Migrieren von Tomcat-Anwendungen zu Azure Container Apps
In dieser Anleitung erfahren Sie, worauf Sie achten müssen, wenn Sie eine vorhandene Tomcat-Anwendung für die Ausführung in Azure Container Apps (ACA) 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.
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 ACA konzipiert. ACA nimmt ggf. einen Lastenausgleich zwischen verschiedenen Instanzen vor und kann für Instanzen 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.
Sonderfälle
Für bestimmte Produktionsszenarien sind unter Umständen zusätzliche Änderungen erforderlich, oder es gelten zusätzliche Einschränkungen. Szenarien dieser Art sind zwar eher selten, 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
Wenn Ihre Anwendung Code mit Abhängigkeiten vom Hostbetriebssystem enthält, müssen Sie ihn umgestalten, um diese Abhängigkeiten zu beseitigen. Beispielsweise müssen Sie möglicherweise die Verwendung von /
oder \
in Dateisystempfaden durch File.Separator
oder Paths.get
ersetzen, wenn Ihre Anwendung unter Windows ausgeführt wird.
Ermitteln, ob MemoryRealm genutzt wird
Für MemoryRealm wird eine persistente XML-Datei benötigt. Unter ACA muss diese Datei dem Containerimage hinzugefügt oder in freigegebenen Speicher hochgeladen werden, der für Container verfügbar gemacht wird. (Weitere Informationen finden Sie im Abschnitt Identifizieren des Sitzungspersistenzmechanismus.) Der pathName
-Parameter 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.
Direktes Testen
Migrieren Sie Ihre Anwendung vor der Erstellung von Containerimages zu dem JDK und der Tomcat-Instanz, das bzw. die Sie unter ACA 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.
Hinweis
Microsoft empfiehlt, immer den sichersten Authentifizierungsflow zu verwenden, der verfügbar ist. Der in diesem Verfahren beschriebene Authentifizierungsfluss, z. B. für Datenbanken, Caches, Nachrichten oder KI-Dienste, erfordert ein sehr hohes Vertrauen in die Anwendung und trägt Risiken, die in anderen Flüssen nicht vorhanden sind. Verwenden Sie diesen Fluss nur, wenn sicherere Optionen wie verwaltete Identitäten für kennwortlose oder schlüssellose Verbindungen nicht geeignet sind. Bei Vorgängen des lokalen Computers bevorzugen Sie Benutzeridentitäten für kennwortlose oder schlüssellose Verbindungen.
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="{password}"
/>
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
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.
Vorbereiten der Bereitstellungsartefakte
Klonen Sie das GitHub-Repository für die Schnellstartanleitung für Tomcat in Containern. Dieses Repository enthält eine Dockerfile und Tomcat-Konfigurationsdateien mit zahlreichen empfohlenen Optimierungen. In den unten angegebenen Schritten werden Änderungen beschrieben, die für diese Dateien ratsam sind, bevor Sie das Containerimage erstellen und unter ACA bereitstellen.
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, wie im folgenden Beispiel gezeigt:
Hinweis
Microsoft empfiehlt, immer den sichersten Authentifizierungsflow zu verwenden, der verfügbar ist. Der in diesem Verfahren beschriebene Authentifizierungsfluss, z. B. für Datenbanken, Caches, Nachrichten oder KI-Dienste, erfordert ein sehr hohes Vertrauen in die Anwendung und trägt Risiken, die in anderen Flüssen nicht vorhanden sind. Verwenden Sie diesen Fluss nur, wenn sicherere Optionen wie verwaltete Identitäten für kennwortlose oder schlüssellose Verbindungen nicht geeignet sind. Bei Vorgängen des lokalen Computers bevorzugen Sie Benutzeridentitäten für kennwortlose oder schlüssellose Verbindungen.
<!-- 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 ACA 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 z. B. die Dockerfile aus dem Repository tomcat-container-quickstart und das Anwendungspaket petclinic.war im aktuellen Verzeichnis haben, können Sie das Containerimage in ACR mit dem folgenden Befehl erstellen:
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 .
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 zuerst lokal zu erstellen und zu testen. Dies ist in den folgenden Befehlen veranschaulicht. 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"
# 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"
Weitere Informationen finden Sie unter Erstellen und Speichern von Containerimages mit Azure Container Registry.
Bereitstellen von Azure Container Apps
Im folgenden Befehl ist eine Beispielbereitstellung gezeigt:
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
Eine ausführlichere Schnellstartanleitung finden Sie in Schnellstart: Bereitstellen Ihrer ersten Container-App.
Nach der Migration
Nachdem Sie Ihre Anwendung zu ACA 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.
Empfehlungen
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. Weitere Informationen finden Sie in den Best Practices für Geschäftskontinuität und Notfallwiederherstellung in Azure Kubernetes Service (AKS).
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 die Parameter
-XX:InitialCodeCacheSize
und-XX:ReservedCodeCacheSize
der Variablen in DockerfileJAVA_OPTS
hinzuzufügen, um die Leistung weiter zu optimieren. Weitere Informationen finden Sie in der Oracle-Dokumentation unter Codecache-Optimierung.Fügen Sie zur schnellen Erkennung und Behandlung von Anomalien ggf. Azure Monitor-Warnungsregeln und -Aktionsgruppen hinzu.
Replizieren Sie eventuell die Azure Container Apps-Bereitstellung in einer anderen Region, um von einer kürzeren Wartezeit sowie von einer höheren Zuverlässigkeit und Fehlertoleranz zu profitieren. Verwenden Sie Azure Traffic Manager für den Lastenausgleich zwischen Bereitstellungen oder Azure Front Door, um SSL-Abladung und Web Application Firewall mit DDoS-Schutz hinzuzufügen.
Sollte keine Georeplikation benötigt werden, können Sie eine Azure Application Gateway-Instanz verwenden, um SSL-Abladung und Web Application Firewall mit DDoS-Schutz hinzuzufügen.