Migrieren von Tomcat-Anwendungen zu Containern in Azure Kubernetes Service (AKS)
In diesem Leitfaden wird beschrieben, was Sie beachten sollten, wenn Sie eine vorhandene Tomcat-Anwendung für die Ausführung unter Azure Kubernetes Service (AKS) migrieren möchten.
Vor der Migration
Führen Sie vor Beginn einer Migration die in den folgenden Abschnitten beschriebenen Schritte zur Bewertung und Bestandsermittlung aus, um eine erfolgreiche Migration zu gewährleisten.
Bestand: Externe Ressourcen
Externe Ressourcen, z. B. Datenquellen, JMS-Nachrichtenbroker und andere, werden per JNDI (Java Naming and Directory Interface) eingefügt. Für einige dieser Ressourcen ist unter Umständen eine Migration oder erneute Konfiguration erforderlich.
Innerhalb Ihrer Anwendung
Untersuchen Sie die Datei META-INF/context.xml. Suchen Sie im <Context>
-Element nach <Resource>
-Elementen.
Auf den Anwendungsservern
Untersuchen Sie die Dateien $CATALINA_BASE/conf/context.xml und $CATALINA_BASE/conf/server.xml sowie die XML-Dateien, die in Verzeichnissen der Art $CATALINA_BASE/conf/[Engine-Name]/[Hostname] enthalten sind.
In context.xml-Dateien werden JNDI-Ressourcen im <Context>
-Element der obersten Ebene mithilfe von <Resource>
-Elementen beschrieben.
In server.xml-Dateien werden JNDI-Ressourcen im <GlobalNamingResources>
-Element mithilfe von <Resource>
-Elementen beschrieben.
Datenquellen
Datenquellen sind JNDI-Ressourcen, für die das type
-Attribut auf javax.sql.DataSource
festgelegt ist. Dokumentieren Sie für jede Datenquelle die folgenden Informationen:
- Wie lautet der Name der Datenquelle?
- Wie ist der Verbindungspool konfiguriert?
- Wo ist die JAR-Datei mit den JDBC-Treibern zu finden?
Weitere Informationen finden Sie in der Tomcat-Dokumentation unter Anleitung zur JNDI-Datenquelle.
Alle anderen externen Ressourcen
Es würde den Rahmen dieses Leitfadens sprengen, jede mögliche externe Abhängigkeit zu dokumentieren. Ihr Team ist dafür verantwortlich, zu überprüfen, dass nach der Migration die Anforderungen aller externen Abhängigkeiten Ihrer Anwendung abgedeckt werden können.
Bestand: Geheimnisse
Kennwörter und sichere Zeichenfolgen
Überprüfen Sie alle Eigenschaften und Konfigurationsdateien auf den Produktionsservern auf Geheimniszeichenfolgen und Kennwörter. Überprüfen Sie unbedingt server.xml und context.xml in $CATALINA_BASE/conf. Unter Umständen finden Sie in Ihrer Anwendung auch Konfigurationsdateien mit Kennwörtern oder Anmeldeinformationen. Dies können Dateien wie META-INF/context.xml und für Spring Boot-Anwendungen application.properties oder application.yml sein.
Ermitteln, ob und wie das Dateisystem verwendet wird
Für jegliche Nutzung des Dateisystems auf dem Anwendungsserver sind erneute Konfigurationen oder in selteneren Fällen auch Architekturänderungen erforderlich. Es kann sein, dass für Sie einige bzw. alle folgenden Szenarien zutreffen.
Schreibgeschützter statischer Inhalt
Falls mit Ihrer Anwendung derzeit statischer Inhalt bereitgestellt wird, benötigen Sie dafür einen anderen Speicherort. Sie können beispielsweise erwägen, statischen Inhalt in Azure Blob Storage zu verschieben und Azure CDN hinzuzufügen, um global eine sehr hohe Downloadgeschwindigkeit zu erzielen. Weitere Informationen finden Sie unter Hosten von statischen Websites in Azure Storage und Schnellstart: Integrieren eines Azure-Speicherkontos in Azure CDN.
Dynamisch veröffentlichter statischer Inhalt
Wenn Ihre Anwendung statischen Inhalt zulässt, der von Ihrer Anwendung hochgeladen bzw. produziert wird, nach der Erstellung aber unveränderlich ist, können Sie Azure Blob Storage und Azure CDN wie oben beschrieben nutzen. Hierbei können Sie auch eine Azure-Funktion zum Verarbeiten von Uploads und der CDN-Aktualisierung verwenden. Eine entsprechende Beispielimplementierung finden Sie unter Hochladen und CDN-Vorabladen von statischem Inhalt mit Azure Functions.
Dynamischer oder interner Inhalt
Für Dateien, für die von Ihrer Anwendung häufige Schreib- und Lesevorgänge durchgeführt werden (z. B. temporäre Datendateien), oder für statische Dateien, die nur für Ihre Anwendung sichtbar sind, können Sie Azure Storage-Freigaben als persistente Volumes bereitstellen. Weitere Informationen finden Sie unter Erstellen und Verwenden eines Volumes mit Azure Files in Azure Kubernetes Service (AKS).
Identifizieren eines Mechanismus für Sitzungspersistenz
Untersuchen Sie die context.xml-Dateien in Ihrer Anwendung und der Tomcat-Konfiguration, um den verwendeten Manager für Sitzungspersistenz zu ermitteln. Suchen Sie nach dem <Manager>
-Element, und notieren Sie sich den Wert des className
-Attributs.
Die integrierten PersistentManager-Implementierungen von Tomcat, z. B. StandardManager oder FileStore, sind nicht für die Nutzung mit einer verteilten skalierten Plattform wie Kubernetes konzipiert. AKS nimmt ggf. einen Lastenausgleich zwischen verschiedenen Pods vor und kann für Pods jederzeit einen transparenten Neustart durchführen. Das dauerhafte Speichern eines veränderlichen Zustands in einem Dateisystem ist daher nicht zu empfehlen.
Ist Sitzungspersistenz erforderlich, müssen Sie eine andere PersistentManager
-Implementierung verwenden, bei der in einen externen Datenspeicher geschrieben wird, z. B. VMware Tanzu-Sitzungs-Manager mit Redis Cache. Weitere Informationen finden Sie unter Verwenden von Redis als Sitzungscache mit Tomcat.
Sonderfälle
Für bestimmte Produktionsszenarien sind unter Umständen zusätzliche Änderungen erforderlich, oder es gelten zusätzliche Einschränkungen. Szenarien dieser Art treten zwar meist nicht sehr häufig auf, aber Sie sollten trotzdem sicherstellen, dass sie für Ihre Anwendung entweder nicht zutreffen oder korrekt behoben werden.
Ermitteln, ob für die Anwendung geplante Aufträge benötigt werden
Geplante Aufträge, z. B. Quartz Scheduler-Aufgaben oder cron-Aufträge, können für Tomcat-Bereitstellungen in Containern nicht verwendet werden. Wenn Ihre Anwendung horizontal hochskaliert wird, wird ein geplanter Auftrag unter Umständen mehrmals pro geplantem Zeitraum ausgeführt. Diese Situation kann unerwünschte Konsequenzen haben.
Inventarisieren Sie alle geplanten Aufträge innerhalb oder außerhalb des Anwendungsservers.
Ermitteln, ob Ihre Anwendung betriebssystemspezifischen Code enthält
Falls Ihre Anwendung Code enthält, in den das Betriebssystem für die Ausführung Ihrer Anwendung einbezogen ist, müssen Sie Ihre Anwendung so umgestalten, dass KEINE Abhängigkeit vom zugrunde liegenden Betriebssystem besteht. Beispielsweise müssen alle Vorkommen von /
oder \
in Dateisystempfaden ggf. durch File.Separator
oder Path.get
ersetzt werden.
Ermitteln, ob MemoryRealm genutzt wird
Für MemoryRealm wird eine persistente XML-Datei benötigt. Unter Kubernetes muss diese Datei dem Containerimage hinzugefügt oder in freigegebenen Speicher hochgeladen werden, der für Container verfügbar gemacht wird. Der Parameter pathName
muss entsprechend geändert werden.
Gehen Sie wie folgt vor, um zu ermitteln, ob MemoryRealm
derzeit verwendet wird: Untersuchen Sie Ihre server.xml- und context.xml-Dateien, und suchen Sie nach <Realm>
-Elementen, für die das className
-Attribut auf org.apache.catalina.realm.MemoryRealm
festgelegt ist.
Ermitteln, ob die SSL-Sitzungsverfolgung genutzt wird
Bei Bereitstellungen in Containern werden SSL-Sitzungen normalerweise außerhalb des Anwendungscontainers angeordnet. Dies erfolgt meist über den Eingangscontroller. Wenn für Ihre Anwendung die SSL-Sitzungsverfolgung benötigt wird, sollten Sie sicherstellen, dass SSL-Datenverkehr direkt an den Anwendungscontainer übergeben wird.
Ermitteln, ob AccessLogValve genutzt wird
Bei Verwendung von AccessLogValve sollte der Parameter directory
auf eine bereitgestellte Azure Files-Freigabe oder eines der zugehörigen Unterverzeichnisse festgelegt werden.
Direktes Testen
Migrieren Sie Ihre Anwendung vor der Erstellung von Containerimages zu dem JDK und der Tomcat-Instanz, das bzw. die Sie unter AKS nutzen möchten. Führen Sie für Ihre Anwendung gründliche Tests durch, um die Kompatibilität und Leistung sicherzustellen.
Parametrisieren der Konfiguration
Bei der Migrationsvorbereitung haben Sie in server.xml- und context.xml-Dateien ggf. Geheimnisse und externe Abhängigkeiten identifiziert, z. B. Datenquellen. Ersetzen Sie für alle hierbei identifizierten Elemente den Benutzernamen, das Kennwort, die Verbindungszeichenfolge und die URL durch eine Umgebungsvariable.
Angenommen, die context.xml-Datei enthält das folgende Element:
<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 diesem Fall können Sie die Änderungen vornehmen, die im folgenden Beispiel angegeben sind:
<Resource
name="jdbc/dbconnection"
type="javax.sql.DataSource"
url="${postgresdb.connectionString}"
driverClassName="org.postgresql.Driver"
username="${postgresdb.username}"
password="${postgresdb.password}"
/>
Migration
Wir empfehlen Ihnen, für jede zu migrierende Anwendung (WAR-Datei) die unten angegebenen Schritte auszuführen (mit Ausnahme des ersten Schritts „Bereitstellen von Containerregistrierung und AKS“).
Hinweis
Einige Tomcat-Bereitstellungen verfügen ggf. über mehrere Anwendungen, die auf einem einzelnen Tomcat-Server ausgeführt werden. Falls dies für Ihre Bereitstellung zutrifft, empfehlen wir Ihnen dringend, jede Anwendung in einem separaten Pod auszuführen. Auf diese Weise können Sie die Ressourcenverwendung für jede Anwendung optimieren und gleichzeitig die Komplexität und Kopplung minimieren.
Bereitstellen von Containerregistrierung und AKS
Erstellen Sie eine Containerregistrierung und einen Azure Kubernetes-Cluster, für den der Dienstprinzipal in der Registrierung über die Rolle „Leser“ verfügt. Achten Sie darauf, dass Sie für die Netzwerkanforderungen Ihres Clusters das richtige Netzwerkmodell auswählen.
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
Vorbereiten der Bereitstellungsartefakte
Klonen Sie das GitHub-Repository für die Schnellstartanleitung für Tomcat in Containern. Es enthält eine Dockerfile und Tomcat-Konfigurationsdateien mit einigen empfohlenen Optimierungen. In den unten angegebenen Schritten werden Änderungen beschrieben, die für diese Dateien ratsam sind, bevor Sie das Containerimage erstellen und unter AKS bereitstellen.
Öffnen von Ports für das Clustering (falls erforderlich)
Wenn Sie das Tomcat-Clustering unter AKS nutzen möchten, sollten Sie sicherstellen, dass in der Dockerfile die erforderlichen Portbereiche verfügbar gemacht werden. Achten Sie beim Angeben der Server-IP-Adresse in server.xml darauf, einen Wert aus einer Variablen zu verwenden, für die beim Starten des Containers die Initialisierung auf die IP-Adresse des Pods durchgeführt wird.
Alternativ kann der Sitzungszustand auch an einem anderen Ort dauerhaft gespeichert werden, damit er für alle Replikate verfügbar ist.
Suchen Sie für die Ermittlung, ob für Ihre Anwendung das Clustering verwendet wird, in der server.xml-Datei in den Elementen <Host>
oder <Engine>
nach dem <Cluster>
-Element.
Hinzufügen von JNDI-Ressourcen
Bearbeiten Sie server.xml, um die Ressourcen hinzuzufügen, die Sie in den Schritten für die Migration vorbereitet haben, z. B. Datenquellen.
Zum Beispiel:
<!-- 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>
Weitere Anweisungen zu Datenquellen finden Sie in der Tomcat-Dokumentation in den folgenden Abschnitten der Anleitung zur JNDI-Datenquelle:
Erstellen und Pushen des Images
Die einfachste Möglichkeit zum Erstellen und Hochladen des Images in Azure Container Registry (ACR) zur Verwendung durch AKS ist die Nutzung des Befehls az acr build
. Für diesen Befehl ist es nicht erforderlich, dass Docker auf Ihrem Computer installiert ist. Wenn Sie im aktuellen Verzeichnis beispielsweise über die obige Dockerfile und das Anwendungspaket petclinic.war verfügen, können Sie das Containerimage in ACR in nur einem Schritt erstellen:
az acr build \
--image "${acrName}.azurecr.io/petclinic:{{.Run.ID}}" \
--registry $acrName \
--build-arg APP_FILE=petclinic.war \
--build-arg=prod.server.xml .
Sie können den Parameter --build-arg APP_FILE...
weglassen, wenn Ihre WAR-Datei den Namen ROOT.war hat. Sie können den Parameter --build-arg SERVER_XML...
weglassen, wenn die XML-Datei des Servers den Namen server.xml hat. Beide Dateien müssen sich in demselben Verzeichnis wie die Dockerfile befinden.
Alternativ können Sie die Docker-CLI verwenden, um das Image lokal zu erstellen. Dieser Ansatz kann das Testen und Optimieren des Images vor der ersten Bereitstellung unter ACR vereinfachen. Hierfür muss allerdings die Docker-CLI installiert und der Docker-Daemon ausgeführt werden.
# 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"
Weitere Informationen finden Sie unter dem Modul Learn für Erstellen und Speichern von Container Images in Azure.
Bereitstellen einer öffentlichen IP-Adresse
Wenn für Ihre Anwendung der Zugriff von außerhalb Ihrer internen oder virtuellen Netzwerke möglich sein soll, ist eine öffentliche statische IP-Adresse erforderlich. Diese IP-Adresse sollte innerhalb der Ressourcengruppe des Clusterknotens bereitgestellt werden.
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}."
Bereitstellen für AKS
Erstellen und Anwenden Ihrer Kubernetes-YAML-Dateien. Wenn Sie einen externen Lastenausgleich erstellen (ob für Ihre Anwendung oder einen Eingangscontroller), sollten Sie darauf achten, dass Sie die IP-Adresse aus dem vorherigen Abschnitt als LoadBalancerIP
angeben.
Binden Sie externalisierte Parameter als Umgebungsvariablen ein. Vermeiden Sie die Einbindung von Geheimnissen (z. B. Kennwörter, API-Schlüssel und JDBC-Verbindungszeichenfolgen). Geheimnisse werden im Abschnitt Konfigurieren von KeyVault FlexVolume beschrieben.
Konfigurieren von persistentem Speicher
Konfigurieren Sie ein oder mehrere persistente Volumes, wenn für Ihre Anwendung nicht flüchtiger Speicher benötigt wird.
Es kann ratsam sein, ein persistentes Volume mit Azure Files zu erstellen, das im Tomcat-Protokollverzeichnis (/tomcat_logs) bereitgestellt wird. Die Protokolle können dann zentral aufbewahrt werden. Weitere Informationen finden Sie unter Dynamisches Erstellen und Verwenden eines persistenten Volumes mit Azure Files in Azure Kubernetes Service (AKS).
Konfigurieren von KeyVault FlexVolume
Erstellen Sie eine Azure KeyVault-Instanz, und fügen Sie alle erforderlichen Geheimnisse ein. Konfigurieren Sie anschließend eine KeyVault FlexVolume-Instanz, um diese Geheimnisse für Pods zugänglich zu machen.
Sie müssen das Startskript ändern (startup.sh im GitHub-Repository für Tomcat in Containern), um die Zertifikate in den lokalen Keystore des Containers zu importieren.
Migrieren von geplanten Aufträgen
Definieren Sie zum Ausführen von geplanten Aufträgen in Ihrem AKS-Cluster je nach Bedarf Cron-Aufträge.
Nach der Migration
Nachdem Sie Ihre Anwendung zu AKS migriert haben, sollten Sie sich vergewissern, dass sie wie erwartet funktioniert. Als Nächstes können Sie sich über unsere Empfehlungen informieren, mit denen Sie Ihre Anwendung cloudnativer gestalten können.
Erwägen Sie, einen DNS-Namen der IP-Adresse hinzuzufügen, die Ihrem Eingangscontroller oder dem Lastenausgleichsmodul der Anwendung zugeordnet ist. Weitere Informationen finden Sie unter Verwenden von TLS mit einem Eingangs-Controller in Azure Kubernetes Service (AKS).
Erwägen Sie, HELM-Diagramme für Ihre Anwendung hinzuzufügen. Mit einem Helm-Diagramm können Sie Ihre Anwendungsbereitstellung parametrisieren, damit diese von unterschiedlichen Kunden genutzt werden kann.
Entwerfen und implementieren Sie eine DevOps-Strategie. Sie können Bereitstellungen automatisieren und mit Azure Pipelines testen, um die Zuverlässigkeit sicherzustellen, während gleichzeitig die Entwicklungsgeschwindigkeit erhöht wird.
Aktivieren Sie die Azure-Überwachung für den Cluster, um das Sammeln von Containerprotokollen, Nachverfolgen der Nutzung und andere Optionen zu ermöglichen.
Erwägen Sie, anwendungsspezifische Metriken über Prometheus verfügbar zu machen. Prometheus ist ein Open-Source-Framework für Metriken, das von der Kubernetes-Community viel genutzt wird. Sie können die Erfassung von Prometheus-Metriken in Azure Monitor konfigurieren, anstatt Ihren eigenen Prometheus-Server zu hosten. So ermöglichen Sie die Aggregation von Metriken aus Ihren Anwendungen und die automatisierte Reaktion auf anomale Bedingungen bzw. deren Eskalation.
Entwerfen und implementieren Sie eine Strategie für Geschäftskontinuität und Notfallwiederherstellung. Bei unternehmenskritischen Anwendungen sollten Sie erwägen, eine Bereitstellungsarchitektur mit mehreren Regionen zu verwenden.
Informieren Sie sich über die Richtlinie zur Unterstützung der Kubernetes-Version. Wir sind dafür verantwortlich, Ihren AKS-Cluster zu aktualisieren und auf dem neuesten Stand zu halten, damit sichergestellt ist, dass immer eine unterstützte Version ausgeführt wird.
Sorgen Sie dafür, dass alle Teammitglieder, die für die Clusterverwaltung und Anwendungsentwicklung zuständig sind, über die entsprechenden bewährten Methoden für AKS informiert sind.
Sehen Sie sich die Elemente in der Datei logging.properties an. Erwägen Sie, einen Teil der Protokollierungsausgabe zu entfernen bzw. zu reduzieren, um die Leistung zu verbessern.
Sie haben auch die Möglichkeit, die Größe des Codecaches zu überwachen und der Variablen
JAVA_OPTS
in der Dockerfile die Parameter-XX:InitialCodeCacheSize
und-XX:ReservedCodeCacheSize
hinzuzufügen, um die Leistung weiter zu optimieren.