Migrar aplicativos Tomcat para aplicativos de contêiner do Azure

Este guia descreve o que você deve saber quando quiser migrar um aplicativo Tomcat existente para ser executado nos Aplicativos de Contêiner do Azure (ACA).

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 movimentaçã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. Você também pode implantar diretamente o conteúdo estático em um aplicativo no plano Azure Spring Apps Enterprise. Para obter mais informações, consulte Implantar arquivos estáticos da Web.

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. Você também pode implantar diretamente o conteúdo estático em um aplicativo no plano Azure Spring Apps Enterprise. Para obter mais informações, consulte Implantar arquivos estáticos da Web.

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 do PersistentManager do Tomcat, como StandardManager ou FileStore, não foram projetadas para uso com uma plataforma distribuída e dimensionada, como o ACA. O ACA pode balancear a carga entre várias instâncias e reiniciar de forma transparente qualquer instância a qualquer momento, portanto, não é recomendável manter o estado mutável em um sistema de arquivos.

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.

Casos especiais

Determinados cenários de produção podem exigir mais alterações ou impor mais limitações. Embora esses cenários sejam raros, é importante verificar se eles não se aplicam ao aplicativo ou estão 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 com dependências do sistema operacional do host, você precisará refatorá-lo para remover essas dependências. Por exemplo, talvez seja necessário substituir qualquer uso de / ou \ em caminhos do sistema de arquivos com File.Separator ou Paths.get.

Determinar se MemoryRealm é usado

MemoryRealm requer um arquivo XML persistente. No ACA, você precisará adicionar esse arquivo à imagem do contêiner ou carregá-lo no armazenamento compartilhado disponibilizado para contêineres. (Para obter mais informações, consulte o Seção Identificar mecanismo de persistência de sessão.) O pathName parâmetro terá de ser modificado em conformidade.

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.

Teste in-loco

Antes de criar imagens de contêiner, migre seu aplicativo para o JDK e o Tomcat que você pretende usar no ACA. 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

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.

Preparar os artefatos de implantação

Clone o repositório do GitHub de início rápido do Tomcat on Containers. Esse repositório contém arquivos de configuração Dockerfile e Tomcat com muitas otimizações recomendadas. Nas etapas abaixo, descrevemos as modificações que você provavelmente precisará fazer nesses arquivos antes de criar a imagem do contêiner e implantar no ACA.

Adicionar recursos de JNDI

Editar servidor.xml para adicionar os recursos preparados nas etapas de pré-migração, como Fontes de Dados, conforme mostrado no exemplo a seguir:

<!-- 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 e carregar a imagem no Registro de Contêiner do Azure (ACR) para uso pelo ACA é usar o az acr build comando. Este comando não requer que o Docker seja instalado no seu computador. Por exemplo, se você tiver o Dockerfile do repositório tomcat-container-quickstart e o pacote de aplicativo petclinic.war no diretório atual, poderá criar a imagem do contêiner no ACR com o seguinte comando:

az acr build \
    --registry $acrName \
    --image "${acrName}.azurecr.io/petclinic:{{.Run.ID}}" 
    --build-arg APP_FILE=petclinic.war \
    --build-arg SERVER_XML=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 usando os comandos a seguir. 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"

# You can now access your application with a browser at http://localhost:8080.

# Sign in to 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 Criar e armazenar imagens de contêiner com o Registro de Contêiner do Azure.

Implantar nos Aplicativos de Contêiner do Azure

O comando a seguir mostra um exemplo de implantação:

az containerapp create \
    --resource-group <RESOURCE_GROUP> \
    --name <APP_NAME> \
    --environment <ENVIRONMENT_NAME> \
    --image <IMAGE_NAME> \
    --target-port 8080 \
    --ingress 'external' \
    --registry-server <REGISTRY_SERVER> \
    --min-replicas 1

Para obter um guia de início rápido mais aprofundado, consulte Guia de início rápido: implantar seu primeiro aplicativo de contêiner.

Após a migração

Agora que você migrou seu aplicativo para o ACA, verifique 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.

Recomendaçõ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. Para obter mais informações, consulte Práticas recomendadas para continuidade de negócios e recuperação de desastres no Serviço de Kubernetes do Azure (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 monitorar o tamanho do cache de código e adicionar os parâmetros -XX:InitialCodeCacheSize e -XX:ReservedCodeCacheSize a JAVA_OPTS variável no Dockerfile para otimizar ainda mais o desempenho. Para obter mais informações, confira Ajuste do Codecache na documentação Oracle.

  • Considere adicionar as regras de alerta e os grupos de ações do Azure Monitor para detectar e abordar as condições anormais rapidamente.

  • Considere replicar a implantação de Aplicativos de Contêiner do Azure em outra região para menor latência e maior confiabilidade e tolerância a falhas. Use o Gerenciador de Tráfego do Azure para balancear a carga entre implantações ou o Azure Front Door para adicionar o descarregamento de SSL e o firewall do aplicativo Web com proteção contra DDoS.

  • Se a replicação geográfica não for necessária, considere adicionar um Gateway de Aplicativo do Azure para adicionar o descarregamento de SSL e o Firewall do aplicativo Web com proteção contra DDoS.