Spring Boot-Java-Anwendung in Kubernetes in Google Kubernetes Engine bereitstellen

1. Hinweis

Kubernetes ist ein Open-Source-Projekt, das sich in vielen verschiedenen Umgebungen ausführen lässt – ob Laptop oder hochverfügbarer Cluster mit mehreren Knoten, ob öffentliche Cloud oder lokales Deployment, ob VM-Instanz (virtuelle Maschine) oder Bare-Metal-Server.

In diesem Codelab stellen Sie eine einfache Spring Boot-Java-Webanwendung in Kubernetes auf GKE bereit. Ziel ist es, dass Sie Ihre Webanwendung als replizierte Anwendung in Kubernetes ausführen. Dazu verwenden Sie Code, den Sie auf Ihrem Computer entwickelt haben, wandeln ihn in ein Docker-Container-Image um und führen dieses dann in GKE aus.

Sie verwenden GKE, einen vollständig verwalteten Kubernetes-Dienst in Google Cloud, damit Sie sich auf Kubernetes konzentrieren können, ohne erst die zugrunde liegende Infrastruktur einrichten zu müssen.

Wenn Sie wissen möchten, wie Sie Kubernetes auf Ihrem lokalen Computer ausführen, z. B. auf einem Entwicklerlaptop, sollten Sie sich Minikube ansehen. Damit lässt sich ein Kubernetes-Cluster mit einem einzelnen Knoten zu Entwicklungs- und Testzwecken ganz einfach einrichten. Wenn Sie möchten, können Sie Minikube auch für dieses Codelab verwenden.

In diesem Codelab wird der Beispielcode aus dem Leitfaden Anwendung mit Spring Boot erstellen verwendet.

Voraussetzungen

  • Kenntnisse der Programmiersprache Java und der entsprechenden Tools
  • Kenntnisse von standardmäßigen Linux-Texteditoren wie Vim, Emacs und Nano

Aufgaben

  • Einfache Java-App als Docker-Container verpacken
  • Erstellen Sie Ihren Kubernetes-Cluster in GKE.
  • Stellen Sie Ihre Java-Anwendung in Kubernetes in GKE bereit.
  • Den Dienst skalieren und ein Upgrade bereitstellen
  • Greifen Sie auf das Dashboard zu, eine webbasierte Kubernetes-Benutzeroberfläche.

Voraussetzungen

2. Einrichtung und Anforderungen

Umgebung zum selbstbestimmten Lernen einrichten

  1. Melden Sie sich in der Google Cloud Console an und erstellen Sie ein neues Projekt oder verwenden Sie ein vorhandenes. Wenn Sie noch kein Gmail- oder Google Workspace-Konto haben, müssen Sie eines erstellen.

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • Der Projektname ist der Anzeigename für die Teilnehmer dieses Projekts. Es handelt sich um einen String, der nicht von Google APIs verwendet wird. Sie können sie jederzeit aktualisieren.
  • Die Projekt-ID ist für alle Google Cloud-Projekte eindeutig und unveränderlich (kann nach dem Festlegen nicht mehr geändert werden). In der Cloud Console wird automatisch ein eindeutiger String generiert. Normalerweise ist es nicht wichtig, wie dieser String aussieht. In den meisten Codelabs müssen Sie auf Ihre Projekt-ID verweisen (in der Regel als PROJECT_ID angegeben). Wenn Ihnen die generierte ID nicht gefällt, können Sie eine andere zufällige ID generieren. Alternativ können Sie es mit einem eigenen Namen versuchen und sehen, ob er verfügbar ist. Sie kann nach diesem Schritt nicht mehr geändert werden und bleibt für die Dauer des Projekts bestehen.
  • Zur Information: Es gibt einen dritten Wert, die Projektnummer, die von einigen APIs verwendet wird. Weitere Informationen zu diesen drei Werten
  1. Als Nächstes müssen Sie die Abrechnung in der Cloud Console aktivieren, um Cloud-Ressourcen/-APIs zu verwenden. Die Durchführung dieses Codelabs kostet wenig oder gar nichts. Wenn Sie Ressourcen herunterfahren möchten, um Kosten zu vermeiden, die über diese Anleitung hinausgehen, können Sie die erstellten Ressourcen oder das Projekt löschen. Neue Google Cloud-Nutzer können am kostenlosen Testzeitraum mit einem Guthaben von 300$ teilnehmen.

Cloud Shell aktivieren

  1. Klicken Sie in der Cloud Console auf Cloud Shell aktivieren 853e55310c205094.png.

55efc1aaa7a4d3ad.png

Wenn Sie die Cloud Shell zum ersten Mal starten, wird ein Fenster mit einer Beschreibung eingeblendet. Klicken Sie in diesem Fall einfach auf Weiter.

9c92662c6a846a5c.png

Das Herstellen der Verbindung mit der Cloud Shell sollte nur wenige Augenblicke dauern.

9f0e51b578fecce5.png

Auf dieser virtuellen Maschine sind alle erforderlichen Entwicklungstools installiert. Sie bietet ein Basisverzeichnis mit 5 GB nichtflüchtigem Speicher und läuft in Google Cloud, was die Netzwerkleistung und Authentifizierung erheblich verbessert. Die meisten, wenn nicht sogar alle Aufgaben in diesem Codelab können mit einem Browser erledigt werden.

Sobald die Verbindung mit der Cloud Shell hergestellt ist, sehen Sie, dass Sie authentifiziert sind und für das Projekt Ihre Projekt-ID eingestellt ist.

  1. Führen Sie in der Cloud Shell den folgenden Befehl aus, um zu prüfen, ob Sie authentifiziert sind:
gcloud auth list

Befehlsausgabe

 Credentialed Accounts
ACTIVE  ACCOUNT
*       <my_account>@<my_domain.com>

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
  1. Führen Sie den folgenden Befehl in Cloud Shell aus, um zu bestätigen, dass der gcloud-Befehl Ihr Projekt kennt:
gcloud config list project

Befehlsausgabe

[core]
project = <PROJECT_ID>

Ist dies nicht der Fall, können Sie die Einstellung mit diesem Befehl vornehmen:

gcloud config set project <PROJECT_ID>

Befehlsausgabe

Updated property [core/project].

3. Quellcode abrufen

Nachdem Cloud Shell gestartet wurde, können Sie über die Befehlszeile den Beispielquellcode im Basisverzeichnis klonen.

$ git clone https://github.com/spring-guides/gs-spring-boot.git
$ cd gs-spring-boot/complete

4. App lokal ausführen

  1. Prüfen Sie, ob JAVA_HOME auf die richtige Version festgelegt ist:
$ export JAVA_HOME=/usr/lib/jvm/java-1.17.0-openjdk-amd64
  1. Sie können die Spring Boot-Anwendung wie gewohnt mit dem Spring Boot-Plug-in starten.
$ ./mvnw -DskipTests spring-boot:run
  1. Klicken Sie nach dem Start der App in der Cloud Shell-Symbolleiste auf Webvorschau1a94d5bd10bfc072.png und wählen Sie Vorschau auf Port 8080 aus.

6252b94905f3f7bd.png

Im Browser wird ein Tab geöffnet und eine Verbindung zum soeben gestarteten Server hergestellt.

9b6c29059957bd0.jpeg

5. Java-App als Docker-Container verpacken

Als Nächstes müssen Sie Ihre App darauf vorbereiten, in Kubernetes ausgeführt zu werden. Dazu legen Sie zuerst den Container und seine Inhalte fest.

  1. Erstellen Sie das JAR-Bereitstellungspaket für die App.
$ ./mvnw -DskipTests package
  1. Aktivieren Sie die Artifact Registry API, um das Container-Image zu speichern, das Sie erstellen.
$ gcloud services enable artifactregistry.googleapis.com
  1. Erstellen Sie ein neues Docker-Repository, falls noch keines vorhanden ist. Sie müssen ein Repository erstellen, bevor Sie Images per Push übertragen können:
$ gcloud artifacts repositories create codelabrepo     --repository-format=docker --location=us-central1 
  1. Ihr Bild hat das folgende Format:

{LOCATION}-docker.pkg.dev/{PROJECT-ID}/{REPOSITORY}/{IMAGE-NAME}

Wenn Sie das Repository beispielsweise am Standort us-central1 mit dem Namen codelabrepo erstellt haben und Ihr Image hello-java:v1 nennen möchten, lautet das Image:

us-central1-docker.pkg.dev/{PROJECT-ID}/codelabrepo/hello-java:v1

  1. Verwenden Sie Jib, um das Container-Image zu erstellen und per Push in die Artifact Registry zu übertragen.
$ export GOOGLE_CLOUD_PROJECT=`gcloud config list --format="value(core.project)"`

$ ./mvnw -DskipTests com.google.cloud.tools:jib-maven-plugin:build -Dimage=us-central1-docker.pkg.dev/${GOOGLE_CLOUD_PROJECT}/codelabrepo/hello-java:v1
  1. Das Container-Image sollte in der Cloud Console auf der Seite Artifact Registry-Images aufgeführt sein. Ihnen steht nun ein Docker-Image für das gesamte Projekt zur Verfügung, das sich mit Kubernetes aufrufen und orchestrieren lässt, wie Sie gleich sehen werden.
  2. Optional: Testen Sie das Image nach Abschluss des Vorgangs (es dauert einige Zeit, bis alles heruntergeladen und extrahiert ist) mit dem folgenden Befehl. Dadurch wird ein Docker-Container als Daemon von Ihrem neu erstellten Container-Image auf Port 8080 ausgeführt. Wenn Berechtigungsprobleme auftreten, führen Sie zuerst gcloud auth configure-docker us-central1-docker.pkg.dev aus:
$ docker run -ti --rm -p 8080:8080 \
  us-central1-docker.pkg.dev/$GOOGLE_CLOUD_PROJECT/codelabrepo/hello-java:v1
  1. Sie können dazu wieder die Webvorschau von Cloud Shell nutzen.

6252b94905f3f7bd.png

  1. Sie sollten nun die Standardseite in einem neuen Tab sehen. Nachdem Sie überprüft haben, dass die App lokal in einem Docker-Container ausgeführt wird, können Sie den Container durch Drücken von Control+C stoppen.

6. Cluster erstellen

Sie können jetzt Ihren GKE-Cluster erstellen. Ein Cluster besteht aus einem von Google verwalteten Kubernetes API-Server und einer Reihe von Worker-Knoten. Bei den Worker-Knoten handelt es sich um Compute Engine-VMs.

  1. Prüfen Sie zuerst, ob die zugehörigen API-Funktionen aktiviert sind.
$ gcloud services enable compute.googleapis.com container.googleapis.com
  1. Erstellen Sie einen Cluster mit zwei n1-standard-1-Knoten. Das kann einige Minuten dauern.
$ gcloud container clusters create hello-java-cluster \
  --num-nodes 2 \
  --machine-type n1-standard-1 \
  --zone us-central1-c

Am Ende sollten Sie den erstellten Cluster sehen.

Creating cluster hello-java-cluster...done.
Created [https://container.googleapis.com/v1/projects/...].
kubeconfig entry generated for hello-dotnet-cluster.
NAME                  ZONE            MASTER_VERSION  
hello-java-cluster  us-central1-c  ...

Sie sollten jetzt einen voll funktionsfähigen Kubernetes-Cluster haben, der von GKE bereitgestellt wird.

758c7fca14f70623.png

Und nun stellen Sie Ihre containerisierte Anwendung auf den Kubernetes-Clustern bereit. Ab jetzt verwenden Sie die Befehlszeile kubectl, die bereits in Ihrer Cloud Shell-Umgebung eingerichtet ist. Für den Rest des Codelabs ist es erforderlich, dass sowohl der Kubernetes-Client als auch der Server mindestens die Versionsnummer 1.2 hat. Mit kubectl version wird die aktuelle Version des Befehls angezeigt.

7. App in Kubernetes bereitstellen

  1. Mit einem Kubernetes-Deployment können mehrere Instanzen Ihrer App mit dem von Ihnen erstellten Container-Image erstellt, verwaltet und skaliert werden. Stellen Sie eine Instanz Ihrer App mit dem Befehl kubectl run in Kubernetes bereit.
$ kubectl create deployment hello-java --image=us-central1-docker.pkg.dev/$GOOGLE_CLOUD_PROJECT/codelabrepo/hello-java:v1
  1. Führen Sie einfach den folgenden Befehl aus, um sich das erstellte Deployment anzusehen:
$ kubectl get deployments

NAME         DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
hello-java   1         1         1            1           37s
  1. Führen Sie den folgenden Befehl aus, um die von der Bereitstellung erstellten App-Instanzen aufzurufen:
$ kubectl get pods

NAME                         READY     STATUS    RESTARTS   AGE
hello-java-714049816-ztzrb   1/1       Running   0          57s

Der Container wird nun unter Kubernetes ausgeführt. Sie müssen ihn jedoch noch für die Öffentlichkeit zugänglich machen.

8. Externen Traffic zulassen

Standardmäßig kann nur die interne IP innerhalb des Clusters auf den Pod zugreifen. Damit der hello-java-Container von außerhalb des virtuellen Kubernetes-Netzwerks zugänglich wird, müssen Sie den Pod als Kubernetes-Dienst zur Verfügung stellen.

  1. In Cloud Shell können Sie den Pod dem öffentlichen Internet zugänglich machen, indem Sie einen Kubernetes-LoadBalancer-Dienst erstellen.
$ kubectl create service loadbalancer hello-java --tcp=8080:8080

Hinweis: Sie machen das Deployment und nicht den Pod direkt verfügbar. Als Folge führt der resultierende Dienst ein Load Balancing des Traffics für alle vom Deployment verwalteten Pods durch (in diesem Fall nur für einen Pod, später werden jedoch weitere Replikate hinzugefügt).

Der Kubernetes-Master erstellt den Load Balancer und die zugehörigen Compute Engine-Weiterleitungsregeln, Zielpools und Firewallregeln, um den Dienst von außerhalb von Google Cloud vollständig zugänglich zu machen.

  1. Die öffentlich zugängliche IP-Adresse des Dienstes erhalten Sie, wenn Sie den Befehl kubectl ausführen. Damit können Sie sich alle Clusterdienste auflisten lassen.
$ kubectl get services

NAME         CLUSTER-IP     EXTERNAL-IP      PORT(S)    AGE
hello-java   10.3.253.62    aaa.bbb.ccc.ddd  8080/TCP    1m
kubernetes   10.3.240.1     <none>           443/TCP    5m
  1. Sie sollten den Dienst jetzt erreichen können. Verweisen Sie dazu Ihren Browser auf http://<EXTERNAL_IP>:8080.

9. Dienst skalieren

Eine der leistungsstarken Funktionen von Kubernetes ist die einfache Skalierung Ihrer App. Angenommen, Sie benötigen plötzlich mehr Kapazität für Ihre App. Sie können den Replikationscontroller einfach anweisen, eine neue Anzahl von Replikaten für Ihre App-Instanzen zu verwalten.

$ kubectl scale deployment hello-java --replicas=3

deployment "hello-java" scaled

$ kubectl get deployment
NAME         DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
hello-java   3         3         3            3           22m

Beachten Sie den deklarativen Ansatz. Anstatt neue Instanzen zu starten oder anzuhalten, deklarieren Sie, wie viele Instanzen zu jeder Zeit ausgeführt werden sollen. Die Abstimmungsschleifen von Kubernetes sorgen dafür, dass dies tatsächlich passiert und bei Bedarf Maßnahmen ergriffen werden.

10. Upgrade für Ihren Dienst bereitstellen

Früher oder später sind für die App, die Sie für die Produktion bereitgestellt haben, Fehlerbehebungen oder zusätzliche Funktionen erforderlich. Kubernetes unterstützt Sie bei der Bereitstellung einer neuen Version für die Produktion, ohne Ihre Nutzer zu beeinträchtigen.

  1. Öffnen Sie den Code-Editor, indem Sie im Cloud Shell-Menü auf Editor öffnen 2109d75686c889a.png klicken.
  2. Rufen Sie src/main/java/com/example/springboot/HelloController.java auf und aktualisieren Sie den Wert der Antwort.
package com.example.springboot;

import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RequestMapping;

@RestController
public class HelloController {

    @RequestMapping("/")
    public String index() {
        return "Greetings from Google Kubernetes Engine!";
    }
}
  1. Verwenden Sie Jib, um eine neue Version des Container-Images zu erstellen und per Push zu übertragen. Das Erstellen und Hochladen des aktualisierten Images sollte dank Caching deutlich schneller gehen.
$ ./mvnw -DskipTests package com.google.cloud.tools:jib-maven-plugin:build -Dimage=us-central1-docker.pkg.dev/$GOOGLE_CLOUD_PROJECT/codelabrepo/hello-java:v2

Sie können nun mit Kubernetes den Replikations-Controller problemlos auf die neue App-Version aktualisieren.

  1. Um das Image-Label Ihres Containers zu ändern, müssen Sie das bestehende hello-java-Deployment bearbeiten und das Image von us-central1-docker.pkg.dev/PROJECT_ID/codelabrepo/hello-java:v1

nach us-central1-docker.pkg.dev/PROJECT_ID/codelabrepo/hello-java:v2

  1. Mit dem Befehl kubectl set image können Sie Kubernetes anweisen, die neue Version Ihrer App mit Rolling Updates im gesamten Cluster bereitzustellen.
$ kubectl set image deployment/hello-java hello-java=us-central1-docker.pkg.dev/$GOOGLE_CLOUD_PROJECT/codelabrepo/hello-java:v2

deployment "hello-java" image updated
  1. Prüfen Sie noch einmal http://EXTERNAL_IP:8080, um zu sehen, ob die neue Antwort zurückgegeben wird.

11. Rollback durchführen

Hoppla! Haben Sie einen Fehler in einer neuen Version der App gemacht? Vielleicht enthält die neue Version einen Fehler und Sie müssen sie schnell zurücksetzen. Mit Kubernetes können Sie ganz einfach zum vorherigen Zustand zurückkehren. Machen Sie die App mit dem folgenden Befehl rückgängig:

$ kubectl rollout undo deployment/hello-java

Wenn Sie http://EXTERNAL_IP:8080 noch einmal aktivieren, sollte die alte Antwort wieder angezeigt werden.

12. Glückwunsch

Sie haben gelernt, wie Sie eine neue Java-basierte Webanwendung in Kubernetes in GKE erstellen und bereitstellen.

Aufräumen

$ gcloud container clusters delete hello-java-cluster --zone us-central1-c

$ gcloud container images delete us-central1-docker.pkg.dev/$GOOGLE_CLOUD_PROJECT/codelabrepo/hello-java:v1 us-central1-docker.pkg.dev/$GOOGLE_CLOUD_PROJECT/codelabrepo/hello-java:v2

Weitere Informationen