Partilhar via


Migrar aplicações Tomcat para contentores no Azure Kubernetes Service

Este guia descreve de que deve estar ciente quando quer migrar uma aplicação Tomcat já existente para a executar num contentor do Azure Kubernetes Service (AKS).

Pré-migração

Para garantir uma migração bem-sucedida, antes de começar, conclua as etapas de avaliação e inventário descritas nas seções a seguir.

Inventariar os recursos externos

Os recursos externos, como origens de dados, mediadores de mensagens JMS, entre outros, são injetados através de Java Naming and Directory Interface (JNDI). Alguns desses recursos podem precisar de migração ou reconfiguração.

Na aplicação

Inspecione o ficheiro META-INF/context.xml. Procure elementos <Resource> dentro do elemento <Context>.

No servidor ou servidores da aplicação

Inspecione os ficheiros $CATALINA_BASE/conf/context.xml e $CATALINA_BASE/conf/server.xml, bem como os ficheiros .xml e localizados nos diretórios $CATALINA_BASE/conf/[engine-name]/[host-name].

Nos ficheiros context.xml, os recursos JNDI serão descritos pelos elementos <Resource> dentro do elemento <Context> de nível superior.

Nos ficheiros server.xml, os recursos JNDI serão descritos pelos elementos <Resource> dentro do elemento <GlobalNamingResources>.

Origens de Dados

Origens de dados e recursos JNDI com o atributo type definido como javax.sql.DataSource. Documente a seguinte informação de cada origem de dados:

  • Qual é o nome da origem de dados?
  • Qual é a configuração do conjunto de ligações?
  • Onde posso obter o ficheiro JAR do controlador JDBC?

Para obter mais informações, veja o MANUAL DE INSTRUÇÕES da Origem de Dados do JNDI na documentação do Tomcat.

Todos os outros recursos externos

Não é exequível documentar todas as dependências externas possíveis neste guia. Cabe à sua equipa verificar que pode satisfazer todas as dependências externas da sua aplicação após a migração.

Inventariar segredos

Palavras-passe e cadeias protegidas

Procure cadeias de segredos e palavras-passe nas propriedades e nos ficheiros de configuração do servidor ou servidores de produção. Não se esqueça de verificar server.xml e context.xml em $CATALINA_BASE/conf. Também poderá encontrar ficheiros de configuração com palavras-passe ou credenciais dentro da aplicação. Esses ficheiros podem incluir META-INF/context.xml e, para aplicações Spring Boot, application.properties ou application.yml.

Determinar se e como é que o sistema de ficheiros é utilizado

Qualquer utilização do sistema de ficheiros no servidor de aplicações irá exigir uma reconfiguração ou, em casos raros, alterações da arquitetura. Poderá identificar alguns ou todos os cenários seguintes.

Conteúdo estático só de leitura

Se a sua aplicação servir conteúdo estático atualmente, precisa de uma localização alternativa para o mesmo. Pode considerar mover o conteúdo estático para o Armazenamento de Blobs do Azure e adicionar a CDN do Azure para obter transferências super-rápidas a nível global. Para obter mais informações, consulte Hospedagem de site estático no Armazenamento do Azure e Guia de início rápido: integrar uma conta de armazenamento do Azure com a CDN do Azure. Você também pode implantar diretamente o conteúdo estático em um aplicativo no plano do Azure Spring Apps Enterprise. Para obter mais informações, consulte Implantar arquivos estáticos da Web.

Conteúdo estático publicado dinamicamente

Se a sua aplicação permitir conteúdo estático carregado/produzido pela mesma, mas que é imutável após a criação, pode utilizar o Armazenamento de Blobs do Azure e a CDN do Azure conforme descrito acima, com uma função das Funções do Azure que lide com os carregamentos e as atualizações da CDN. Disponibilizamos uma implementação de exemplo que pode utilizar, em Uploading and CDN-preloading static content with Azure Functions (Carregamento e pré-carregamento da CDN de conteúdo estático com as Funções do Azure). Você também pode implantar diretamente o conteúdo estático em um aplicativo no plano do Azure Spring Apps Enterprise. Para obter mais informações, consulte Implantar arquivos estáticos da Web.

Conteúdo dinâmico ou interno

Para os ficheiros que são frequentemente escritos e lidos pela sua aplicação (tais como ficheiros de dados temporários) ou os ficheiros estáticos que só estão visíveis para a sua aplicação, pode montar partilhas do Armazenamento do Microsoft Azure sob a forma de volumes persistentes. Para obter mais informações, veja Criar e utilizar de forma dinâmica um volume persistente com Ficheiros do Azure no Azure Kubernetes Service.

Identificar o mecanismo de persistência de sessão

Para identificar o gestor de persistência de sessão que está a ser utilizado, inspecione os ficheiros context.xml que se encontram na sua aplicação e a configuração do Tomcat. Procure o elemento <Manager> e, em seguida, veja o valor do atributo className.

As implementações PersistentManager integradas do Tomcat, tais como StandardManager ou FileStore, não foram concebidas para serem utilizadas com uma plataforma distribuída e dimensionada como o Kubernetes. O AKS poderá balancear a carga entre vários pods e reiniciar de forma transparente qualquer pod em qualquer momento. Não se recomenda que um sistema de ficheiros permaneça num estado mutável.

Se a persistência da sessão for necessária, você precisará usar uma implementação alternativa PersistentManager que gravará em um armazenamento de dados externo, como o VMware Tanzu Session Manager com Cache Redis. Para obter mais informações, veja Utilizar Redis como cache da sessão com o Tomcat.

Casos especiais

Alguns cenários de produção poderão exigir alterações adicionais ou impor mais limitações. Embora estes cenários possam ser pouco frequentes, é importante garantir que não são aplicáveis à sua aplicação ou que são corretamente resolvidos.

Determinar se a aplicação depende de tarefas agendadas

As tarefas agendadas, tais como tarefas do Quartz Scheduler ou do Cron, não podem ser utilizadas com implementações Tomcat em contentor. Se a sua aplicação estiver ampliada, uma tarefa agendada pode ser executada mais de uma vez por período agendado. Esta situação pode provocar consequências não intencionais.

Faça o inventário de todas as tarefas agendadas, dentro ou fora do servidor de aplicações.

Determinar se a aplicação contem código de SO específico

Se a sua aplicação contiver código que esteja a acomodar o SO no qual a sua aplicação está a ser executada, a sua aplicação tem de ser refatorizada para NÃO depender do SO subjacente. Por exemplo, qualquer utilização de / ou \ em caminhos do sistema de ficheiros poderá ter de ser substituída por File.Separator ou Path.get.

Determinar se o MemoryRealm está a ser utilizado

O MemoryRealm necessita de um ficheiro XML persistente. No Kubernetes, este ficheiro terá de ser adicionado à imagem de contentor ou carregado para armazenamento partilhado que é disponibilizado aos contentores. O parâmetro pathName terá de ser modificado em conformidade.

Para determinar se o MemoryRealm está a ser utilizado atualmente, inspecione os seus ficheiros server.xml e context.xml e procure elementos <Realm> nos quais o atributo className está definido como org.apache.catalina.realm.MemoryRealm.

Determinar se o controlo de sessões de SSL está a ser utilizado

Em implementações em contentor, as sessões de SSL costumam ser descarregadas fora do contentor da aplicação, geralmente pelo controlador de entrada. Se a sua aplicação necessitar de controlo de sessões de SSL, certifique-se de que o tráfego de SSL é transmitido diretamente através do contentor da aplicação.

Determinar se o AccessLogValve está a ser utilizado

Se o AccessLogValve estiver a ser utilizado, o parâmetro directory deve ser definido como uma partilha de Ficheiros do Azure montada ou um dos seus subdiretórios.

Testes no local

Antes de criar imagens de contentor, migre a sua aplicação para o JDK e Tomcat que pretende utilizar no AKS. Teste a sua aplicação de forma minuciosa para garantir a compatibilidade e o desempenho.

Parametrizar a configuração

É provável que na fase de pré-migração tenha identificado segredos e dependências externas, tais como origens de dados, nos ficheiros server.xml e context.xml. Para cada item identificado como tal, substitua todos os nomes de utilizador, palavras-passe, cadeias de ligação ou URLs por uma variável de ambiente.

Por exemplo, imagine que o ficheiro context.xml contém o seguinte elemento:

<Resource
    name="jdbc/dbconnection"
    type="javax.sql.DataSource"
    url="jdbc:postgresql://postgresdb.contoso.com/wickedsecret?ssl=true"
    driverClassName="org.postgresql.Driver"
    username="postgres"
    password="t00secure2gue$$"
/>

Neste caso, pode mudá-lo conforme mostrado no seguinte exemplo:

<Resource
    name="jdbc/dbconnection"
    type="javax.sql.DataSource"
    url="${postgresdb.connectionString}"
    driverClassName="org.postgresql.Driver"
    username="${postgresdb.username}"
    password="${postgresdb.password}"
/>

Migração

Excetuando o primeiro passo ("Aprovisionar o registo de contentor e o AKS"), recomendamos que siga individualmente os passos abaixo para cada aplicação (ficheiro WAR) que pretenda migrar.

Nota

Algumas implementações do Tomcat poderão ter múltiplas aplicações em execução num único servidor Tomcat. Se for este o caso na sua implementação, recomendamos vivamente que execute cada aplicação num pod separado. Isto permite-lhe otimizar a utilização de recursos para cada aplicação e, ao mesmo tempo, minimizar a complexidade e o acoplamento.

Aprovisionar o registo de contentor e o AKS

Crie um registo de contentor e um cluster do Azure Kubernetes cujo Principal de Serviço tenha a função de Leitor no registo. Certifique-se de que escolhe o modelo de rede adequado para os requisitos de rede do seu cluster.

az group create \
    --resource-group $resourceGroup \
    --location eastus
az acr create \
    --resource-group $resourceGroup \
    --name $acrName \
    --sku Standard
az aks create \
    --resource-group $resourceGroup \
    --name $aksName \
    --attach-acr $acrName \
    --network-plugin azure

Preparar os artefactos de implementação

Clone o repositório do GitHub de Início Rápido do Tomcat em Contentores. Este repositório contém ficheiros de configuração Dockerfile e Tomcat com várias otimizações recomendadas. Nos passos abaixo, delineamos modificações que provavelmente terá de fazer a estes ficheiros antes de criar a imagem de contentor e de proceder à implementação no AKS.

Abrir portas para clustering se for necessário

Se quiser utilizar o Clustering do Tomcat no AKS, certifique-se de que os intervalos de portas necessários estão expostos no Dockerfile. Para especificar o endereço IP do servidor no ficheiro server.xml, certifique-se de que utiliza um valor de uma variável que é inicializada aquando do arranque do contentor para o endereço IP do pod.

Em alternativa, o estado de sessão pode ser mantido para uma localização alternativa de forma a estar disponível nas réplicas.

Para determinar se a sua aplicação utiliza clustering, procure o elemento <Cluster> dentro dos elementos <Host> ou <Engine> no ficheiro server.xml.

Adicionar recursos JNDI

Edite o ficheiro server.xml para adicionar os recursos que preparou nos passos de pré-migração, tais como origens de dados.

Por exemplo:

<!-- Global JNDI resources
      Documentation at /docs/jndi-resources-howto.html
-->
<GlobalNamingResources>
    <!-- Editable user database that can also be used by
         UserDatabaseRealm to authenticate users
    -->
    <Resource name="UserDatabase" auth="Container"
              type="org.apache.catalina.UserDatabase"
              description="User database that can be updated and saved"
              factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
              pathname="conf/tomcat-users.xml"
               />

    <!-- Migrated datasources here: -->
    <Resource
        name="jdbc/dbconnection"
        type="javax.sql.DataSource"
        url="${postgresdb.connectionString}"
        driverClassName="org.postgresql.Driver"
        username="${postgresdb.username}"
        password="${postgresdb.password}"
    />
    <!-- End of migrated datasources -->
</GlobalNamingResources>

Para obter instruções adicionais da origem de dados, veja as seguintes secções do Manual de Instruções da Origem de Dados do JNDI na documentação do Tomcat:

Criar e emitir a imagem

A forma mais simples de criar e carregar a imagem para o Azure Container Registry (ACR) de forma que o AKS a utilize é através da utilização do comando az acr build. Este comando não exige que o Docker esteja instalado no teu computador. Por exemplo, se tiver o Dockerfile acima e o pacote de aplicação petclinic.war no diretório atual, pode criar a imagem de contentor no ACR ao seguir um único passo:

az acr build \
    --image "${acrName}.azurecr.io/petclinic:{{.Run.ID}}" \
    --registry $acrName \
    --build-arg APP_FILE=petclinic.war \
    --build-arg=prod.server.xml .

Pode omitir o parâmetro --build-arg APP_FILE... se o seu ficheiro WAR se chamar ROOT.war. Pode omitir o parâmetro --build-arg SERVER_XML... se o seu ficheiro XML de servidor se chamar server.xml. Estes dois ficheiros têm de estar no mesmo diretório do Dockerfile.

Em alternativa, pode utilizar a CLI do Docker para criar a imagem localmente. Esta abordagem pode simplificar os testes e refinar a imagem antes da implementação inicial no ACR. No entanto, exige que a CLI do Docker esteja instalada e que o daemon do Docker esteja em execução.

# Build the image locally
sudo docker build . --build-arg APP_FILE=petclinic.war -t "${acrName}.azurecr.io/petclinic:1"

# Run the image locally
sudo docker run -d -p 8080:8080 "${acrName}.azurecr.io/petclinic:1"

# Your application can now be accessed with a browser at http://localhost:8080.

# Log into ACR
sudo az acr login --name $acrName

# Push the image to ACR
sudo docker push "${acrName}.azurecr.io/petclinic:1"

Para obter mais informações, consulte o módulo Learn para criar e armazenar imagens de contêiner no Azure.

Aprovisionar um endereço IP público

Se quiser que a sua aplicação seja acessível fora das suas redes internas ou virtuais, será necessário um endereço IP estático público. Este endereço IP deve ser aprovisionado dentro do grupo de recursos do nó de cluster.

export nodeResourceGroup=$(az aks show \
    --resource-group $resourceGroup \
    --name $aksName \
    --query 'nodeResourceGroup' \
    --output tsv)
export publicIp=$(az network public-ip create \
    --resource-group $nodeResourceGroup \
    --name applicationIp \
    --sku Standard \
    --allocation-method Static \
    --query 'publicIp.ipAddress' \
    --output tsv)
echo "Your public IP address is ${publicIp}."

Implementar para AKS

Crie e aplique os seus ficheiros YAML do Kubernetes. Se estiver a criar um balanceador de carga externo (seja na sua aplicação ou num controlador de entrada), certifique-se de que fornece o endereço IP aprovisionado na secção anterior como o LoadBalancerIP.

Inclua parâmetros exteriorizados como variáveis de ambiente. Não inclua segredos (tais como palavras-passe, chaves de API e cadeias de ligação JDBC). Os segredos são abordados na secção Configurar o KeyVault FlexVolume.

Configurar armazenamento persistente

Se a sua aplicação necessitar de armazenamento não volátil, configure um ou mais Volumes Persistentes.

É recomendado que crie um Volume Persistente através de Ficheiros do Azure montados no diretório de registos do Tomcat (/tomcat_logs) para reter os registos centralmente. Para obter mais informações, veja Criar e utilizar de forma dinâmica um volume persistente com Ficheiros do Azure no Azure Kubernetes Service (AKS).

Configurar o FlexVolume do KeyVault

Crie um Azure KeyVault e preencha todos os segredos necessários. Em seguida, configure um KeyVault FlexVolume para tornar esses segredos acessíveis a pods.

Terá de modificar o script de arranque (startup.sh no repositório do GitHub do Tomcat em Contentores) para importar os certificados para o keystore local no contentor.

Migrar trabalhos agendados

Para executar tarefas agendadas no seu cluster do AKS, defina Tarefas do Cron conforme for necessário.

Pós-migração

Agora que já migrou a sua aplicação para o AKS, deve verificar se esta funciona como o esperado. Posto isto, temos algumas recomendações que podem tornar a sua aplicação mais nativa da nuvem.

  • Considere adicionar um nome DNS ao endereço IP alocado ao seu controlador de entrada ou balanceador de carga da aplicação. Para obter mais informações, consulte Criar um controlador de entrada com um endereço IP público estático no AKS.

  • Considere adicionar gráficos HELM para a sua aplicação. Os gráficos Helm permitem-lhe parametrizar a implementação da sua aplicação para que esta seja personalizada e utilizada por um conjunto mais diversificado de clientes.

  • Crie e implemente uma estratégia de DevOps. Para manter a fiabilidade ao mesmo tempo que aumenta a sua velocidade de desenvolvimento, considere automatizar implementações e testar com Pipelines do Azure.

  • Ative a Monitorização do Azure para o cluster de forma a permitir a recolha de registos de contentores, a utilização de controlo, entre outros.

  • Considere expor métricas específicas da aplicação via Prometeu. O Prometheus é uma arquitetura de métricas open-source que é amplamente adotado na comunidade do Kubernetes. Pode configurar métricas Prometheus no Azure Monitor em vez de alojar o seu próprio servidor Prometheus para permitir a agregação de métricas das suas aplicações e a resposta automatizada ou o dimensionamento de condições aberrantes.

  • Crie e implemente uma estratégia de continuidade de negócio e recuperação após desastre. Caso a aplicação seja essencial para a atividade, considere uma arquitetura de implementação multirregiões.

  • Reveja a política de Suporte de Versão do Kubernetes. É da sua responsabilidade continuar a atualizar o seu cluster do AKS para garantir que este está sempre a executar uma versão suportada.

  • Faça com que todos os membros da equipa responsáveis pela administração de clusters e pelo desenvolvimento de aplicações revejam as melhores práticas do AKS pertinentes.

  • Avalie os itens que se encontram no ficheiro logging.properties. Considere eliminar ou reduzir parte das saídas de registo para melhorar o desempenho.

  • Considere monitorizar o tamanho da cache de código e adicionar os parâmetros -XX:InitialCodeCacheSize e -XX:ReservedCodeCacheSize à variável JAVA_OPTS no Dockerfile para otimizar ainda mais o desempenho.