Tomcat-toepassingen migreren naar containers in Azure Kubernetes Service

In deze handleiding wordt beschreven waarmee u rekening moet houden wanneer u een bestaande Tomcat-toepassing wilt uitvoeren in Azure Kubernetes Service (AKS).

Premigratie

Voltooi voordat u begint de evaluatie- en inventarisstappen die in de volgende secties worden beschreven om een geslaagde migratie te garanderen.

Externe resources inventariseren

Externe resources, zoals gegevensbronnen, JMS-berichtenbrokers en andere resources, worden ingevoerd via Java Naming and Directory Interface (JNDI). Voor sommige resources kan migratie of herconfiguratie vereist zijn.

Binnen uw toepassing

Inspecteer het bestand META-INF/context.xml. Zoek naar <Resource>-elementen in het <Context>-element.

Op de toepassingsserver(s)

Inspecteer de bestanden $CATALINA_BASE/conf/context.xml en $CATALINA_BASE/conf/server.xml, evenals de .xml-bestanden die zich bevinden in de mappen $CATALINA_BASE/conf/[engine-name]/[host-name].

In context.xml-bestanden worden JNDI-resources beschreven door de <Resource>-elementen binnen het <Context>-element op het hoogste niveau.

In server.xml-bestanden worden JNDI-resources beschreven door de <Resource>-elementen binnen het <GlobalNamingResources>-element.

Gegevensbronnen

Gegevensbronnen zijn JNDI-resources waarvoor het kenmerk type is ingesteld op javax.sql.DataSource. Documenteer voor elke gegevensbron de volgende informatie:

  • Wat is de naam van de gegevensbron?
  • Wat is de configuratie van de verbindingsgroep?
  • Waar vind ik het JAR-bestand van het JDBC-stuurprogramma?

Raadpleeg JNDI Datasource HOW-TO in de Tomcat-documentatie.

Alle andere externe resources

Het is niet haalbaar om alle mogelijke externe afhankelijkheden in deze handleiding te documenteren. Het is de verantwoordelijkheid van uw team om alle externe afhankelijkheden van uw toepassing te verifiëren na de migratie.

Geheimen inventariseren

Wachtwoorden en beveiligde tekenreeksen

Controleer alle eigenschaps- en configuratiebestanden op de productieserver(s) op geheime tekenreeksen en wachtwoorden. Controleer in elk geval server.xml en context.xml in $CATALINA_BASE/conf. U kunt ook configuratiebestanden met wachtwoorden of referenties in uw toepassing aantreffen. Het kan gaan om de bestanden META-INF/context.xml en, voor Spring Boot-toepassingen, application.properties of application.yml.

Nagaan of en hoe het bestandssysteem wordt gebruikt

Voor het gebruik van het bestandssysteem op de toepassingsserver is herconfiguratie vereist of zijn in zeldzame gevallen architectuurwijzigingen vereist. U kunt enkele of elk van de volgende scenario's identificeren.

Statische alleen-lezeninhoud

Als uw toepassing momenteel met statische inhoud werkt, hebt u hiervoor een alternatieve locatie nodig. U kunt statische inhoud verplaatsen naar Azure Blob Storage en Azure CDN toevoegen voor razendsnelle downloads wereldwijd. Zie statische websitehosting in Azure Storage en quickstart: Een Azure-opslagaccount integreren met Azure CDN voor meer informatie. U kunt de statische inhoud ook rechtstreeks implementeren in een app in het Azure Spring Apps Enterprise-abonnement. Zie Statische webbestanden implementeren voor meer informatie.

Dynamisch gepubliceerde statische inhoud

Als uw toepassing statische inhoud toestaat die wordt geüpload/geproduceerd door uw toepassing, maar onveranderbaar is nadat deze is gemaakt, kunt u Azure Blob Storage en Azure CDN gebruiken zoals hierboven beschreven, met een Azure-functie om uploads en CDN-vernieuwing te verwerken. U vindt een voorbeeldimplementatie voor gebruik in Statische inhoud uploaden en via CDN vooraf laden met Azure Functions. U kunt de statische inhoud ook rechtstreeks implementeren in een app in het Azure Spring Apps Enterprise-abonnement. Zie Statische webbestanden implementeren voor meer informatie.

Dynamische of interne inhoud

Voor bestanden die vaak worden gelezen en waarin regelmatig gegevens worden geschreven door uw toepassing (zoals tijdelijke gegevensbestanden), of voor statische bestanden die alleen zichtbaar zijn voor uw toepassing, kunt u Azure Storage-shares koppelen als permanente volumes. Zie Permanent volume dynamisch maken en gebruiken met Azure Files in Azure Kubernetes Service voor meer informatie.

Methode voor de sessiepersistentie bepalen

Controleer de context.xml-bestanden in uw toepassing en Tomcat-configuratie om te bepalen welk sessiepersistentiebeheer wordt gebruikt. Ga naar het element <Manager> en noteer de waarde van het kenmerk className.

De ingebouwde PersistentManager-implementaties van Tomcat, zoals StandardManager of FileStore, zijn niet ontworpen om te worden gebruikt met een gedistribueerd, geschaald platform zoals Kubernetes. AKS kan een taakverdeling tussen verschillende pods toepassen en pods op elk gewenst moment op transparante wijze opnieuw opstarten. Daarom wordt het niet aanbevolen om een veranderlijke status te blijven behouden voor een bestandssysteem.

Als sessiepersistentie vereist is, moet u een alternatieve PersistentManager implementatie gebruiken die naar een extern gegevensarchief schrijft, zoals VMware Tanzu Session Manager met Redis Cache. Zie Redis als een sessiecache gebruiken met Tomcat voor meer informatie.

Speciale gevallen

Voor bepaalde productiescenario's zijn mogelijk aanvullende wijzigingen vereist of gelden extra beperkingen. Hoewel dergelijke scenario's mogelijk niet vaak voorkomen, is het belangrijk om ervoor te zorgen dat deze niet toepasbaar zijn op uw toepassing of dat deze op de juiste wijze zijn opgelost.

Bepalen of de toepassing gebruikmaakt van geplande taken

Geplande taken, zoals Quartz Scheduler-taken of Cron-taken, kunnen niet worden gebruikt met in containers geplaatste Tomcat-implementaties. Als uw toepassing wordt uitgeschaald, kan één geplande taak meer dan één keer per geplande periode worden uitgevoerd. Deze situatie kan tot onbedoelde gevolgen leiden.

Maak een inventaris van de geplande taken binnen of buiten de toepassingsserver.

Bepalen of uw toepassing code bevat die specifiek is voor het besturingssysteem

Als uw toepassing code bevat die specifiek is voor het besturingssysteem waarin uw toepassing wordt uitgevoerd, moet uw toepassing worden geherstructureerd zodat deze NIET meer afhankelijk is van het onderliggende besturingssysteem. Elk gebruik van / of \ in bestandssysteempaden moet bijvoorbeeld worden vervangen door File.Separator of Path.get.

Bepalen of MemoryRealm wordt gebruikt

Voor MemoryRealm is een persistent XML-bestand vereist. In Kubernetes moet dit bestand worden toegevoegd aan de containerinstallatiekopie of worden geüpload naar gedeelde opslag die beschikbaar wordt gemaakt voor containers. De parameter pathName moet dienovereenkomstig worden gewijzigd.

Als u wilt bepalen of MemoryRealm op het huidige moment wordt gebruikt, controleert u de bestanden server.xml en context.xml en zoekt u naar <Realm>-elementen waarbij het kenmerk className is ingesteld op org.apache.catalina.realm.MemoryRealm.

Bepalen of SSL-sessietracering wordt gebruikt

In containerimplementaties worden SSL-sessies doorgaans buiten de toepassingscontainer geoffload, meestal door de controller voor inkomend verkeer. Als voor uw toepassing SSL-sessietracering is vereist, moet u ervoor zorgen dat het SSL-verkeer rechtstreeks aan de toepassingscontainer wordt doorgegeven.

Bepalen of AccessLogValve wordt gebruikt

Als AccessLogValve wordt gebruikt, moet de parameter directory worden ingesteld op een gekoppelde Azure Files-share of een van de submappen ervan.

In-place tests

Voordat u containerinstallatiekopieën maakt, migreert u uw toepassing naar de JDK en Tomcat die u wilt gebruiken in AKS. Test uw toepassing grondig op compatibiliteit en prestaties.

De configuratie parameteriseren

In de fase voorafgaand aan de migratie hebt u waarschijnlijk de geheimen en externe afhankelijkheden geïdentificeerd, zoals gegevensbronnen, in de bestanden server.xml en context.xml. Vervang voor elk item dat als zodanig is geïdentificeerd de gebruikersnaam, het wachtwoord, de verbindingsreeks of URL door een omgevingsvariabele.

Stel bijvoorbeeld dat het bestand context.xml het volgende element bevat:

<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 dat geval kunt u dit wijzigen zoals wordt weergegeven in het volgende voorbeeld:

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

Migratie

Met uitzondering van de eerste stap (Containerregister en AKS inrichten), wordt aanbevolen de onderstaande stappen voor elke toepassing (elk WAR-bestand) die u wilt migreren afzonderlijk uit te voeren.

Notitie

In sommige Tomcat-implementaties worden mogelijk meerdere toepassingen uitgevoerd op één Tomcat-server. Als dit het geval is in uw implementatie, wordt het ten zeerste aanbevolen elke toepassing uit te voeren in een afzonderlijke pod. Zo kunt u het resourcegebruik voor elke toepassing optimaliseren en tegelijkertijd de complexiteit en koppeling minimaliseren.

Containerregister en AKS inrichten

Maak een containerregister en een Azure Kubernetes-cluster waarvan de service-principal de lezersrol heeft in het register. Zorg ervoor dat u het juiste netwerkmodel kiest voor de netwerkvereisten van uw 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

De implementatieartefacten voorbereiden

Kloon de Quickstart GitHub-opslagplaats Tomcat in containers. Deze bevat een Dockerfile en Tomcat-configuratiebestanden met een aantal aanbevolen optimalisaties. De onderstaande stappen bieden een overzicht van de wijzigingen die u waarschijnlijk moet aanbrengen in deze bestanden voordat u de containerinstallatiekopie bouwt en implementeert in AKS.

Poorten openen voor clusteren, indien nodig

Als u Tomcat-clustering wilt gebruiken in AKS, moet u ervoor zorgen dat de Dockerfile de benodigde poortbereiken bevat. Als u het IP-adres van de server in server.xml wilt opgeven, moet u een waarde gebruiken van een variabele die wordt geïnitialiseerd bij het opstarten van de container. Deze waarde moet verwijzen naar het IP-adres van de pod.

U kunt ook de sessiestatus doorvoeren op een andere locatie zodat deze beschikbaar is in verschillende replica's.

Als u wilt bepalen of uw app gebruikmaakt van clustering, zoekt u naar het element <Cluster> in de elementen <Host> of <Engine> in het bestand server.xml.

JNDI-resources toevoegen

Bewerk server.xml om de resources toe te voegen die u hebt voorbereid in de stappen voorafgaand aan de migratie, zoals gegevensbronnen.

Voorbeeld:

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

Raadpleeg de volgende gedeelten van JNDI Datasource How-To in de Tomcat-documentatie voor aanvullende gegevensbroninstructies:

De installatiekopie bouwen en pushen

De eenvoudigste manier om de installatiekopie te bouwen en te uploaden naar Azure Container Registry (ACR) voor gebruik door AKS, is door gebruik te maken van de opdracht az acr build. Voor deze opdracht hoeft Docker niet op uw computer geïnstalleerd te zijn. Als u bijvoorbeeld de bovenstaande Dockerfile en het toepassingspakket petclinic.war in de huidige map hebt, kunt u de containerinstallatiekopie met één stap maken in ACR:

az acr build \
    --image "${acrName}.azurecr.io/petclinic:{{.Run.ID}}" \
    --registry $acrName \
    --build-arg APP_FILE=petclinic.war \
    --build-arg=prod.server.xml .

U kunt de parameter --build-arg APP_FILE... weglaten als uw WAR-bestand de naam ROOT.war heeft. U kunt de parameter --build-arg SERVER_XML... weglaten als uw XML-bestand de naam server.xml heeft. Beide bestanden moeten zich in dezelfde map als Dockerfile bevinden.

U kunt ook Docker CLI gebruiken om de installatiekopie lokaal te bouwen. Met deze aanpak kunt u het testen en verfijnen van de installatiekopie voorafgaand aan de initiële implementatie in ACR vereenvoudigen. Hiervoor moet Docker CLI zijn geïnstalleerd en de Docker-daemon actief zijn.

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

Zie de Learn-module voor het bouwen en opslaan van containerinstallatiekopieën in Azure voor meer informatie.

Een openbaar IP-adres inrichten

Als uw toepassing toegankelijk moet zijn buiten uw interne of virtuele netwerk(en), is een openbaar statisch IP-adres vereist. Dit IP-adres moet worden ingericht in de resourcegroep van het clusterknooppunt.

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}."

Implementeren naar AKS

Maak de Kubernetes YAML-bestand(en) en pas dit/deze toe. Als u een externe load balancer maakt (naar uw toepassing of naar een controller voor inkomend verkeer), geeft u het IP-adres op dat u in de vorige sectie hebt ingericht als LoadBalancerIP.

Neem extern gemaakte parameters op als omgevingsvariabelen. Neem geen geheimen op (zoals wachtwoorden, API-sleutels en JDBC-verbindingsreeksen). Geheimen worden behandeld in de sectie KeyVault FlexVolume configureren.

Permanente opslag configureren

Als voor uw toepassing niet-vluchtige opslag vereist is, configureert u een of meer permanente volumes.

U kunt een permanent volume maken met behulp van Azure Files gekoppeld aan de map Tomcat_logs (/tomcat_logs) om logboeken centraal te bewaren. Zie Permanent volume dynamisch maken en gebruiken met Azure Files in Azure Kubernetes Service (AKS) voor meer informatie.

KeyVault FlexVolume configureren

Maak een Azure KeyVault en vul alle benodigde geheimen in. Configureer vervolgens een KeyVault FlexVolume om deze geheimen toegankelijk te maken voor pods.

U moet het opstartscript (startup.sh in de GitHub-opslagplaats Tomcat in containers) wijzigen om de certificaten te importeren in het lokale sleutelarchief in de container.

Geplande taken migreren

Als u geplande taken wilt uitvoeren in uw AKS-cluster, moet u de benodigde Cron-taken definiëren.

Postmigratie

Nu u de toepassing naar AKS hebt gemigreerd, moet u controleren of deze naar behoren werkt. Wanneer u dat gedaan hebt, hebben we enkele aanbevelingen voor u aan de hand waarvan u de toepassing geschikter kunt maken voor de cloud.

  • U kunt een DNS-naam toevoegen aan het IP-adres dat is toegewezen aan uw controller voor inkomend verkeer of uw load balancer voor toepassingen. Zie Een ingangscontroller maken met een statisch openbaar IP-adres in AKS voor meer informatie.

  • U kunt Helm-grafieken toevoegen voor uw toepassing. Met een Helm-grafiek kunt u de implementatie van uw toepassing parameteriseren voor gebruik en aanpassing door een gevarieerdere set klanten.

  • Ontwerp en implementeer een DevOps-strategie. Als u sneller wilt ontwikkelen zonder dat dit ten koste gaat van de betrouwbaarheid, kunt u het beste implementaties en testen automatiseren met Azure Pipelines.

  • Schakel Azure Monitoring voor het cluster in om het verzamelen van containerlogboeken, het bijhouden van het gebruik enzovoort mogelijk te maken.

  • U kunt toepassingsspecifieke metrische gegevens beschikbaar maken via Prometheus. Prometheus is een open source-framework voor metrische gegevens dat veel wordt gebruikt in de Kubernetes-community. U kunt Scraping van metrische gegevens voor Prometheus in Azure Monitor configureren in plaats van uw eigen Prometheus-server te hosten om metrische aggregatie van uw toepassingen en automatische reacties op of escalatie van afwijkende omstandigheden mogelijk te maken.

  • Ontwerp en implementeer een strategie voor bedrijfscontinuïteit en herstel na noodgevallen. Voor bedrijfskritische toepassingen kunt u het beste een implementatiearchitectuur voor meerdere regio's gebruiken.

  • Raadpleeg het Beleid voor ondersteuning van Kubernetes-versies. Het is uw verantwoordelijkheid om uw AKS-cluster bij te werken zodat er altijd een ondersteunde versie wordt uitgevoerd.

  • Zorg ervoor dat alle teamleden die verantwoordelijk zijn voor clusterbeheer en toepassingsontwikkeling de relevante best practices voor AKS bekijken.

  • Controleer de items in het bestand logging.properties. U kunt een deel van de logboekuitvoer elimineren of beperken om de prestaties te verbeteren.

  • U kunt de grootte van de codecache bewaken en de parameters -XX:InitialCodeCacheSize en -XX:ReservedCodeCacheSize toevoegen aan de variabele JAVA_OPTS in de Dockerfile om de prestaties verder te verbeteren.