Migración de aplicaciones de Tomcat a Azure Container Apps

En esta guía se describe lo que debe tener en cuenta cuando quiera migrar una aplicación existente de Tomcat para que se ejecute en Azure Container Apps (ACA).

Antes de la migración

Para asegurarse de que la migración se realiza correctamente, antes de empezar, complete los pasos de evaluación e inventario descritos en las secciones siguientes.

Recursos externos de inventario

Los recursos externos, tales como los orígenes de datos, los agentes de mensajes JMS y otros, se insertan a través de la interfaz de directorio y nomenclatura de Java (JNDI). Algunos de estos recursos pueden requerir una migración o reconfiguración.

Dentro de la aplicación

Inspeccione el archivo META-INF/context.xml. Busque elementos <Resource> dentro del elemento <Context>.

En los servidores de aplicaciones

Inspeccione los archivos $CATALINA_BASE/conf/context.xml y $CATALINA_BASE/conf/server.xml, así como los archivos .xml que se encuentran en los directorios $CATALINA_BASE/conf/[nombreDelMotor]/[nombreDelHost].

En los archivos context.xml, los recursos de JNDI se describen con los elementos <Resource> que están dentro del elemento <Context> de nivel superior.

En los archivos server.xml, los recursos de JNDI se describen con los elementos <Resource> que están dentro del elemento <GlobalNamingResources>.

Orígenes de datos

Los orígenes de datos son recursos de JNDI con el atributo type establecido en javax.sql.DataSource. Para cada origen de datos, documente la siguiente información:

  • ¿Cuál es el nombre del origen de datos?
  • ¿Cuál es la configuración del grupo de conexiones?
  • ¿Dónde puedo encontrar el archivo JAR del controlador JDBC?

Para más información, consulte los artículos de procedimientos de los orígenes de datos JNDI en la documentación de Tomcat.

Todos los demás recursos externos

No es factible documentar todas las dependencias externas posibles en esta guía. Es responsabilidad del equipo comprobar que puede cumplir todas las dependencias externas de la aplicación después de la migración.

Secretos de inventario

Contraseñas y cadenas seguras

Compruebe las cadenas secretas y las contraseñas en todas las propiedades y los archivos de configuración de los servidores de producción. Asegúrese de comprobar los archivos server.xml y context.xml en $CATALINA_BASE/conf. También puede encontrar archivos de configuración que contengan contraseñas o credenciales dentro de la aplicación. Estos pueden ser archivos META-INF/context.xml y, para las aplicaciones de Spring Boot, archivos application.properties o application.yml.

Determinación de si se usa el sistema de archivos y cómo

Para usar el sistema de archivos en el servidor de aplicaciones será necesario cambiar la configuración o, en raras ocasiones, la arquitectura. Puede identificar algunos o todos los escenarios siguientes.

Contenido estático de solo lectura

Si su aplicación actualmente sirve contenido estático, necesitará una ubicación alternativa para él. Quizás quiera considerar la posibilidad de mover el contenido estático a Azure Blob Storage y agregar Azure CDN para tener descargas de alta velocidad globalmente. Para más información, consulte Hospedaje de sitios web estáticos en Azure Storage e Inicio rápido: Integración de una cuenta de una instancia de Azure Storage con Azure CDN. También puede implementar directamente el contenido estático en una aplicación en el plan Enterprise de Azure Spring Apps. Para obtener más información, consulte Implementación de archivos estáticos web.

Contenido estático publicado dinámicamente

Si su aplicación permite que haya contenido estático que la aplicación carga o produce, pero que es inmutable una vez creado, puede usar Azure Blob Storage y Azure CDN con una función de Azure para controlar las cargas y la actualización de la red CDN. Hemos proporcionado una implementación de ejemplo para su uso en Cargar y carga previa en CDN de contenido estático con Azure Functions. También puede implementar directamente el contenido estático en una aplicación en el plan Enterprise de Azure Spring Apps. Para obtener más información, consulte Implementación de archivos estáticos web.

Identificación del mecanismo de persistencia de sesión

Para identificar el administrador de persistencia de sesión que se está usando, inspeccione los archivos context.xml de la aplicación y la configuración de Tomcat. Busque el elemento <Manager> y, a continuación, anote el valor del atributo className.

Las implementaciones integradas de PersistentManager de Tomcat, como StandardManager o FileStore , no están diseñadas para su uso con una plataforma distribuida y escalada como ACA. ACA puede equilibrar la carga entre varias instancias y reiniciar de forma transparente cualquier instancia en cualquier momento, por lo que no se recomienda conservar el estado mutable en un sistema de archivos.

Si se necesita la persistencia de la sesión, deberá usar una implementación de PersistentManager alternativa que escribirá en un almacén de datos externo, como VMware Tanzu Session Manager con Redis Cache.

Casos especiales

Algunos escenarios de producción pueden requerir más cambios o imponer más limitaciones. Aunque estos escenarios no son frecuentes, es importante asegurarse de que no son aplicables a la aplicación o que se han resuelto correctamente.

Determinación de si la aplicación se basa en trabajos programados

Los trabajos programados, como las tareas del programador de Quartz o los trabajos de cron, no se pueden usar con implementaciones de Tomcat en contenedor. Si la aplicación se escala horizontalmente, un trabajo programado se podría ejecutar más de una vez por cada período programado. Esta situación puede tener consecuencias no deseadas.

Haga un inventario de todos los trabajos programados, dentro o fuera del servidor de aplicaciones.

Determinación de si la aplicación contiene código específico del sistema operativo

Si la aplicación contiene código con dependencias en el sistema operativo host, deberá refactorizarla para quitar esas dependencias. Por ejemplo, puede que necesite reemplazar el uso de / o \ en las rutas de acceso del sistema de archivos por File.Separator o Paths.get.

Determinación de si se usa MemoryRealm

MemoryRealm requiere un archivo XML persistente. En ACA, deberá agregar este archivo a la imagen de contenedor o cargarlo en el almacenamiento compartido que está disponible para los contenedores. (Para obtener más información, consulte Sección Identificar el mecanismo de persistencia de sesión). El pathName parámetro tendrá que modificarse en consecuencia.

Para determinar si MemoryRealm se usa actualmente, inspeccione los archivos server.xml y context.xml y busque elementos <Realm> en los que el atributo className esté establecido en org.apache.catalina.realm.MemoryRealm.

Pruebas en contexto

Antes de crear imágenes de contenedor, migre la aplicación al JDK y Tomcat que quiere usar en ACA. Pruebe la aplicación exhaustivamente para garantizar su compatibilidad y rendimiento.

Parametrización de la configuración

En la migración previa, es probable que haya identificado secretos y dependencias externas, como orígenes de bits, en los archivos server.xml y context.xml. En cada elemento identificado, reemplace los nombres de usuario, contraseñas, cadenas de conexión o direcciones URL por una variable de entorno.

Por ejemplo, supongamos que el archivo context.xml contiene el siguiente 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$$"
/>

En este caso, podría cambiarlo como se muestra en el ejemplo siguiente:

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

Migración

Nota:

Algunas implementaciones de Tomcat pueden tener varias aplicaciones que se ejecutan en un solo servidor de Tomcat. Si este es el caso de su implementación, es muy recomendable ejecutar cada aplicación en un pod independiente. Esto le permite optimizar el uso de recursos para cada aplicación a la vez que minimiza la complejidad y el acoplamiento.

Preparación de los artefactos de implementación

Clone el repositorio de GitHub de inicio rápido de Tomcat on Containers. Este repositorio contiene archivos de configuración dockerfile y Tomcat con muchas optimizaciones recomendadas. En los pasos siguientes, es probable que tenga que realizar modificaciones en estos archivos antes de compilar la imagen de contenedor e implementarla en ACA.

Adición de recursos de JNDI

Edite server.xml para agregar los recursos que preparó en los pasos previos a la migración, como orígenes de datos, como se muestra en el ejemplo siguiente:

<!-- 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 más instrucciones sobre orígenes de datos, consulte las siguientes secciones de los artículos de procedimientos de los orígenes de datos JNDI en la documentación de Tomcat:

Compilación e inserción de la imagen

La manera más sencilla de compilar y cargar la imagen en Azure Container Registry (ACR) para que la use ACA es usar el az acr build comando . Este comando no requiere que Docker esté instalado en el equipo. Por ejemplo, si tiene el Dockerfile desde el repositorio tomcat-container-quickstart y el paquete de aplicación pet clinic.war en el directorio actual, puede compilar la imagen de contenedor en ACR con el siguiente 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 .

Puede omitir el parámetro --build-arg APP_FILE... si el archivo WAR se llama ROOT.war. Puede omitir el parámetro --build-arg SERVER_XML... si el archivo XML del servidor se llama server.xml. Ambos archivos deben estar en el mismo directorio que el archivo Dockerfile.

Como alternativa, puede usar la CLI de Docker para compilar la imagen localmente mediante los siguientes comandos. Este enfoque puede simplificar las pruebas y perfeccionar la imagen antes de la implementación inicial en ACR. Sin embargo, requiere instalar la CLI de Docker y el demonio de Docker para ejecutarse.

# 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 más información, consulte Compilación y almacenamiento de imágenes de contenedor con Azure Container Registry.

Implementación en Azure Container Apps

El comando siguiente muestra un ejemplo de implementación:

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 obtener una guía de inicio rápido más detallada, consulte Inicio rápido: Implementación de la primera aplicación de contenedor.

Después de la migración

Ahora que ha migrado la aplicación a ACA, debe comprobar que funciona según lo previsto. Una vez hecho esto, tenemos algunas recomendaciones que pueden hacer que su aplicación sea más nativa de la nube.

Recomendaciones

  • Diseñe e implemente una estrategia de continuidad empresarial y recuperación ante desastres. En el caso de las aplicaciones críticas, considere la posibilidad de usar una arquitectura de implementación de varias regiones. Para más información, consulte Procedimientos recomendados para la continuidad empresarial y la recuperación ante desastres en Azure Kubernetes Service (AKS).

  • Evalúe los elementos del archivo logging.properties. Considere la posibilidad de eliminar o reducir parte de la salida del registro para mejorar el rendimiento.

  • Considere la posibilidad de supervisar el tamaño de la caché de código y agregar los parámetros -XX:InitialCodeCacheSize y -XX:ReservedCodeCacheSize a la JAVA_OPTS variable del Dockerfile para optimizar aún más el rendimiento. Para más información, consulte cómo ajustar Codecache en la documentación de Oracle.

  • Considere la posibilidad de agregar reglas de alerta y grupos de acciones de Azure Monitor para detectar y resolver rápidamente las condiciones anómalas.

  • Considere la posibilidad de replicar la implementación de Azure Container Apps en otra región para una menor latencia y mayor confiabilidad y tolerancia a errores. Use Azure Traffic Manager para equilibrar la carga entre las implementaciones, o use Azure Front Door para agregar la descarga de SSL y un firewall de aplicaciones web con protección contra DDoS.

  • Si no es necesaria la replicación geográfica, considere la posibilidad de agregar una puerta de enlace de aplicación de Azure para agregar la descarga SSL y un firewall de aplicaciones web con protección contra DDoS.