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

1. Hinweis

Kubernetes ist ein Open-Source-Projekt, das in vielen verschiedenen Umgebungen ausgeführt werden kann – von Laptops bis hin zu hochverfügbaren Clustern mit mehreren Knoten, von öffentlichen Clouds bis hin zu lokalen Bereitstellungen und von VM-Instanzen bis hin zu Bare-Metal-Instanzen.

In diesem Codelab stellen Sie eine einfache Spring Boot-Java-Webanwendung in Kubernetes in GKE bereit. Ihr Ziel ist es, Ihre Webanwendung als replizierte Anwendung in Kubernetes auszuführen. Dabei wandeln Sie Code, den Sie auf Ihrem Computer entwickeln, in ein Docker-Container-Image um und führen das Image in GKE aus.

Sie verwenden GKE, einen vollständig verwalteten Kubernetes-Dienst in Google Cloud, damit Sie sich mehr auf die Arbeit mit Kubernetes konzentrieren können, anstatt die zugrunde liegende Infrastruktur einzurichten.

Wenn Sie Kubernetes auf einem lokalen Computer ausführen möchten, z. B. auf einem Entwicklungslaptop, sollten Sie sich Minikube ansehen. Damit lässt sich ein Kubernetes-Cluster mit einem einzelnen Knoten zu Entwicklungs- und Testzwecken ganz einfach einrichten. Sie können Minikube auch verwenden, um das Codelab zu durchlaufen.

Für das Codelab wird der Beispielcode aus der Anleitung zum Erstellen einer Anwendung mit Spring Boot verwendet.

Voraussetzungen

  • Vertrautheit mit der Programmiersprache und -tools von Java
  • Kenntnisse in standardmäßigen Linux-Texteditoren wie vim, emacs und nano

Aufgabe

  • Einfache Java-Anwendung als Docker-Container verpacken
  • Erstellen Sie den Kubernetes-Cluster in GKE.
  • Stellen Sie Ihre Java-Anwendung in Kubernetes in GKE bereit.
  • Dienst skalieren und ein Upgrade einführen
  • Rufen Sie das Dashboard auf, eine webbasierte Kubernetes-Benutzeroberfläche.

Voraussetzungen

2. Einrichtung und Anforderungen

Umgebung für das selbstbestimmte Lernen einrichten

  1. Melden Sie sich in der Google Cloud Console an und erstellen Sie ein neues Projekt oder verwenden Sie ein vorhandenes Projekt. 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 Projektteilnehmer. Es handelt sich um eine Zeichenfolge, die von Google APIs nicht verwendet wird. Sie können sie jederzeit aktualisieren.
  • Die Projekt-ID ist für alle Google Cloud-Projekte eindeutig und unveränderlich. Sie kann nach dem Festlegen nicht mehr geändert werden. Die Cloud Console generiert automatisch einen eindeutigen String. ist Ihnen meist egal, was es ist. In den meisten Codelabs musst du auf deine Projekt-ID verweisen, die üblicherweise als PROJECT_ID bezeichnet wird. Wenn Ihnen die generierte ID nicht gefällt, können Sie eine weitere zufällige ID generieren. Alternativ können Sie einen eigenen verwenden und nachsehen, ob er verfügbar ist. Sie kann nach diesem Schritt nicht mehr geändert werden und bleibt für die Dauer des Projekts erhalten.
  • Zur Information gibt es noch einen dritten Wert, die Projektnummer, die von manchen APIs verwendet wird. Weitere Informationen zu allen drei Werten finden Sie in der Dokumentation.
  1. Als Nächstes müssen Sie in der Cloud Console die Abrechnung aktivieren, um Cloud-Ressourcen/APIs verwenden zu können. Dieses Codelab ist kostengünstig. Sie können die von Ihnen erstellten Ressourcen oder das Projekt löschen, um Ressourcen herunterzufahren, um zu vermeiden, dass über diese Anleitung hinaus Kosten anfallen. Neue Google Cloud-Nutzer haben Anspruch auf das kostenlose Testprogramm mit 300$Guthaben.

Cloud Shell aktivieren

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

55efc1aaa7a4d3ad.png

Wenn Sie Cloud Shell zum ersten Mal starten, wird ein Zwischenbildschirm mit einer Beschreibung der Funktion angezeigt. Wenn ein Zwischenbildschirm angezeigt wird, klicken Sie auf Weiter.

9c92662c6a846a5c.png

Die Bereitstellung und Verbindung mit Cloud Shell dauert nur einen Moment.

9f0e51b578fecce5.png

Diese virtuelle Maschine verfügt über alle erforderlichen Entwicklertools. Es bietet ein Basisverzeichnis mit 5 GB nichtflüchtigem Speicher und wird in Google Cloud ausgeführt. Dadurch werden die Netzwerkleistung und die Authentifizierung erheblich verbessert. Viele, wenn nicht sogar alle Arbeiten in diesem Codelab können mit einem Browser erledigt werden.

Sobald Sie mit Cloud Shell verbunden sind, sollten Sie sehen, dass Sie authentifiziert sind und das Projekt auf Ihre Projekt-ID eingestellt ist.

  1. Führen Sie in 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 in Cloud Shell den folgenden Befehl aus, um zu prüfen, ob 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

Nach dem Start von Cloud Shell 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. Vergewissern Sie sich, dass JAVA_HOME auf die richtige Version eingestellt ist:
$ export JAVA_HOME=/usr/lib/jvm/java-1.17.0-openjdk-amd64
  1. Sie können die Spring Boot-Anwendung normal mit dem Spring Boot-Plug-in starten.
$ ./mvnw -DskipTests spring-boot:run
  1. Klicken Sie nach dem Start der Anwendung 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-Anwendung als Docker-Container verpacken

Als Nächstes müssen Sie Ihre Anwendung für die Ausführung in Kubernetes vorbereiten. Dazu legen Sie zuerst den Container und seine Inhalte fest.

  1. Erstellen Sie die bereitstellbare JAR-Datei für die Anwendung.
$ ./mvnw -DskipTests package
  1. Aktivieren Sie die Artifact Registry API, um das zu erstellende Container-Image zu speichern.
$ 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 an das Repository übertragen können:
$ gcloud artifacts repositories create codelabrepo     --repository-format=docker --location=us-central1 
  1. Ihr Bild hat folgendes Format:

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

Wenn Sie beispielsweise das Repository am Standort us-central1 codelabrepo erstellt haben und Ihr Image hello-java:v1 benennen 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 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 Console aufgelistet sein. Rufen Sie dazu in der Cloud Console die Artifacts Registry-Images auf. Ihnen steht jetzt ein projektweites Docker-Image zur Verfügung, auf das Kubernetes zugreifen und es orchestrieren kann, wie Sie in wenigen Minuten sehen werden.
  2. (Optional) Nach Abschluss des Vorgangs (es dauert einige Zeit, bis alles heruntergeladen und extrahiert werden kann) testen Sie das Image mit dem folgenden Befehl. Dadurch wird ein Docker-Container als Daemon auf Port 8080 aus dem neu erstellten Container-Image 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. Nutzen Sie wieder die Webvorschaufunktion von Cloud Shell.

6252b94905f3f7bd.png

  1. Die Standardseite sollte in einem neuen Tab angezeigt werden. Nachdem Sie überprüft haben, ob die Anwendung lokal in einem Docker-Container ausgeführt wird, können Sie den ausgeführten Container mit Control+C beenden.

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. Die Worker-Knoten sind Compute Engine-VMs.

  1. Stellen Sie zunächst sicher, dass 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. Dies 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 auf GKE basiert.

758c7fca14f70623.png

Jetzt ist es an der Zeit, Ihre Containeranwendung im Kubernetes-Cluster bereitzustellen. Ab jetzt verwenden Sie die kubectl-Befehlszeile, die bereits in Ihrer Cloud Shell-Umgebung eingerichtet ist. Für den Rest des Codelabs müssen der Kubernetes-Client und die Serverversion mindestens Version 1.2 sein. kubectl version zeigt Ihnen die aktuelle Version des Befehls an.

7. Anwendung in Kubernetes bereitstellen

  1. Mit einem Kubernetes-Deployment können Sie mithilfe des von Ihnen erstellten Container-Images mehrere Instanzen Ihrer Anwendung erstellen, verwalten und skalieren. Stellen Sie mit dem Befehl kubectl run eine Instanz der Anwendung 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 die von Ihnen erstellte Bereitstellung anzuzeigen:
$ 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 Anwendungsinstanzen aufzurufen:
$ kubectl get pods

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

Zu diesem Zeitpunkt sollte Ihr Container unter der Kontrolle von Kubernetes ausgeführt werden, aber Sie müssen ihn dennoch für die Außenwelt zugänglich machen.

8. Externen Traffic zulassen

Standardmäßig ist der Pod nur über seine interne IP-Adresse im Cluster zugänglich. Damit der hello-java-Container von außerhalb des virtuellen Kubernetes-Netzwerks zugänglich ist, müssen Sie den Pod als Kubernetes-Dienst verfügbar machen.

  1. In Cloud Shell können Sie den Pod durch Erstellen eines Kubernetes LoadBalancer-Dienstes für das öffentliche Internet freigeben.
$ kubectl create service loadbalancer hello-java --tcp=8080:8080

Beachten Sie, dass Sie das Deployment direkt freigeben, nicht den Pod. Dadurch führt der resultierende Dienst das Load-Balancing des Traffics für alle Pods durch, die vom Deployment verwaltet werden (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. Wenn Sie die öffentlich zugängliche IP-Adresse des Dienstes ermitteln möchten, fordern Sie einfach kubectl an, um alle Clusterdienste aufzulisten.
$ 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, indem Sie in Ihrem Browser http://<EXTERNAL_IP>:8080 aufrufen.

9. Dienst skalieren

Eines der leistungsstarken Features von Kubernetes ist die einfache Skalierung Ihrer Anwendung. Angenommen, Sie benötigen plötzlich mehr Kapazität für Ihre Anwendung. Sie können den Replikations-Controller einfach anweisen, eine neue Anzahl von Replikaten für Ihre Anwendungsinstanzen 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. Kubernetes-Abgleichsschleifen sorgen einfach dafür, dass die Realität Ihren Anforderungen entspricht, und ergreifen bei Bedarf Maßnahmen.

10. Upgrade für Ihren Dienst bereitstellen

Irgendwann sind für die App, die Sie für die Produktion bereitgestellt haben, Fehlerbehebungen oder zusätzliche Funktionen erforderlich. Kubernetes kann Sie dabei unterstützen, eine neue Version ohne Beeinträchtigung Ihrer Nutzer für die Produktion bereitzustellen.

  1. Öffnen Sie den Code-Editor, indem Sie im Cloud Shell-Menü auf Editor öffnen 2109d75686c889a.png klicken.
  2. Gehen Sie zu src/main/java/com/example/springboot/HelloController.java 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. Mit Jib eine neue Version des Container-Images erstellen und per Push ü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

Kubernetes kann Ihren Replikationscontroller reibungslos auf die neue Version der Anwendung aktualisieren.

  1. Wenn Sie das Image-Label für Ihren laufenden Container ändern möchten, müssen Sie das vorhandene hello-java-Deployment bearbeiten und das Image von us-central1-docker.pkg.dev/PROJECT_ID/codelabrepo/hello-java:v1 ändern

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 Anwendung instanziierend und 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 http://EXTERNAL_IP:8080 noch einmal, um zu sehen, ob die neue Antwort zurückgegeben wird.

11. Rollback durchführen

Hoppla! Haben Sie bei der Aktualisierung der App einen Fehler gemacht? Möglicherweise enthielt die neue Version einen Fehler und Sie müssen schnell ein Rollback durchführen. Mit Kubernetes können Sie einfach ein Rollback zum vorherigen Status durchführen. Führen Sie den folgenden Befehl aus, um ein Rollback der Anwendung durchzuführen:

$ kubectl rollout undo deployment/hello-java

Sie sollten die alte Antwort sehen, wenn Sie http://EXTERNAL_IP:8080 noch einmal prüfen.

12. Glückwunsch

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

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