zurück zum Artikel

App in die Cloud mit Java EE

Frank Pientka

(Bild: Erzeugt mit Midjourney durch heise medienwerk)

Für den Cloud-native-Umzug von Java-EE-Webanwendungen zu AWS stehen vielfältige Dienste bereit, um den Vorgang zu erleichtern.

Obwohl die Programmiersprache Java zu einer Zeit entstand, als das Internet noch in den Kinderschuhen steckte und der Begriff Cloud Computing noch längst nicht existierte, bietet es sich an, Java-Anwendungen in die Cloud zu migrieren oder dort neu zu entwickeln. Dieser Artikel betrachtet die Möglichkeiten dafür jenseits des Rehostings von On-premises-Anwendungen in die Cloud (Lift & Shift) und zeigt auf, welche Dienste von AWS (Amazon Web Services) für eine Cloud-native-Entwicklung zur Verfügung stehen. Mit einer eigenen kostenlosen Linux- und Java-Distribution bietet Amazon eine gute Basis.

Wie bei jeder guten Reisevorbereitung gilt es, die eigenen aktuellen Anforderungen und Ressourcen zu sichten und sich einen schnellen Überblick über mögliche Angebote zu verschaffen. Erst dann lässt sich eine entsprechende Strategie und Planung erstellen. Um den Zustand einer zu migrierenden Anwendung sowie das Risiko und die Chance einer Modernisierung einzuschätzen, gibt es verschiedene Code-Metriken, um die "Cloud-Readiness [1]" einer Anwendung zu bestimmen.

Dafür lässt sich der auf dem Code-Such- und Transformationssystem OpenRewrite basierende, kostenlose Cloud Suitability Analyzer [2] von VMware verwenden. OpenRewrite definiert Regeln, um zu prüfen, welche Stellen durch ein Update der Java-Version oder einer Spring-Boot-Version betroffen sind. Einige der nötigen Anpassungen kann OpenRewrite automatisch durchführen, während man andere erst nach mehreren Tests feststellen wird – um schließlich alle 12-Faktor-App-Kriterien für eine Cloud-native App nach der Definition der Cloud Native Computing Foundation [3] (CNCF) zu erfüllen. Hilfreich ist es, dafür automatische Builds oder das Spring-Cloud-Framework einzusetzen. Die Spring-Cloud-AWS-Erweiterungen [4] vereinfachen die Verwendung und damit die Integration der Anwendung in einige AWS-Dienste.

Möchte man eine typische Java-EE-Webanwendung in die AWS-Cloud bringen, gibt es dafür mehrere Dienste. Welche man verwendet, hängt vom vorhandenen Wissen über AWS sowie von der gewünschten Flexibilität ab. Die einfachste Möglichkeit, eine Java-EE-Webanwendung ohne viele Änderungen in die AWS-Cloud zu bringen, ist der Orchestrierungsdienst AWS Elastic Beanstalk. Er basiert auf den virtuellen Amazon-Elastic-Compute-Cloud-(EC2)-Instanzen mit einem Amazon-Linux-Image (AL2023). Es ist lediglich der gewünschte Instanztyp mit einem passenden Amazon Machine Image (AMI) mit Linux oder Windows auszuwählen.

Elastic Beanstalk richtet die notwendigen Netzwerke und Lastverteiler ein, ohne dass Entwicklerinnen und Entwickler sich mit den dahinterliegenden AWS-Diensten näher beschäftigen müssen. Sie können einfach ihre Datenbank in einer verwalteten Amazon-RDS-Datenbank (MySQL, MariaDB, PostgreSQL, Oracle, SQL-Server) anlegen und ihre Anwendung wie gewohnt als WAR-Datei in einen Apache-Tomcat-Webserver deployen. Insgesamt gibt es ein breites Spektrum an Compute- und relationalen Datenbank-Diensten bei AWS, bei der die Auswahl zwischen Komfort und Flexibilität nicht leicht fällt (Abbildung 1).

AWS bietet verschiedene Compute- und RDS-Optionen an (Abb. 1).,

AWS bietet verschiedene Compute- und RDS-Optionen an (Abb. 1).

Weitere Anpassungen an der Konfiguration sind in eigenen Dateien im Ordner .ebextensions möglich. Elastic Beanstalk bietet eine fertig eingerichtete, skalierbare, produktive Ablaufumgebung mit Autoskalierung, Monitoring und automatischen Updates der Systemumgebungen. Alternativ lassen sich auch Java-SE-Anwendungen als JAR-Datei oder Java-Anwendungen als Container deployen. Das erfordert jedoch oft das Anpassen einer klassischen Java-EE-Webanwendung oder das Verändern des Deployments. Liegt die Webanwendung noch nicht als Container vor [5], ist dieser im Build mit geeigneten Plug-ins wie Jib, Buildpacks oder Source-to-Image (S2I) selbst generierbar. Alternativ funktioniert das mit dem Eclipse-JKube-Plug-in äquivalent für Kubernetes-Deployments, und noch einfacher geht es mit dem AWS-App-Runner-Dienst.

Für kleinere Webanwendungen eignet sich auch der Amazon Lightsail Container Service. Bei Kubernetes-Clustern besteht die Wahl zwischen Amazon Elastic Kubernetes Service (EKS), Amazon Elastic Container Service (Amazon ECS) und dem serverlosen AWS Fargate. Ersteres erfordert jedoch größeres Wissen und Aufwände für einen produktiven Betrieb. Außerdem sind weiterhin das Verwalten der Worker-Nodes und die Pflege der Pods beziehungsweise Container notwendig.

Für kleinere Event-orientierte Java-Anwendungen ist der serverlose Lambda-Dienst verwendbar (Abbildung 2). Um Anwendungen als JAR-Datei oder Container-Image zu deployen, ist es jedoch nötig, sie im Sourcecode an Eigenheiten des Lambda-Dienstes anzupassen. Ähnlich wie bei Elastic Beanstalk muss man sich dabei nicht um das Aktualisieren der Java-Laufzeitumgebung, das Verwalten der vorkonfigurierten Ressourcen und deren Skalierbarkeit kümmern, da AWS das übernimmt. Ebenso sind die entsprechenden AWS-Dienste für Logging, Tracing und Monitoring bereits aktiviert, was später bei der Fehlersuche hilfreich sein kann.

Diese Möglichkeiten gibt es bei AWS für eine Java-Webanwendung (Abb. 2).,

Diese Möglichkeiten gibt es bei AWS für eine Java-Webanwendung (Abb. 2).

Auf der Reise zu Cloud-nativen Anwendungen führt bei Java an Frameworks wie Quarkus oder Spring Boot kein Weg vorbei. Selbst beim Einsatz des AWS-verwalteten Kubernetes-Dienstes Fargate für ECS fällt einiger Aufwand an, um diese Umgebungen zu erstellen, zu pflegen und zu überwachen. In Abbildung 3 sind die benötigten Dienste nur sehr grob dargestellt. Da Entwicklerinnen und Entwickler bei der Pflege einer Kubernetes-Umgebung über die Webkonsole schnell an ihre Grenzen kommen können, setzt man dazu Infrastructure-as-Code-(IaC)-Werkzeuge wie Terraform [6] oder das Cloud Development Kit (CDK) [7] ein. Für ECS, EKS und AWS Fargate gibt es von Amazon ECS Blueprints für CDK und Terraform [8], die die Verwendung aus fertig ausführbaren Vorlagen erlauben, um Kubernetes-Umgebungen zu pflegen. CDK [9] hat gegenüber Terraform den Vorteil, dass die Vorlagen mit Java programmierbar sind. Gegenüber Terraform-Dateien führt das zu kompakterem Code mit sinnvollen Standardwerten, der sich mit Standard-Testmitteln überprüfen lässt.

Mit cdk8s, dem Cloud Development Kit for Kubernetes [10], gibt es sogar eine CDK-Erweiterung, die es möglich macht, Kubernetes-Ressourcen zu verwalten. Trotzdem sind weitere AWS-Dienste wie Amazon Elastic Container Registry (ECR), eine Versionsverwaltung und eine Code-Pipeline nötig. Bei den IaC- und Kubernetes-Artefakten ist es sinnvoll, entsprechende Governance- und Qualitätsregeln aufzustellen und automatisch zu überprüfen.

Beim Bauen von Container-Images gibt es einiges zu beachten. So verwendet man am besten die mit AWS Corretto und AWS Linux vorgefertigten Container als Basis-Images [11] aus der ECR Public Gallery, um damit seine angepassten Images zu erstellen. Corretto ist eine plattformübergreifende, kostenlose OpenJDK-Distribution, für die Amazon vierteljährliche Sicherheits- und kritische Updates bereitstellt. AWS Linux basiert auf der Fedora-Distribution und bietet einen Langzeit-Support über fünf Jahre. Linux und die Corretto-Images [12] werden mit verschiedenem Umfang und damit Größe angeboten. Da beide auch außerhalb der AWS-Umgebung für die Plattformen x64 und die ARM-Plattform AArch64 verfügbar sind, lassen sie sich ebenso auf lokalen Rechnern einsetzen.

Amazon bietet EC2-basierte Instanzen für eine Vielzahl von Prozessorarchitekturen an (AMD, Intel, ARM). Besonders die eigenen ARM-basierten AWS-Graviton3-Prozessoren besitzen ein gutes Preis-Leistungs-Verhältnis, sodass sie sowohl für Java-Anwendungen (EC2, Container, Lambda) als auch für die Datenbanken Amazon RDS/Amazon Aurora MySQL, MariaDB oder PostgreSQL als günstige Alternative infrage kommen. Wie eine typische Referenzarchitektur mit den Kubernetes-Diensten von AWS aussehen kann, ist in Abbildung 3 dargestellt.

Die Grafik zeigt eine AWS-Referenzarchitektur für Kubernetes (Abb. 3).,

Die Grafik zeigt eine AWS-Referenzarchitektur für Kubernetes (Abb. 3).

Um Anwendungen dauerhaft in die Cloud zu bringen, ist es nötig, sich mit Themen wie DevOps, Überwachbarkeit [13] und Microservices [14] auseinanderzusetzen. Damit sind die Entwicklungs- und Betriebsprozesse anzupassen, aber auch andere Überwachungs- und Sicherheitsverfahren einzusetzen als bisher gewohnt. Das erzeugt oft höhere Lern- und Umstellungsaufwände als die Verwendung der AWS-Dienste allein. So ist es etwa sinnvoll, die Zugangsdaten für die Datenbank nicht in Umgebungsvariablen abzulegen, sondern die AWS-Dienste Secrets Manager oder AppConfig zu verwenden. Ebenso bietet AWS eine eigene Distribution von OpenTelemetry an, um damit bei der Überwachung der Anwendungen nicht nur auf die AWS-eigenen proprietären Dienste angewiesen zu sein.

Letztlich müssen Entwicklerinnen und Entwickler entscheiden, wie stark sie sich von AWS-Diensten abhängig machen möchten oder ob sie das als Chance ergreifen, um sich mehr auf die eigentliche Anwendungsentwicklung zu konzentrieren und weniger um das Verwalten von Infrastruktur.

Bei der Migration der Anwendung sollen Daten möglichst mit umziehen, wie Abbildung 4 anhand einer Webanwendung mit relationaler Datenbank zeigt. Unter Beibehaltung des Datenbankprodukts läuft das meist auf das Einspielen eines kompletten Backups hinaus. Bei Amazon RDS oder Aurora entfallen die Aufwände für die Routinetätigkeiten und Pflege der Datenbankumgebung. Auch hier hat man eine breite Auswahl an EC2-Instanzen. Möchte man das Datenbankprodukt wechseln, um zum Beispiel Lizenzkosten zu sparen, so bietet AWS einen Database Migration Service (DMS) und ein Schemakonvertierungs-Tool (SCT) an. Der DMS-Dienst lässt sich auch dazu nutzen, Daten nach dem initialen Laden live aus der Quelldatenbank zu aktualisieren. Der Einsatz von DMS setzt eine stabile VPN-Verbindung voraus. Oft ist es einfacher, Backups per HTTPS in einen Amazon-Simple-Storage-Service-(S3)-Bucket hochzuladen.

Ein bestehendes Backup-Verfahren lässt sich durch das Speichern der Sicherungen auf S3 bereits vor der Migration zu RDS erweitern. Da Backups bei S3 in mehreren Rechenzentren gespeichert werden, besteht eine höhere Verfügbarkeit und Ausfallsicherheit als im eigenen Rechenzentrum. Mit S3 lässt sich ein einfaches Lebenszykluskonzept erstellen, um nur für Nachweiszwecke benötigte Backups automatisch auf sichere und unveränderliche, günstigere Speicherklassen zu verschieben. Ebenso ist das Backup auch in andere Regionen verteilbar, um eine höhere Redundanz zu erhalten.

Eine Webanwendung mit relationaler Datenbank lässt sich zu AWS migrieren (Abb. 4).,

Eine Webanwendung mit relationaler Datenbank lässt sich zu AWS migrieren (Abb. 4).

Java gehört auch in der Cloud nicht zum alten Eisen. Ganz im Gegenteil gibt es dafür eine breite Unterstützung und viele Möglichkeiten. Dieser Artikel hat mehrere Wege für den Umzug von Java-Anwendungen in die AWS-Cloud vorgestellt, die man auf der Reise hin zu einer Cloud-nativen Entwicklung nutzen kann. Welcher Weg am geeignetsten ist, hängt von den gegebenen Anforderungen, Ressourcen und Wissen ab.

Das volle Potenzial der Cloud werden Entwicklerinnen und Entwickler erst mit der Zeit auszunutzen. Je mehr sie verwaltete Dienste einsetzen und je weniger sie sich daher um den Betrieb der Infrastruktur kümmern müssen, umso stärker können sie sich auf die Weiterentwicklung oder die Optimierung der Anwendung konzentrieren. Da sich bei AWS immer wieder neue Möglichkeiten ergeben und Entwickler bei der Nutzung der AWS-Dienste ständig dazulernen, kann es sich lohnen, Dienste zu wechseln, um die Nutzung zu optimieren und die Anwendungen Cloud-nativer zu machen. Cloud-native Anwendungen bieten die Chance, neue Architekturstile umzusetzen und alte Zöpfe abzuschneiden.

Frank Pientka
begleitet als zertifizierter und erfahrener Architekt die Kunden bei ihrer erfolgreichen Reise in der Cloud.


(map [15])


URL dieses Artikels:
https://www.heise.de/-9575077

Links in diesem Artikel:
[1] https://docs.aws.amazon.com/prescriptive-guidance/latest/cloud-design-patterns
[2] https://docs.openrewrite.org/recipes/cloudsuitability
[3] https://github.com/cncf/toc/blob/main/DEFINITION.md#deutsch
[4] https://awspring.io/
[5] https://docs.aws.amazon.com/prescriptive-guidance/latest/modernization-containerize-javaee
[6] https://aws-ia.github.io/terraform-aws-eks-blueprints/
[7] https://aws-quickstart.github.io/cdk-eks-blueprints/
[8] https://catalog.workshops.aws/ecs-solution-blueprints/
[9] https://docs.aws.amazon.com/cdk/v2/guide/ecs_example.html
[10] https://cdk8s.io/
[11] https://docs.aws.amazon.com/wellarchitected/latest/container-build-lens/container-build-lens.html
[12] https://gallery.ecr.aws/amazoncorretto/amazoncorretto
[13] https://docs.aws.amazon.com/prescriptive-guidance/latest/patterns/automatically-build-and-deploy-a-java-application-to-amazon-eks-using-a-ci-cd-pipeline.html
[14] https://docs.aws.amazon.com/prescriptive-guidance/latest/modernization-decomposing-monoliths/welcome.html
[15] mailto:map@ix.de