Migrer des applications Tomcat vers Azure Container Apps

Ce guide décrit ce que vous devez savoir quand vous souhaitez migrer une application Tomcat existante à exécuter sur Azure Container Apps (ACA).

Prémigration

Pour garantir la réussite de la migration, avant de commencer, effectuez les étapes d’évaluation et d’inventaire décrites dans les sections suivantes.

Inventorier les ressources externes

Les ressources externes, comme les sources de données, les répartiteurs de messages JMS, etc., sont injectées par le biais de l’interface JNDI (Java Naming and Directory Interface). Certaines de ces ressources peuvent nécessiter une migration ou une reconfiguration.

Au sein de votre application

Examinez le fichier META-INF/context.xml. Recherchez les éléments <Resource> à l’intérieur de l’élément <Context>.

Sur le ou les serveurs d’applications

Examinez les fichiers $CATALINA_BASE/conf/context.xml et $CATALINA_BASE/conf/server.xml, ainsi que les fichiers .xml trouvés dans les répertoires $CATALINA_BASE/conf/[engine-name]/[host-name].

Dans les fichiers context.xml, les ressources JNDI sont décrites par les éléments <Resource> à l’intérieur de l’élément <Context> de niveau supérieur.

Dans les fichiers server.xml, les ressources JNDI sont décrites par les éléments <Resource> à l’intérieur de l’élément <GlobalNamingResources>.

Sources de données

Les sources de données sont des ressources JNDI dont l’attribut type a la valeur javax.sql.DataSource. Pour chaque source de données, réunissez les informations suivantes :

  • Quel est le nom de la source de données ?
  • Quelle est la configuration du pool de connexions ?
  • Où trouver le fichier JAR du pilote JDBC ?

Pour plus d’informations, consultez JNDI Datasource HOW-TO (Guide pratique sur les sources de données JNDI) dans la documentation Tomcat.

Toutes les autres ressources externes

Il n’est pas possible de décrire toutes les dépendances externes possibles dans ce guide. Il incombe à votre équipe de vérifier que vous pouvez satisfaire à toutes les dépendances externes de votre application après la migration.

Inventorier les secrets

Mots de passe et chaînes sécurisées

Recherchez dans l’ensemble des propriétés et fichiers de configuration présents sur les serveurs de production d’éventuels chaînes secrètes et mots de passe. Pensez à vérifier server.xml et context.xml dans $CATALINA_BASE/conf. Vous pouvez également trouver des fichiers de configuration contenant des mots de passe ou des informations d’identification à l’intérieur de votre application. Il peut s’agir du fichier META-INF/context.xml et, pour les applications Spring Boot, des fichiers application.properties ou application.yml.

Déterminer si le système de fichiers est utilisé et de quelle manière

Toute utilisation du système de fichiers sur le serveur d’applications nécessite une reconfiguration ou, dans de rares cas, des modifications architecturales. Vous pouvez identifier une partie ou l’ensemble des scénarios suivants.

Contenu statique en lecture seule

Si votre application sert actuellement du contenu statique, vous aurez besoin d’un autre emplacement pour lui. Vous pouvez envisager de déplacer du contenu statique vers le Stockage Blob Azure et d’ajouter Azure CDN pour accélérer globalement les téléchargements. Pour plus d’informations, consultez Hébergement de sites web statiques dans le service Stockage Azure et Démarrage rapide : Intégrer un compte de stockage Azure à Azure CDN. Vous pouvez également déployer directement le contenu statique sur une application dans le plan Azure Spring Apps Enterprise. Pour plus d’informations, consultez Déployer des fichiers statiques web.

Contenu statique publié dynamiquement

Si votre application autorise le contenu statique chargé/produit par votre application mais immuable après sa création, vous pouvez utiliser le Stockage Blob Azure et Azure CDN comme décrit ci-dessus, avec une fonction Azure pour gérer les chargements et l’actualisation du réseau CDN. Nous avons mis à votre disposition un exemple d’implémentation dans Chargement et préchargement CDN de contenu statique avec Azure Functions. Vous pouvez également déployer directement le contenu statique sur une application dans le plan Azure Spring Apps Enterprise. Pour plus d’informations, consultez Déployer des fichiers statiques web.

Identifier le mécanisme de persistance de session

Pour identifier le gestionnaire de persistance de session en cours d’utilisation, examinez les fichiers context.xml dans votre application et votre configuration Tomcat. Recherchez l’élément <Manager>, puis notez la valeur de l’attribut className.

Les implémentations intégrées de Tomcat PersistentManager , telles que StandardManager ou FileStore , ne sont pas conçues pour être utilisées avec une plateforme distribuée et mise à l’échelle telle qu’ACA. ACA peut équilibrer la charge entre plusieurs instances et redémarrer de manière transparente n’importe quelle instance à tout moment, de sorte que la persistance de l’état mutable dans un système de fichiers n’est pas recommandée.

Si la persistance de session est nécessaire, vous devez utiliser une autre implémentation PersistentManager qui écrit dans un magasin de données externe, comme VMware Tanzu Session Manager avec le cache Redis.

Cas particuliers

Certains scénarios de production peuvent nécessiter davantage de modifications ou imposer plus de limitations. Même si de tels scénarios peuvent être rares, il est important de s’assurer qu’ils ne sont pas applicables à votre application ou qu’ils sont correctement résolus.

Déterminer si l’application s’appuie sur des tâches planifiées

Les tâches planifiées, comme les tâches Quartz Scheduler ou les travaux Cron, ne peuvent pas être utilisées avec des déploiements Tomcat conteneurisés. Si votre application a fait l’objet d’un scale-out, une seule tâche planifiée peut s’exécuter plusieurs fois par période planifiée. Cette situation peut entraîner des conséquences inattendues.

Inventoriez toutes les tâches planifiées à l’intérieur ou à l’extérieur du serveur d’applications.

Déterminer si votre application contient du code propre au système d’exploitation

Si votre application contient du code avec des dépendances vis-à-vis du système d’exploitation hôte, vous devez la refactoriser pour supprimer ces dépendances. Par exemple, vous pouvez avoir besoin de remplacer toute utilisation de / ou \ dans les chemins de système de fichiers par File.Separator ou Paths.get.

Déterminer si MemoryRealm est utilisé

MemoryRealm nécessite un fichier XML persistant. Sur ACA, vous devez ajouter ce fichier à l’image conteneur ou le charger dans un stockage partagé mis à la disposition des conteneurs. (Pour plus d’informations, consultez le Identifier la section du mécanisme de persistance de session.) Le pathName paramètre doit être modifié en conséquence.

Pour déterminer si MemoryRealm est actuellement utilisé, examinez vos fichiers server.xml et context.xml et recherchez les éléments <Realm> dont l’attribut className a la valeur org.apache.catalina.realm.MemoryRealm.

Test sur place

Avant de créer des images conteneur, migrez votre application vers le JDK et Tomcat que vous envisagez d’utiliser sur ACA. Testez votre application minutieusement pour garantir sa compatibilité et ses performances.

Paramétrer la configuration

Lors de la prémigration, vous aurez probablement identifié des secrets et des dépendances externes, comme des sources de données, dans les fichiers server.xml et context.xml. Pour chaque élément ainsi identifié, remplacez le nom d’utilisateur, le mot de passe, la chaîne de connexion ou l’URL par une variable d’environnement.

Par exemple, supposons que le fichier context.xml contienne l’élément suivant :

<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$$"
/>

Dans ce cas, vous pouvez le changer comme indiqué dans l’exemple suivant :

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

Migration

Remarque

Certains déploiements Tomcat peuvent avoir plusieurs applications en cours d’exécution sur un même serveur Tomcat. Si c’est le cas dans votre déploiement, nous vous recommandons vivement d’exécuter chaque application dans un pod distinct. Ainsi, vous optimisez l’utilisation des ressources pour chaque application tout en minimisant la complexité et le couplage.

Préparer les artefacts de déploiement

Clonez le dépôt GitHub de démarrage rapide Tomcat sur conteneurs. Ce référentiel contient des fichiers de configuration Dockerfile et Tomcat avec de nombreuses optimisations recommandées. Dans les étapes ci-dessous, nous décrivons les modifications que vous devrez probablement apporter à ces fichiers avant de générer l’image conteneur et de déployer sur ACA.

Ajouter des ressources JNDI

Modifiez server.xml pour ajouter les ressources que vous avez préparées dans les étapes de prémigation, telles que les sources de données, comme illustré dans l’exemple suivant :

<!-- 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>

Pour obtenir des instructions supplémentaires sur les sources de données, consultez les sections suivantes de la page JNDI Datasource How-To (Guide pratique sur les sources de données JNDI) dans la documentation Tomcat :

Générer et envoyer (push) l’image

La façon la plus simple de générer et de charger l’image dans Azure Container Registry (ACR) à utiliser par ACA consiste à utiliser la az acr build commande. Cette commande ne nécessite pas l’installation de Docker sur votre ordinateur. Par exemple, si vous disposez du fichier Dockerfile à partir du dépôt tomcat-container-quickstart et du package d’application petclinic.war dans le répertoire actif, vous pouvez générer l’image conteneur dans ACR avec la commande suivante :

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 .

Vous pouvez omettre le paramètre --build-arg APP_FILE... si votre fichier WAR est nommé ROOT.war. Vous pouvez omettre le paramètre --build-arg SERVER_XML... si le fichier XML de votre serveur se nomme server.xml. Les deux fichiers doivent se trouver dans le même répertoire que le Dockerfile.

Vous pouvez également utiliser Docker CLI pour générer l’image localement à l’aide des commandes suivantes. Cette approche peut simplifier le test et l’affinage de l’image avant son déploiement initial sur ACR. Toutefois, elle nécessite que l’interface CLI de Docker soit installée et le démon de Docker en cours d’exécution.

# 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"

Pour plus d’informations, consultez Générer et stocker des images conteneur avec Azure Container Registry.

Déployer sur Azure Container Apps

La commande suivante illustre un exemple de déploiement :

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

Pour obtenir un guide de démarrage rapide plus détaillé, consultez Démarrage rapide : Déployer votre première application conteneur.

Post-migration

Maintenant que vous avez migré votre application vers ACA, vous devez vérifier qu’elle fonctionne comme prévu. Une fois que vous avez terminé, nous vous fournissons des recommandations pour rendre votre application plus native dans le cloud.

Recommandations

  • Concevez et implémentez une stratégie de continuité de l’activité et de reprise d’activité. Pour les applications stratégiques, envisagez une architecture de déploiement multirégion. Pour plus d’informations, consultez les meilleures pratiques en matière de continuité d’activité et de reprise d’activité dans Azure Kubernetes Service (AKS).

  • Évaluez les éléments inclus dans le fichier logging.properties. Envisagez d’éliminer ou de réduire une partie de la sortie de journalisation pour améliorer les performances.

  • Envisagez de surveiller la taille du cache de code et d’ajouter les paramètres -XX:InitialCodeCacheSize et -XX:ReservedCodeCacheSize à la JAVA_OPTS variable dans le fichier Dockerfile pour optimiser davantage les performances. Pour plus d’informations, consultez la rubrique sur le paramétrage de codecache dans la documentation Oracle.

  • Ajoutez des groupes d’actions et des règles d’alerte Azure Monitor pour détecter et résoudre rapidement les conditions aberrantes.

  • Envisagez de répliquer le déploiement d’Azure Container Apps dans une autre région pour une latence plus faible et une plus grande fiabilité et tolérance de panne. Utilisez Azure Traffic Manager pour équilibrer la charge entre les déploiements, ou utilisez Azure Front Door pour ajouter le déplacement SSL et le pare-feu d’applications web avec la protection DDoS.

  • Si la géoréplication n’est pas nécessaire, ajoutez une passerelle d’application Azure pour ajouter le déplacement SSL et le pare-feu d’applications web avec la protection DDoS.