Esegui il deployment di un'app Java Spring Boot in Kubernetes su Google Kubernetes Engine

1. Prima di iniziare

Kubernetes è un progetto open source eseguibile in molti ambienti diversi, dai laptop ai cluster multinodo ad alta disponibilità, dai cloud pubblici ai deployment on-premise e dalle istanze di macchine virtuali (VM) al bare metal.

In questo codelab, eseguirai il deployment di una semplice app web Java Spring Boot in Kubernetes su GKE, con l'obiettivo di eseguire l'app web come app replicata su Kubernetes. Prenderai il codice che sviluppi sulla tua macchina, lo trasformerai in un'immagine container Docker ed eseguirai l'immagine su GKE.

Utilizzerai GKE, un servizio Kubernetes completamente gestito su Google Cloud, per concentrarti maggiormente sull'utilizzo di Kubernetes anziché sulla configurazione dell'infrastruttura sottostante.

Se ti interessa eseguire Kubernetes sulla tua macchina locale, ad esempio un laptop di sviluppo, dai un'occhiata a Minikube, che offre una semplice configurazione di un cluster Kubernetes a un solo nodo per scopi di sviluppo e test. Se vuoi, puoi utilizzare Minikube per completare il codelab.

Il codelab utilizzerà il codice di esempio della guida su Creazione di un'app con Spring Boot.

Prerequisiti

  • Familiarità con il linguaggio di programmazione Java e gli strumenti
  • Conoscenza degli editor di testo standard di Linux, ad esempio Vim, Emacs e nano

Attività previste

  • Pacchettizza una semplice app Java come container Docker.
  • Crea il cluster Kubernetes su GKE.
  • Esegui il deployment della tua app Java in Kubernetes su GKE.
  • Aumenta le dimensioni del tuo servizio ed esegui il deployment di un upgrade.
  • Accedi a Dashboard, un'interfaccia utente Kubernetes basata sul web.

Che cosa ti serve

2. Configurazione e requisiti

Configurazione dell'ambiente autonomo

  1. Accedi alla console Google Cloud e crea un nuovo progetto o riutilizzane uno esistente. Se non hai ancora un account Gmail o Google Workspace, devi crearne uno.

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • Il nome del progetto è il nome visualizzato per i partecipanti a questo progetto. È una stringa di caratteri non utilizzata dalle API di Google. Puoi sempre aggiornarlo.
  • L'ID progetto è univoco in tutti i progetti Google Cloud ed è immutabile (non può essere modificato dopo l'impostazione). La console Cloud genera automaticamente una stringa univoca, di solito non ti interessa di cosa si tratta. Nella maggior parte dei codelab, dovrai fare riferimento all'ID progetto (in genere identificato come PROJECT_ID). Se l'ID generato non ti piace, puoi generarne un altro casuale. In alternativa, puoi provare a crearne uno e vedere se è disponibile. Non può essere modificato dopo questo passaggio e rimane per tutta la durata del progetto.
  • Per tua informazione, esiste un terzo valore, un numero di progetto, utilizzato da alcune API. Scopri di più su tutti e tre questi valori nella documentazione.
  1. Successivamente, devi abilitare la fatturazione in Cloud Console per utilizzare le risorse/API Cloud. Completare questo codelab non costa molto, se non nulla. Per arrestare le risorse ed evitare addebiti oltre a quelli previsti in questo tutorial, puoi eliminare le risorse che hai creato o il progetto. I nuovi utenti di Google Cloud possono beneficiare del programma prova senza costi di 300$.

Attiva Cloud Shell

  1. Nella console Cloud, fai clic su Attiva Cloud Shell 853e55310c205094.png.

55efc1aaa7a4d3ad.png

Se è la prima volta che avvii Cloud Shell, viene visualizzata una schermata intermedia che ne descrive le funzionalità. Se è stata visualizzata una schermata intermedia, fai clic su Continua.

9c92662c6a846a5c.png

Bastano pochi istanti per eseguire il provisioning e connettersi a Cloud Shell.

9f0e51b578fecce5.png

Questa macchina virtuale è caricata con tutti gli strumenti di sviluppo necessari. Offre una home directory permanente da 5 GB e viene eseguita in Google Cloud, migliorando notevolmente le prestazioni e l'autenticazione della rete. Gran parte del lavoro per questo codelab, se non tutto, può essere svolto con un browser.

Una volta eseguita la connessione a Cloud Shell, dovresti vedere che il tuo account è autenticato e il progetto è impostato sul tuo ID progetto.

  1. Esegui questo comando in Cloud Shell per verificare che l'account sia autenticato:
gcloud auth list

Output comando

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

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
  1. Esegui questo comando in Cloud Shell per verificare che il comando gcloud conosca il tuo progetto:
gcloud config list project

Output comando

[core]
project = <PROJECT_ID>

In caso contrario, puoi impostarlo con questo comando:

gcloud config set project <PROJECT_ID>

Output comando

Updated property [core/project].

3. Recuperare il codice sorgente

Dopo l'avvio di Cloud Shell, puoi utilizzare la riga di comando per clonare il codice sorgente di esempio nella directory home.

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

4. Esegui l'app localmente

  1. Assicurati che JAVA_HOME sia impostato sulla versione corretta:
$ export JAVA_HOME=/usr/lib/jvm/java-1.17.0-openjdk-amd64
  1. Puoi avviare l'app Spring Boot normalmente con il plug-in Spring Boot.
$ ./mvnw -DskipTests spring-boot:run
  1. Dopo l'avvio dell'app, fai clic su Anteprima web 1a94d5bd10bfc072.pngnella barra degli strumenti di Cloud Shell e seleziona Anteprima sulla porta 8080.

6252b94905f3f7bd.png

Si apre una scheda nel browser e si connette al server appena avviato.

9b6c29059957bd0.jpeg

5. Pacchettizzare l'app Java come container Docker

Poi, devi preparare l'app per l'esecuzione su Kubernetes. Il primo passaggio consiste nel definire il contenitore e i relativi contenuti.

  1. Crea il file JAR di cui è possibile eseguire il deployment per l'app.
$ ./mvnw -DskipTests package
  1. Abilita l'API Artifact Registry per archiviare l'immagine container che creerai.
$ gcloud services enable artifactregistry.googleapis.com
  1. Crea un nuovo repository Docker se non ne esiste uno. Prima di eseguire il push delle immagini, devi creare un repository:
$ gcloud artifacts repositories create codelabrepo     --repository-format=docker --location=us-central1 
  1. L'immagine avrà il formato:

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

Ad esempio, se hai creato il repository nella località us-central1 denominato codelabrepo e vuoi chiamare la tua immagine hello-java:v1, l'immagine sarà:

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

  1. Utilizza Jib per creare l'immagine container ed eseguirne il push su Artifact Registry.
$ 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. Dovresti essere in grado di visualizzare l'immagine container elencata nella console accedendo alla pagina Immagini di Artifact Registry nella console Google Cloud. Ora hai a disposizione un'immagine Docker a livello di progetto, a cui Kubernetes può accedere e che può orchestrare, come vedrai tra qualche minuto.
  2. (Facoltativo) Al termine (ci vorrà un po' di tempo per scaricare ed estrarre tutto), testa l'immagine con il seguente comando, che eseguirà un container Docker come daemon sulla porta 8080 dalla nuova immagine container creata. Se riscontri problemi di autorizzazione, esegui prima gcloud auth configure-docker us-central1-docker.pkg.dev:
$ docker run -ti --rm -p 8080:8080 \
  us-central1-docker.pkg.dev/$GOOGLE_CLOUD_PROJECT/codelabrepo/hello-java:v1
  1. Anche in questo caso, sfrutta la funzionalità di anteprima web di Cloud Shell.

6252b94905f3f7bd.png

  1. Dovresti vedere la pagina predefinita in una nuova scheda. Dopo aver verificato che l'app è in esecuzione localmente in un container Docker, puoi arrestare il container in esecuzione premendo Control+C.

6. Crea il cluster

Ora puoi creare il cluster GKE. Un cluster è costituito da un server API Kubernetes gestito da Google e da un insieme di nodi worker. I nodi worker sono VM di Compute Engine.

  1. Innanzitutto, assicurati che le funzionalità API correlate siano abilitate.
$ gcloud services enable compute.googleapis.com container.googleapis.com
  1. Crea un cluster con due nodi n1-standard-1 (il completamento dell'operazione richiederà alcuni minuti).
$ gcloud container clusters create hello-java-cluster \
  --num-nodes 2 \
  --machine-type n1-standard-1 \
  --zone us-central1-c

Alla fine, dovresti vedere il cluster creato.

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  ...

Ora dovresti avere un cluster Kubernetes completamente funzionante basato su GKE.

758c7fca14f70623.png

Ora è il momento di eseguire il deployment dell'app containerizzata nel cluster Kubernetes. D'ora in poi, utilizzerai la riga di comando kubectl (già configurata nel tuo ambiente Cloud Shell). Il resto del codelab richiede che la versione del client e del server Kubernetes sia 1.2 o successive. kubectl version mostrerà la versione attuale del comando.

7. Esegui il deployment dell'app in Kubernetes

  1. Un deployment Kubernetes può creare, gestire e scalare più istanze della tua app utilizzando l'immagine container che hai creato. Esegui il deployment di un'istanza della tua app in Kubernetes utilizzando il comando kubectl run.
$ kubectl create deployment hello-java --image=us-central1-docker.pkg.dev/$GOOGLE_CLOUD_PROJECT/codelabrepo/hello-java:v1
  1. Per visualizzare il deployment che hai creato, esegui questo comando:
$ kubectl get deployments

NAME         DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
hello-java   1         1         1            1           37s
  1. Per visualizzare le istanze dell'app create dal deployment, esegui questo comando:
$ kubectl get pods

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

A questo punto, il container dovrebbe essere in esecuzione sotto il controllo di Kubernetes, ma devi ancora renderlo accessibile al mondo esterno.

8. Consenti traffico esterno

Per impostazione predefinita, il pod è accessibile solo tramite il suo IP interno all'interno del cluster. Per rendere accessibile il container hello-java dall'esterno della rete virtuale Kubernetes, devi esporre il pod come servizio Kubernetes.

  1. In Cloud Shell, puoi esporre il pod a internet pubblico creando un servizio Kubernetes LoadBalancer.
$ kubectl create service loadbalancer hello-java --tcp=8080:8080

Tieni presente che esponi direttamente il deployment, non il pod. In questo modo, il servizio risultante bilancia il carico del traffico su tutti i pod gestiti dal deployment (in questo caso, un solo pod, ma in seguito aggiungerai altre repliche).

Il master Kubernetes crea il bilanciatore del carico e le regole di forwarding, i pool di destinazione e le regole firewall di Compute Engine correlate per rendere il servizio completamente accessibile dall'esterno di Google Cloud.

  1. Per trovare l'indirizzo IP accessibile pubblicamente del servizio, richiedi semplicemente kubectl per elencare tutti i servizi del cluster.
$ 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. Ora dovresti essere in grado di raggiungere il servizio puntando il browser su http://<EXTERNAL_IP>:8080.

9. Scalare il servizio

Una delle potenti funzionalità offerte da Kubernetes è la facilità di scalabilità della tua app. Supponiamo che tu abbia improvvisamente bisogno di più capacità per la tua app. Puoi semplicemente chiedere al controller di replica di gestire un nuovo numero di repliche per le istanze dell'app.

$ 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

Nota l'approccio dichiarativo. Anziché avviare o arrestare nuove istanze, dichiari quante istanze devono essere in esecuzione in qualsiasi momento. I cicli di riconciliazione di Kubernetes si assicurano semplicemente che la realtà corrisponda a ciò che hai richiesto e intervengono, se necessario.

10. Implementa ed esegui l'upgrade del servizio

A un certo punto, l'app di cui hai eseguito il deployment in produzione richiederà correzioni di bug o funzionalità aggiuntive. Kubernetes può aiutarti a eseguire il deployment di una nuova versione in produzione senza influire sugli utenti.

  1. Apri l'editor di codice facendo clic su Apri editor 2109d75686c889a.pngnel menu di Cloud Shell.
  2. Vai a src/main/java/com/example/springboot/HelloController.java e aggiorna il valore della risposta.
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. Utilizza Jib per creare ed eseguire il push di una nuova versione dell'immagine container. La creazione e il push dell'immagine aggiornata dovrebbero essere molto più rapidi, in quanto sfrutti appieno la memorizzazione nella cache.
$ ./mvnw -DskipTests package com.google.cloud.tools:jib-maven-plugin:build -Dimage=us-central1-docker.pkg.dev/$GOOGLE_CLOUD_PROJECT/codelabrepo/hello-java:v2

Ora Kubernetes può aggiornare senza problemi il controller di replica alla nuova versione dell'app.

  1. Per modificare l'etichetta dell'immagine per il container in esecuzione, devi modificare il deployment hello-java esistente e cambiare l'immagine da us-central1-docker.pkg.dev/PROJECT_ID/codelabrepo/hello-java:v1

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

  1. Puoi utilizzare il comando kubectl set image per chiedere a Kubernetes di eseguire il deployment della nuova versione dell'app nell'intero cluster un'istanza alla volta con gli aggiornamenti in sequenza.
$ 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. Controlla di nuovo http://EXTERNAL_IP:8080 per verificare che restituisca la nuova risposta.

11. Rollback

Spiacenti. Hai commesso un errore con una nuova versione dell'app? Forse la nuova versione conteneva un errore e devi eseguire rapidamente il rollback. Con Kubernetes, puoi eseguire facilmente il rollback allo stato precedente. Esegui il rollback dell'app eseguendo questo comando:

$ kubectl rollout undo deployment/hello-java

Dovresti vedere la vecchia risposta quando controlli di nuovo http://EXTERNAL_IP:8080.

12. Complimenti

Hai imparato a creare ed eseguire il deployment di una nuova app web basata su Java in Kubernetes su GKE.

Pulizia

$ 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

Scopri di più