Eseguire la migrazione di applicazioni Tomcat ad App Azure Container

Questa guida descrive gli aspetti da tenere presenti quando si vuole eseguire la migrazione di un'applicazione Tomcat esistente da eseguire in App Azure Container.This guide describes what you be aware of when you want to migrate an existing Tomcat application to run on Azure Container Apps (ACA).

Pre-migrazione

Per garantire una corretta migrazione, prima di iniziare completare i passaggi di valutazione e inventario descritti nelle sezioni seguenti.

Inventario delle risorse esterne

Le risorse esterne, ad esempio le origini dati, i broker di messaggi JMS e altre, vengono inserite tramite JNDI (Java Naming and Directory Interface). Alcune di queste risorse possono richiedere la migrazione o la riconfigurazione.

All'interno dell'applicazione

Esaminare il file META-INF/context.xml. Cercare gli elementi <Resource> all'interno dell'elemento <Context>.

Nei server applicazioni

Esaminare i file $CATALINA_BASE/conf/context.xml e $CATALINA_BASE/conf/server.xml, oltre ai file con estensione xml disponibili nelle directory $CATALINA_BASE/conf/[nome-motore]/[nome-host].

Nei file context.xml le risorse JNDI verranno descritte dagli elementi <Resource> all'interno dell'elemento <Context> di primo livello.

Nei file server.xml le risorse JNDI verranno descritte dagli elementi <Resource> all'interno dell'elemento <GlobalNamingResources>.

Datasources

Le origini dati sono risorse JNDI con l'attributo type impostato su javax.sql.DataSource. Per ogni origine dati, documentare le informazioni seguenti:

  • Qual è il nome dell'origine dati?
  • Qual è la configurazione del pool di connessioni?
  • Dove è possibile trovare il file JAR del driver JDBC?

Per altre informazioni, vedere la sezione di procedure per le origini dati JNDI nella documentazione di Tomcat.

Tutte le altre risorse esterne

Non è possibile documentare tutte le possibili dipendenze esterne in questa guida. È responsabilità del team verificare che sia possibile soddisfare tutte le dipendenze esterne dell'applicazione dopo la migrazione.

Inventario dei segreti

Password e stringhe sicure

Controllare tutte le proprietà e i file di configurazione nei server di produzione per verificare la presenza di stringhe segrete e password. Assicurarsi di controllare i file server.xml e context.xml in $CATALINA_BASE/conf. È anche possibile trovare i file di configurazione contenenti password o credenziali all'interno dell'applicazione. Possono includere il file META-INF/context.xml e, per le applicazioni Spring Boot, il file application.properties o application.yml.

Determinare se e come viene usato il file system

Qualsiasi utilizzo del file system nel server applicazioni richiede modifiche della configurazione o, in casi rari, dell'architettura. È possibile identificare alcuni o tutti gli scenari seguenti.

Contenuto statico di sola lettura

Se l'applicazione attualmente distribuisce contenuto statico, è necessario modificarne la posizione. Si può scegliere di spostare il contenuto statico in Archiviazione BLOB di Azure e di aggiungere la rete di distribuzione dei contenuti di Azure per accelerare i download a livello globale. Per altre informazioni, vedere Hosting di siti Web statici in Archiviazione di Azure e Avvio rapido: Integrare un account di archiviazione di Azure con Rete CDN di Azure. È anche possibile distribuire direttamente il contenuto statico in un'app nel piano Azure Spring Apps Enterprise. Per altre informazioni, vedere Distribuire file statici Web.

Contenuto statico pubblicato dinamicamente

Se l'applicazione consente contenuto statico caricato/prodotto dall'applicazione ma non modificabile dopo la creazione, è possibile usare Archiviazione BLOB di Azure e la rete di distribuzione dei contenuti di Azure, come descritto sopra, con una funzione di Azure per gestire i caricamenti e l'aggiornamento della rete CDN. Nell'articolo Caricamento e precaricamento nella rete CDN di contenuto statico con Funzioni di Azure è riportata un'implementazione di esempio che è possibile usare. È anche possibile distribuire direttamente il contenuto statico in un'app nel piano Azure Spring Apps Enterprise. Per altre informazioni, vedere Distribuire file statici Web.

Identificare il meccanismo di persistenza delle sessioni

Per identificare il gestore di persistenza delle sessioni in uso, esaminare i file context.xml nell'applicazione e nella configurazione di Tomcat. Cercare l'elemento <Manager>, quindi prendere nota del valore dell'attributo className.

Le implementazioni predefinite di PersistentManager di Tomcat, ad esempio StandardManager o FileStore, non sono progettate per l'uso con una piattaforma distribuita e ridimensionata, ad esempio ACA. ACA può bilanciare il carico tra diverse istanze e riavviare in modo trasparente qualsiasi istanza in qualsiasi momento, pertanto non è consigliabile mantenere lo stato modificabile in un file system.

Se è richiesta la persistenza delle sessioni, è necessario usare un'implementazione di PersistentManager alternativa che scriverà in un archivio dati esterno, ad esempio VMware Tanzu Session Manager con Cache Redis.

Casi speciali

Alcuni scenari di produzione possono richiedere più modifiche o imporre più limitazioni. Sebbene tali scenari siano poco frequenti, è importante assicurarsi che siano inapplicabili all'applicazione o risolti correttamente.

Determinare se l'applicazione si basa su processi pianificati

I processi pianificati, ad esempio le attività di Quartz Scheduler o i processi Cron, non possono essere usati con le distribuzioni di Tomcat in contenitori. Se l'applicazione viene ampliata, un processo pianificato può essere eseguito più di una volta per ogni periodo pianificato. Questa situazione può provocare conseguenze indesiderate.

Creare un inventario di tutti i processi pianificati, all'interno o all'esterno del server applicazioni.

Determinare se l'applicazione contiene codice specifico del sistema operativo

Se l'applicazione contiene codice con dipendenze dal sistema operativo host, sarà necessario effettuarne il refactoring per rimuovere tali dipendenze. Ad esempio, potrebbe essere necessario sostituire qualsiasi utilizzo di / o \ nei percorsi del file system con File.Separator o Paths.get.

Determinare se viene usato MemoryRealm

MemoryRealm richiede un file XML persistente. In ACA è necessario aggiungere questo file all'immagine del contenitore o caricarlo nell'archiviazione condivisa resa disponibile per i contenitori. Per altre informazioni, vedere Identificare la sezione relativa al meccanismo di persistenza della sessione. Il pathName parametro dovrà essere modificato di conseguenza.

Per determinare se MemoryRealm è attualmente in uso, esaminare i file server.xml e context.xml e cercare gli elementi <Realm> in cui l'attributo className è impostato su org.apache.catalina.realm.MemoryRealm.

Test sul posto

Prima di creare immagini del contenitore, eseguire la migrazione dell'applicazione a JDK e Tomcat che si intende usare in ACA. Testare accuratamente l'applicazione per garantirne la compatibilità e le prestazioni.

Parametrizzare la configurazione

Nella fase di pre-migrazione è probabile che nei file server.xml e context.xml siano stati identificati segreti e dipendenze esterne, ad esempio origini dati. Per ogni elemento di questo tipo identificato, sostituire l'eventuale nome utente, password, stringa di connessione o URL con una variabile di ambiente.

Si supponga, ad esempio, che il file context.xml contenga l'elemento seguente:

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

In questo caso, è possibile cambiarlo come illustrato nell'esempio seguente:

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

Migrazione

Nota

Alcune distribuzioni di Tomcat possono avere più applicazioni in esecuzione in un singolo server Tomcat. Se questo è il caso, è consigliabile eseguire ogni applicazione in un pod separato. In questo modo è possibile ottimizzare l'utilizzo delle risorse per ogni applicazione riducendo al tempo stesso la complessità e l'accoppiamento.

Preparare gli artefatti della distribuzione

Clonare il repository GitHub di avvio rapido tomcat nei contenitori. Questo repository contiene un Dockerfile e file di configurazione Tomcat con molte ottimizzazioni consigliate. Nei passaggi seguenti verranno descritte le modifiche che probabilmente è necessario apportare a questi file prima di compilare l'immagine del contenitore e distribuirla in ACA.

Aggiungere risorse JNDI

Modificare server.xml per aggiungere le risorse preparate nei passaggi di pre-migrazione, ad esempio Origini dati, come illustrato nell'esempio seguente:

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

Per altre istruzioni sulle origini dati, vedere le sezioni seguenti sulle procedure sulle origini dati JNDI nella documentazione di Tomcat:

Creare l'immagine ed eseguirne il push

Il modo più semplice per compilare e caricare l'immagine in Registro Azure Container (ACR) da usare da ACA consiste nell'usare il az acr build comando . Questo comando non richiede l'installazione di Docker nel computer. Ad esempio, se si ha il Dockerfile dal repository tomcat-container-quickstart e il pacchetto dell'applicazione petclinic.war nella directory corrente, è possibile compilare l'immagine del contenitore in Registro Azure Container con il comando seguente:

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 .

È possibile omettere il parametro --build-arg APP_FILE... se il file WAR è denominato ROOT.war. È possibile omettere il parametro --build-arg SERVER_XML... se il file XML del server è denominato server.xml. Entrambi i file devono trovarsi nella stessa directory del Dockerfile.

In alternativa, è possibile usare l'interfaccia della riga di comando di Docker per compilare l'immagine in locale usando i comandi seguenti. Questo approccio può semplificare il test e il perfezionamento dell'immagine prima della distribuzione iniziale in Registro Azure Container. Tuttavia, è necessario che l'interfaccia della riga di comando di Docker sia installata e che il daemon Docker sia in esecuzione.

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

Per altre informazioni, vedere Creare e archiviare immagini del contenitore con Registro Azure Container.

Eseguire la distribuzione in App Azure Container

Il comando seguente illustra un esempio di distribuzione:

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

Per una guida introduttiva più approfondita, vedere Avvio rapido: Distribuire la prima app contenitore.

Dopo la migrazione

Ora che è stata eseguita la migrazione dell'applicazione ad ACA, è necessario verificare che funzioni come previsto. Una volta completata questa operazione, sono disponibili alcune raccomandazioni per rendere l'applicazione maggiormente nativa del cloud.

Consigli

  • Progettare e implementare una strategia di continuità aziendale e ripristino di emergenza. Per le applicazioni cruciali, considerare un'architettura di distribuzione in più aree. Per altre informazioni, vedere Procedure consigliate per la continuità aziendale e il ripristino di emergenza in servizio Azure Kubernetes (servizio Azure Kubernetes).

  • Valutare gli elementi nel file logging.properties. Valutare se eliminare o ridurre parte dell'output della registrazione per migliorare le prestazioni.

  • Prendere in considerazione il monitoraggio delle dimensioni della cache del codice e l'aggiunta dei parametri -XX:InitialCodeCacheSize e -XX:ReservedCodeCacheSize alla JAVA_OPTS variabile nel Dockerfile per ottimizzare ulteriormente le prestazioni. Per altre informazioni, vedere come ottimizzare la cache di codice nella documentazione di Oracle.

  • Valutare la possibilità di aggiungere regole di avviso e gruppi di azioni di Monitoraggio di Azure per rilevare rapidamente e risolvere le condizioni anomale.

  • Valutare la possibilità di replicare la distribuzione di App Contenitore di Azure in un'altra area per ridurre la latenza e maggiore affidabilità e tolleranza di errore. Usare Gestione traffico di Azure per bilanciare il carico tra le distribuzioni o usare Frontdoor di Azure per aggiungere l'offload SSL e Web Application Firewall con protezione DDoS.

  • Se la replica geografica non è necessaria, è consigliabile aggiungere un gateway applicazione di Azure per aggiungere l'offload SSL e Web Application Firewall con protezione DDoS.