Migrar aplicativos Tomcat para contêineres no AKS (Serviço de Kubernetes do Azure)
Este guia descreve as informações das quais você deve estar ciente quando deseja migrar um aplicativo Tomcat existente para ser executado em um contêiner do AKS (Serviço de Kubernetes do Azure).
Pré-migração
Antes de tudo, para garantir uma migração bem-sucedida, conclua as etapas de avaliação e de inventário descritas nas seções a seguir.
Recursos externos de inventário
Recursos externos, como fontes de dados, agentes de mensagem JMS e outros, são injetados por meio de JNDI (Interface de Nomenclatura e Diretório do Java). Alguns desses recursos podem exigir migração ou reconfiguração.
Dentro de seu aplicativo
Inspecione o arquivo META-INF/context.xml. Procure elementos de <Resource>
dentro do elemento <Context>
.
Nos servidores de aplicativos
Inspecione os arquivos $CATALINA_BASE/conf/context.xml e $CATALINA_BASE/conf/server.xml, bem como os arquivos .xml encontrados nos diretórios $CATALINA_BASE/conf/[nome-do-mecanismo]/[nome-do-host].
Em arquivos context.xml, os recursos de JNDI serão descritos pelos elementos <Resource>
dentro do elemento <Context>
de nível superior.
Em arquivos server.xml, os recursos de JNDI serão descritos pelos elementos <Resource>
dentro do elemento <GlobalNamingResources>
.
Fontes de dados
Fontes de dados são recursos de JNDI com o atributo type
definido como javax.sql.DataSource
. Para cada fonte de dados, documente as seguintes informações:
- Qual é o nome da fonte de dados?
- Qual é a configuração do pool de conexões?
- Onde posso encontrar o arquivo JAR do driver JDBC?
Para obter mais informações, consulte Instruções de fonte de dados JNDI na documentação do Tomcat.
Todos os outros recursos externos
Não é possível documentar todas as dependências externas possíveis neste guia. É responsabilidade da sua equipe verificar se você pode atender a todas as dependências externas de seu aplicativo após a migração.
Segredos de inventário
Senhas e cadeias de caracteres seguras
Verifique todas as propriedades e os arquivos de configuração nos servidores de produção para quaisquer senhas e cadeias de caracteres secretas. É necessário verificar server.xml e context.xml em $CATALINA_BASE/conf. Você também pode encontrar arquivos de configuração que contenham senhas ou credenciais dentro de seu aplicativo. Eles podem incluir META-INF/context.xml e, para aplicativos Spring boot, arquivos application.properties ou application.yml.
Determinar se e como o sistema de arquivos é usado
Qualquer uso do sistema de arquivos no servidor de aplicativos exigirá reconfiguração ou, em casos raros, alterações de arquitetura. Você pode identificar alguns ou todos os cenários a seguir.
Conteúdo estático somente leitura
Se seu aplicativo estiver servindo conteúdo estático no momento, você precisará de um local alternativo para ele. Talvez você queira considerar a migração de conteúdo estático para o Armazenamento de Blobs do Azure e a adição da CDN do Azure para downloads extremamente rápidos, globalmente. Para obter mais informações, confira Hospedagem de site estático no Armazenamento do Microsoft Azure e Início rápido: Integrar uma conta de armazenamento do Azure à CDN do Azure.
Conteúdo estático publicado dinamicamente
Se o aplicativo permitir conteúdo estático que é carregado/produzido pelo aplicativo, mas não puder ser alterado após sua criação, você poderá usar o Armazenamento de Blobs do Azure e a CDN do Azure, conforme descrito acima, com uma Função do Azure para lidar com uploads e atualização de CDN. Fornecemos uma implementação de exemplo para seu uso em Carregar conteúdo estático e fazer o pré-carregamento desse conteúdo pela CDN com o Azure Functions.
Conteúdo dinâmico ou interno
Para arquivos que são frequentemente escritos e lidos pelo aplicativo (como arquivos de dados temporários) ou arquivos estáticos que são visíveis somente para o aplicativo, você pode montar compartilhamentos do Armazenamento do Azure como volumes persistentes. Para obter mais informações, confira Criar e usar um volume com os Arquivos do Azure no AKS (Serviço de Kubernetes do Azure).
Identificar o mecanismo de persistência da sessão
Para identificar o gerenciador de persistência de sessão em uso, inspecione os arquivos context.xml em seu aplicativo e a configuração do Tomcat. Procure o elemento <Manager>
e observe o valor do atributo className
.
As implementações internas de PersistentManager do Tomcat, como StandardManager ou FileStore, não são projetadas para uso com uma plataforma distribuída e dimensionada como o Kubernetes. O AKS pode balancear a carga entre vários pods e reiniciar de forma transparente qualquer Pod a qualquer momento, então a persistência de um estado mutável para um sistema de arquivos não é recomendada.
Se a persistência da sessão for necessária, você precisará usar uma implementação alternativa de PersistentManager
que será gravada em um armazenamento de dados externo, como o VMware Tanzu Session Manager com o Cache Redis. Para obter mais informações, confira Usar o Redis como um cache de sessão com o Tomcat.
Casos especiais
Determinados cenários de produção podem exigir alterações adicionais ou impor limitações adicionais. Embora esses cenários possam ser infrequentes, é importante garantir que eles não se apliquem ao seu aplicativo ou que sejam resolvidos corretamente.
Determinar se o aplicativo depende de trabalhos agendados
Trabalhos agendados, como tarefas do Agendador do Quartz ou trabalhos cron, não podem ser usados com implantações do Tomcat em contêineres. Se o aplicativo for escalado horizontalmente, um trabalho agendado poderá ser executado mais de uma vez por período agendado. Essa situação pode levar a consequências indesejadas.
Inventarie quaisquer trabalhos agendados, dentro ou fora do servidor de aplicativos.
Determinar se o aplicativo contém código específico do sistema operacional
Se seu aplicativo contiver qualquer código que esteja acomodando o sistema operacional no qual seu aplicativo estiver sendo executado, o aplicativo precisará ser refatorado para NÃO depender do sistema operacional subjacente. Por exemplo, qualquer uso de /
ou \
em caminhos de sistema de arquivos podem precisar ser substituídos por File.Separator
ou Path.get
.
Determinar se MemoryRealm é usado
MemoryRealm requer um arquivo XML persistente. No Kubernetes, esse arquivo precisará ser adicionado à imagem de contêiner ou carregado no armazenamento compartilhado disponibilizado para os contêineres. O parâmetro pathName
precisará ser modificado de acordo.
Para determinar se MemoryRealm
está sendo usado no momento, inspecione os arquivos server.xml e context.xml e pesquise por elementos <Realm>
em que o atributo className
está definido como org.apache.catalina.realm.MemoryRealm
.
Determinar se o acompanhamento de sessão SSL é usado
Em implantações em contêineres, as sessões SSL normalmente são descarregadas fora do contêiner do aplicativo, geralmente pelo controlador de entrada. Se o aplicativo exigir acompanhamento de sessão SSL, verifique se o tráfego SSL é passado diretamente para o contêiner do aplicativo.
Determine se AccessLogValve é ou não usado
Se AccessLogValve for usado, o parâmetro directory
deverá ser definido para um compartilhamento dos Arquivos do Azure montado ou um dos respectivos subdiretórios.
Teste in-loco
Antes de criar imagens de contêiner, migre seu aplicativo para o JDK e o Tomcat que você pretende usar no AKS. Teste seu aplicativo cuidadosamente para garantir a compatibilidade e o desempenho.
Parametrizar a configuração
Na pré-migração, você provavelmente terá identificado segredos e dependências externas, como fontes de dados, nos arquivos server.xml e context.xml. Para cada item identificado assim, substitua qualquer nome de usuário, senha, cadeia de conexão ou URL por uma variável de ambiente.
Por exemplo, suponha que o arquivo 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$$"
/>
Nesse caso, você poderia alterá-lo conforme mostrado no exemplo a seguir:
<Resource
name="jdbc/dbconnection"
type="javax.sql.DataSource"
url="${postgresdb.connectionString}"
driverClassName="org.postgresql.Driver"
username="${postgresdb.username}"
password="${postgresdb.password}"
/>
Migração
Com exceção da primeira etapa ("Provisionar registro de contêiner e AKS"), recomendamos que você siga as etapas abaixo individualmente para cada aplicativo (arquivo WAR) que deseje migrar.
Observação
Algumas implantações do Tomcat podem ter vários aplicativos em execução em um único servidor Tomcat. Se esse for o caso em sua implantação, será altamente recomendável executar cada aplicativo em um pod separado. Isso permite que você otimize a utilização de recursos para cada aplicativo, minimizando a complexidade e o acoplamento.
Provisionar registro de contêiner e AKS
Crie um registro de contêiner e um cluster do Kubernetes do Azure cuja entidade de serviço tenha a função de Leitor no registro. Verifique se você escolheu o modelo de rede apropriado 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 artefatos de implantação
Clone o repositório GitHub do início rápido do Tomcat em contêineres. Ele contém um Dockerfile e arquivos de configuração do Tomcat com várias otimizações recomendadas. Nas etapas abaixo, descrevemos as modificações que você provavelmente precisará fazer nesses arquivos antes de criar a imagem de contêiner e implantá-la no AKS.
Abrir portas para clustering, se necessário
Se você pretende usar o clustering de Tomcat no AKS, verifique se os intervalos de portas necessários estão expostos no Dockerfile. Para especificar o endereço IP do servidor em server.xml, é necessário usar um valor de uma variável que é inicializada na inicialização do contêiner para o endereço IP do pod.
Como alternativa, o estado de sessão pode ser persistido em um local alternativo para estar disponível entre as réplicas.
Para determinar se seu aplicativo usa clustering, procure o elemento <Cluster>
dentro dos elementos <Host>
ou <Engine>
no arquivo server.xml.
Adicionar recursos de JNDI
Edite server.xml para adicionar os recursos que você preparou nas etapas de pré-migração, como fontes 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 fonte de dados, consulte as seções a seguir das Instruções de fonte de dados JNDI na documentação do Tomcat:
Criar imagem e enviá-la por push
A maneira mais simples de criar a imagem e carregá-la no ACR (Registro de Contêiner do Azure) para uso pelo AKS é usar o comando az acr build
. Este comando não requer que o Docker seja instalado no seu computador. Por exemplo, se você tiver o Dockerfile acima e o pacote de aplicativos petclinic.war no diretório atual, poderá criar a imagem de contêiner no ACR com uma etapa:
az acr build \
--image "${acrName}.azurecr.io/petclinic:{{.Run.ID}}" \
--registry $acrName \
--build-arg APP_FILE=petclinic.war \
--build-arg=prod.server.xml .
Você poderá omitir o parâmetro --build-arg APP_FILE...
se o seu arquivo WAR for nomeado ROOT.war. Você poderá omitir o parâmetro --build-arg SERVER_XML...
se o seu arquivo XML do servidor for nomeado server.xml. Ambos os arquivos precisam estar no mesmo diretório que o Dockerfile.
Como alternativa, você pode usar a CLI do Docker para criar a imagem localmente. Essa abordagem pode simplificar o teste e refinar a imagem antes da implantação inicial no ACR. No entanto, ela requer que a CLI do Docker seja 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 do Learn para Criar e armazenar imagens de contêiner no Azure.
Provisionar um endereço IP público
Se quiser que seu aplicativo esteja acessível de fora de suas redes internas ou virtuais, você precisará de um endereço IP estático público. Esse endereço IP deve ser provisionado dentro do grupo de recursos do nó do 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}."
Implantar no AKS
Crie e aplique seus arquivos YAML do Kubernetes. Se você estiver criando um balanceador de carga externo (seja para seu aplicativo ou para um controlador de entrada), será necessário fornecer o endereço IP provisionado na seção anterior como o LoadBalancerIP
.
Inclua parâmetros externos como variáveis de ambiente. Não inclua segredos (como senhas, chaves de API e cadeias de conexão JDBC). Os segredos são abordados na seção Configurar o FlexVolume do KeyVault.
Configurar um armazenamento persistente
Se seu aplicativo exigir armazenamento não volátil, configure um ou mais Volumes Persistentes.
Talvez você queira criar um volume persistente usando os Arquivos do Azure montados no diretório de logs do Tomcat (/tomcat_logs) para manter os logs centralmente. Para obter mais informações, confira Criar e usar dinamicamente um volume persistente com Arquivos do Azure no AKS (Serviço de Kubernetes do Azure).
Configurar FlexVolume do KeyVault
Crie um Azure KeyVault e preencha todos os segredos necessários. Em seguida, configure um FlexVolume do KeyVault para tornar esses segredos acessíveis para pods.
Você precisará modificar o script de inicialização (startup.sh no repositório GitHub Tomcat em Contêineres) para importar os certificados para o repositório de chaves local no contêiner.
Migrar os trabalhos agendados
Para executar trabalhos agendados em seu cluster do AKS, defina Trabalhos do Cron conforme necessário.
Após a migração
Agora que você migrou seu aplicativo para o AKS, você deve verificar se ele funciona conforme o esperado. Depois de fazer isso, temos algumas recomendações para você que podem tornar seu aplicativo mais nativo da nuvem.
Considere adicionar um nome DNS ao endereço IP alocado ao controlador de entrada ou ao balanceador de carga do aplicativo. Para obter mais informações, consulte Usar o TLS com um controlador de entrada no AKS (Serviço de Kubernetes do Azure).
Considere adicionar gráficos HELM ao aplicativo. Um gráfico do Helm permite que você parametrize a implantação do aplicativo para uso e personalização por um conjunto mais diversificado de clientes.
Crie e implemente uma estratégia de DevOps. Para manter a confiabilidade, aumentando simultaneamente a velocidade de desenvolvimento, considere automatizar implantações e testar com Azure Pipelines.
Habilite o Monitoramento do Azure para o cluster para permitir a coleta de logs de contêiner, a utilização de acompanhamento e assim por diante.
Considere a possibilidade de expor métricas específicas do aplicativo por meio do Prometheus. O Prometheus é uma estrutura de métricas open-source amplamente adotada na comunidade do Kubernetes. Você pode configurar o recorte de métricas do Prometheus no Azure Monitor, em vez de hospedar seu próprio servidor do Prometheus para habilitar a agregação de métricas de seus aplicativos e resposta automatizada para condições anormais ou escalonamento dessas condições.
Criar a implementar uma estratégia de continuidade dos negócios e recuperação de desastre. Para aplicativos críticos, considere a possibilidade de usar uma arquitetura de implantação em várias regiões.
Examine a política de suporte a versão do Kubernetes. É sua responsabilidade continuar atualizando seu cluster do AKS para garantir que você esteja sempre executando uma versão compatível.
Faça com que todos os membros da equipe responsáveis pela administração de clusters e pelo desenvolvimento de aplicativos examinem as práticas recomendadas do AKS.
Avalie os itens no arquivo logging.properties. Considere a possibilidade de eliminar ou reduzir parte da saída de log para melhorar o desempenho.
Considere a possibilidade de monitorar o tamanho do cache de código e de adicionar os parâmetros
-XX:InitialCodeCacheSize
e-XX:ReservedCodeCacheSize
à variávelJAVA_OPTS
no Dockerfile para otimizar ainda mais o desempenho.