1. Panoramica
Informazioni su Micronaut
Micronaut è un moderno framework full stack basato su JVM per la creazione di applicazioni serverless e di microservizi modulari e facilmente testabili. Micronaut mira a offrire tempi di avvio rapidi, velocità effettiva elevata, con un utilizzo della memoria minimo. Gli sviluppatori possono sviluppare con Micronaut in Java, Groovy o Kotlin.
Micronaut offre:
- Tempi di avvio rapidi e consumo di memoria ridotto: i framework IoC basati sulla riflessione caricano e memorizzano nella cache i dati di riflessione per ogni singolo campo, metodo e costruttore nel codice, mentre con Micronaut, il tempo di avvio dell'applicazione e il consumo di memoria non sono legati alle dimensioni del codebase.
- Client HTTP dichiarativo, reattivo e tempo di compilazione: crea in modo dichiarativo client HTTP reattivi, implementati in fase di compilazione, riducendo il consumo di memoria.
- Server HTTP senza blocco basato su Netty: con una curva di apprendimento fluida, il server HTTP di Micronaut semplifica il più possibile l'esposizione delle API utilizzabili dai client HTTP.
- Test semplici e rapidi: avvia facilmente server e client nei test delle unità ed eseguili all'istante.
- Efficiente inserimento delle dipendenze e AOP in fase di compilazione: Micronaut fornisce una semplice API di programmazione orientata all'aspetto in fase di compilazione che non utilizza la riflessione.
- Crea app completamente reattive e non bloccanti: Micronaut supporta qualsiasi framework che implementa Reactive Streams, tra cui RxJava e Reactor.
Per ulteriori informazioni, visita il sito web di Microcronaut.
Informazioni su Kubernetes
Kubernetes è un progetto open source eseguibile in molti ambienti diversi, dai laptop ai cluster multinodo ad alta disponibilità, dai cloud pubblici alle implementazioni on-premise, dalle macchine virtuali alle soluzioni bare metal.
In questo lab eseguirai il deployment di un semplice microservizio Micronaut basato su Groovy su Kubernetes in esecuzione su Kubernetes Engine.
L'obiettivo di questo codelab è eseguire il tuo microservizio come servizio replicato in esecuzione su Kubernetes. Devi trasformare il codice che hai sviluppato sulla macchina in un'immagine container Docker ed eseguirla su Kubernetes Engine.
Ecco un diagramma delle varie parti in gioco in questo codelab per aiutarti a capire come si incastrano i vari pezzi. usalo come riferimento man mano che procedi nel codelab. dovrebbe essere tutto chiaro quando arrivi alla fine (ma ignora pure questo per ora).
Ai fini di questo codelab, l'utilizzo di un ambiente gestito come Kubernetes Engine (una versione di Kubernetes ospitata da Google in esecuzione su Compute Engine) ti consente di concentrarti maggiormente sull'utilizzo di Kubernetes anziché sulla configurazione dell'infrastruttura sottostante.
Se vuoi eseguire Kubernetes sulla tua macchina locale, ad esempio un laptop per lo sviluppo, probabilmente dovresti prendere in considerazione Minikube. Questa opzione offre una semplice configurazione di un cluster Kubernetes a nodo singolo per scopi di sviluppo e test. Se vuoi, puoi usare Minikube per seguire questo codelab.
Informazioni su Jib
Jib è uno strumento open source che consente di creare immagini Docker e OCI per le tue applicazioni Java. È disponibile come plug-in per Maven e Gradle e come libreria Java.
Jib mira a essere:
- Rapido: esegui rapidamente il deployment delle modifiche. Jib separa l'applicazione in più livelli, dividendo le dipendenze dalle classi. Ora non devi aspettare che Docker ricostruisci l'intera applicazione Java: devi solo eseguire il deployment dei livelli che sono stati modificati.
- Riproducibile: ricreare l'immagine container con gli stessi contenuti genera sempre la stessa immagine. Non attivare più un aggiornamento non necessario.
- Daemonless: riduci le dipendenze dell'interfaccia a riga di comando. Crea la tua immagine Docker da Maven o Gradle ed esegui il push a qualsiasi registro di tua scelta. Non dovrai più scrivere Dockerfile e chiamare docker build/push.
Per ulteriori informazioni su Jib, consulta la pagina del progetto GitHub.
Informazioni su questo tutorial
Questo tutorial utilizza il codice campione dello strumento Jib per creare container per applicazioni Java.
L'esempio è un semplice servizio Hello World che utilizza il framework Micronaut e il linguaggio di programmazione Apache Groovy.
Obiettivi didattici
- Pacchettizzare una semplice applicazione Java come container Docker utilizzando Jib
- Come creare un cluster Kubernetes su Kubernetes Engine.
- Eseguire il deployment del tuo servizio Micronaut in Kubernetes su Kubernetes Engine
- Come fare lo scale up del servizio e implementare un upgrade.
- Come accedere alla dashboard grafica di Kubernetes.
Che cosa ti serve
- Un progetto Google Cloud
- Un browser, ad esempio Chrome o Firefox
- Familiarità con gli editor di testo standard di Linux, ad esempio Vim, EMAC o Nano.
Come utilizzerai questo tutorial?
Come valuteresti la tua esperienza nello sviluppo di app web HTML/CSS?
Come giudichi la tua esperienza di utilizzo dei servizi della piattaforma Google Cloud?
2. Configurazione e requisiti
Configurazione dell'ambiente da seguire in modo autonomo
- Accedi alla console Cloud e crea un nuovo progetto o riutilizzane uno esistente. Se non hai ancora un account Gmail o G Suite, devi crearne uno.
Ricorda l'ID progetto, un nome univoco in tutti i progetti Google Cloud (il nome precedente è già stato utilizzato e non funzionerà correttamente). Verrà indicato più avanti in questo codelab come PROJECT_ID
.
- Successivamente, dovrai abilitare la fatturazione in Cloud Console per utilizzare le risorse Google Cloud.
Eseguire questo codelab non dovrebbe costare molto. Assicurati di seguire le istruzioni nella sezione "Pulizia" in cui viene spiegato come arrestare le risorse in modo da non incorrere in fatturazione oltre questo tutorial. I nuovi utenti di Google Cloud sono idonei al programma prova senza costi di 300$.
3. recupera il codice sorgente di esempio Micronaut
Dopo il lancio di Cloud Shell, puoi utilizzare la riga di comando per clonare il codice sorgente di esempio nella home directory e passare alla directory contenente il nostro servizio di esempio:
$ git clone https://github.com/GoogleContainerTools/jib.git
$ cd jib/examples/micronaut/
4. Una rapida occhiata al codice
Il nostro semplice servizio Micronaut è costituito da un controller che restituisce il famigerato messaggio Hello World:
@Controller("/hello") class HelloController { @Get("/") String index() { "Hello World" } }
Il controller HelloController
risponde alle richieste nel percorso /hello
e il metodo index()
accetta le richieste HTTP GET.
È disponibile anche una classe di test Spock per verificare che nell'output venga fornito il messaggio corretto.
class HelloControllerSpec extends Specification { @Shared @AutoCleanup EmbeddedServer embeddedServer = ApplicationContext.run(EmbeddedServer) @Shared @AutoCleanup RxHttpClient client = embeddedServer.applicationContext.createBean(RxHttpClient, embeddedServer.getURL()) void "test hello world response"() { when: HttpRequest request = HttpRequest.GET('/hello') String rsp = client.toBlocking().retrieve(request) then: rsp == "Hello World" } }
Più di un semplice test delle unità, questo test esegue in realtà lo stesso stack di server Micronaut (in base al framework Netty) eseguito in produzione. Pertanto, il comportamento del codice sarà lo stesso nel prodotto e nei test.
Per eseguire i test, puoi eseguire il comando seguente per verificare che non ci siano problemi:
./gradlew test
5. Esegui l'applicazione a livello locale
Puoi avviare il servizio Micronaut normalmente con il seguente comando Gradle:
$ ./gradlew run
Una volta avviata l'applicazione, puoi aprire un'istanza Cloud Shell aggiuntiva grazie alla piccola icona +, quindi verificare con curl che il risultato sia quello previsto:
$ curl localhost:8080/hello
Dovresti vedere anche un semplice "Hello World" .
6. Pacchettizzazione dell'applicazione come container Docker con Jib
A questo punto, prepara l'app per l'esecuzione su Kubernetes. A questo scopo, sfrutteremo Jib per fare il lavoro più duro al posto nostro, in quanto non dovremo contattare noi stessi un Dockerfile
.
Eseguiamo il comando per creare il container:
$ ./gradlew jibDockerBuild
Ecco l'output che dovresti visualizzare:
Tagging image with generated image reference micronaut-jib:0.1. If you'd like to specify a different tag, you can set the jib.to.image parameter in your build.gradle, or use the --im age=<MY IMAGE> commandline flag. Containerizing application to Docker daemon as micronaut-jib:0.1... warning: Base image 'gcr.io/distroless/java' does not use a specific image digest - build may not be reproducible Getting base image gcr.io/distroless/java... Building dependencies layer... Building resources layer... Building classes layer... Finalizing... Container entrypoint set to [java, -cp, /app/resources:/app/classes:/app/libs/*, example.micronaut.Application] Loading to Docker daemon... Built image to Docker daemon as micronaut-jib:0.1
Ora che l'immagine è stata creata, vediamo se riusciamo a vedere il nostro messaggio hello, eseguendo l'immagine Docker nella prima scheda di Cloud Shell:
$ docker run -it -p 8080:8080 micronaut-jib:0.1 16:57:20.255 [main] INFO i.m.context.env.DefaultEnvironment - Established active environments: [cloud, gcp] 16:57:23.203 [main] INFO io.micronaut.runtime.Micronaut - Startup completed in 2926ms. Server Running: http://97b7d76ccf3f:8080
Il nostro servizio è in esecuzione, quindi possiamo avviare il comando curl nella seconda scheda di Cloud Shell per vedere se funziona come previsto:
$ curl localhost:8080/hello Hello World
Puoi arrestare il container premendo Ctrl+C
in Cloud Shell.
7. Esegui il push del nostro servizio containerizzato nel registry
Ora che l'immagine funziona come previsto, puoi eseguirne il push in Google Container Registry, un repository privato per le tue immagini Docker accessibili da ogni progetto Google Cloud (ma anche dall'esterno della piattaforma Google Cloud).
Prima di poter eseguire il push al registry, assicurati che Container Registry sia abilitato per il nostro progetto, selezionando Strumenti > di Container Registry. Se non è abilitata, dovrebbe essere visualizzata la seguente finestra di dialogo, quindi fai clic su "Abilita API Container Registry" per abilitarlo:
Quando il registro è pronto, per eseguire il push dell'immagine al registro, avvia i seguenti comandi:
$ gcloud auth configure-docker $ docker tag micronaut-jib:0.1 \ gcr.io/$GOOGLE_CLOUD_PROJECT/micronaut-jib:0.1 $ docker push gcr.io/$GOOGLE_CLOUD_PROJECT/micronaut-jib:0.1
I comandi riportati sopra consentono a gcloud SDK di configurare e autorizzare docker a eseguire il push delle immagini alla tua istanza di Container Registry, di contrassegnare l'immagine in modo che punti alla sua posizione nel registro e di eseguirne il push nel registro.
Se tutto funziona correttamente, dopo un po' di tempo dovresti riuscire a vedere l'immagine container elencata nella console: Strumenti > di Container Registry. A questo punto hai a disposizione un'immagine Docker a livello di progetto a cui Kubernetes può accedere e orchestrare, come vedrai tra qualche minuto.
8. Crea il tuo cluster
Ora tutto è pronto per creare il tuo cluster Kubernetes Engine, ma prima vai alla sezione Google Kubernetes Engine della console web e attendi che il sistema venga inizializzato (l'operazione dovrebbe richiedere solo pochi secondi).
Un cluster è costituito da un server API master Kubernetes gestito da Google e da un insieme di nodi worker. I nodi worker sono macchine virtuali Compute Engine. Utilizza l'interfaccia a riga di comando gcloud
della sessione di CloudShell per creare un cluster con due nodi n1-standard-1
(il completamento dell'operazione richiederà alcuni minuti):
$ gcloud container clusters create hello-cluster \ --num-nodes 2 \ --machine-type n1-standard-1 \ --zone us-central1-c
Alla fine dovresti vedere il cluster creato.
Creating cluster hello-cluster in us-central1-c...done. Created [https://container.googleapis.com/v1/projects/mn-gke-test/zones/us-central1-c/clusters/hello-cluster]. To inspect the contents of your cluster, go to: https://console.cloud.google.com/kubernetes/workload_/gcloud/us-central1-c/hello-cluster?project=mn-gke-test kubeconfig entry generated for hello-cluster. NAME LOCATION MASTER_VERSION MASTER_IP MACHINE_TYPE NODE_VERSION NUM_NODES STATUS hello-cluster us-central1-c 1.9.7-gke.7 35.239.224.115 n1-standard-1 1.9.7-gke.7 2 RUNNING
A questo punto dovresti avere un cluster Kubernetes completamente funzionante basato su Google Kubernetes Engine:
È ora di eseguire il deployment della tua applicazione containerizzata nel cluster Kubernetes. D'ora in poi utilizzerai la riga di comando kubectl
(già configurata nel tuo ambiente Cloud Shell). La parte restante di questo codelab richiede che la versione del server e del client Kubernetes sia 1.2 o successiva. kubectl version
mostrerà la versione corrente del comando.
9. Esegui il deployment dell'applicazione in Kubernetes
Un deployment Kubernetes può creare, gestire e scalare più istanze della tua applicazione utilizzando l'immagine container che hai appena creato. Creiamo un deployment della tua applicazione in Kubernetes utilizzando il comando kubectl create deployment
:
$ kubectl create deployment hello-micronaut \ --image=gcr.io/$GOOGLE_CLOUD_PROJECT/micronaut-jib:0.1
Per visualizzare il deployment appena creato, esegui semplicemente:
$ kubectl get deployments NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE hello-micronaut 1 1 1 1 5m
Per visualizzare le istanze dell'applicazione create dal deployment, esegui questo comando:
$ kubectl get pods NAME READY STATUS RESTARTS AGE hello-micronaut-5647fb98c5-lh5h7 1/1 Running 0 5m
A questo punto, il container dovrebbe essere in esecuzione sotto il controllo di Kubernetes, ma devi comunque renderlo accessibile al mondo esterno.
10. Consenti traffico esterno
Per impostazione predefinita, il pod è accessibile solo dal suo IP interno all'interno del cluster. Per rendere il container hello-micronaut
accessibile dall'esterno della rete virtuale Kubernetes, devi esporre il pod come servizio Kubernetes.
Da Cloud Shell puoi esporre il pod alla rete internet pubblica con il comando kubectl expose
combinato con il flag --type=LoadBalancer
. Questo flag è obbligatorio per la creazione di un IP accessibile dall'esterno :
$ kubectl expose deployment hello-micronaut --type=LoadBalancer --port=8080
Il flag utilizzato in questo comando specifica che utilizzerai il bilanciatore del carico fornito dall'infrastruttura sottostante (in questo caso il bilanciatore del carico di Compute Engine). Tieni presente che esponi il deployment, non direttamente il pod. Ciò farà sì che il servizio risultante bilancia il carico del traffico tra tutti i pod gestiti dal deployment (in questo caso solo 1 pod, ma aggiungerai altre repliche in un secondo momento).
Il master Kubernetes crea il bilanciatore del carico e le relative regole di forwarding di Compute Engine, i pool di destinazione e le regole firewall per rendere il servizio completamente accessibile dall'esterno di Google Cloud Platform.
Per trovare l'indirizzo IP del servizio accessibile pubblicamente, richiedi semplicemente a kubectl
di elencare tutti i servizi del cluster:
$ kubectl get services NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE hello-micronaut LoadBalancer 10.39.243.251 aaa.bbb.ccc.ddd 8080:30354/TCP 1m kubernetes ClusterIP 10.39.240.1 <none> 443/TCP 31m
Tieni presente che sono elencati due indirizzi IP per il tuo servizio, entrambi sulla porta 8080
. uno è l'IP interno visibile solo all'interno della tua rete virtuale cloud; mentre l'altro è IP esterno con bilanciamento del carico. In questo esempio, l'indirizzo IP esterno è aaa.bbb.ccc.ddd
.
Ora dovresti essere in grado di accedere al servizio puntando il browser all'indirizzo: http://<EXTERNAL_IP>
:8080
/hello
11. Fai lo scale up del servizio
Una delle potenti funzionalità offerte da Kubernetes è la facilità di scalabilità dell'applicazione. Supponiamo che tu abbia improvvisamente bisogno di più capacità per la tua applicazione. puoi semplicemente indicare al controller di replica di gestire un nuovo numero di repliche per le istanze dell'applicazione:
$ kubectl scale deployment hello-micronaut --replicas=3 deployment.extensions "hello-micronaut" scaled $ kubectl get deployment NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE hello-micronaut 3 3 3 3 16m
Qui puoi notare l'approccio dichiarativo, anziché avviare o arrestare nuove istanze, devi dichiarare quante istanze devono essere in esecuzione in qualsiasi momento. I loop di riconciliazione di Kubernetes si limitano ad assicurarsi che la realtà corrisponda a quanto richiesto e intervengono, se necessario.
12. Implementa un upgrade del servizio
A un certo punto, l'applicazione di cui hai eseguito il deployment in produzione richiederà correzioni di bug o funzionalità aggiuntive. Kubernetes è a tua disposizione per aiutarti a eseguire il deployment di una nuova versione in produzione senza influire sugli utenti.
Innanzitutto, modifichiamo l'applicazione. Apri l'editor di codice da Cloud Shell.
Vai a /jib/examples/micronaut/src/main/groovy/example/micronaut/HelloController.groovy
e aggiorna il valore della risposta:
@Controller("/hello") class HelloController { @Get("/") String index() { "Hello Kubernetes World" } }
In /jib/examples/micronaut/build.gradle
, eseguiremo l'upgrade della versione della nostra immagine dalla 0.1 alla 0.2 aggiornando questa riga:
version '0.2'
Quindi ricrea e pacchettizza l'applicazione con le ultime modifiche:
$ ./gradlew jibDockerBuild
Tagga ed esegui il push dell'immagine nel registro delle immagini container:
$ docker tag micronaut-jib:0.2 \ gcr.io/$GOOGLE_CLOUD_PROJECT/micronaut-jib:0.2 $ docker push gcr.io/$GOOGLE_CLOUD_PROJECT/micronaut-jib:0.2
Ora è tutto pronto per consentire a Kubernetes di aggiornare senza problemi il controller di replica alla nuova versione dell'applicazione. Per cambiare l'etichetta dell'immagine per il container in esecuzione, devi modificare il valore hello-micronaut deployment
esistente e cambiare l'immagine da gcr.io/PROJECT_ID/micronaut-jib:0.1
a gcr.io/PROJECT_ID/micronaut-jib:0.2
.
Puoi utilizzare il comando kubectl set image
per chiedere a Kubernetes di eseguire il deployment della nuova versione dell'applicazione nell'intero cluster un'istanza alla volta con l'aggiornamento in sequenza:
$ kubectl set image deployment/hello-micronaut \ micronaut-jib=gcr.io/$GOOGLE_CLOUD_PROJECT/micronaut-jib:0.2 deployment.apps "hello-micronaut" image updated
Controlla di nuovo http://EXTERNAL_IP:8080 per verificare che stia restituendo la nuova risposta.
13. Rollback
Ops! Hai commesso un errore con una nuova versione dell'applicazione? Forse la nuova versione conteneva un errore e dovrai eseguire rapidamente il rollback. Con Kubernetes, puoi facilmente eseguire il rollback allo stato precedente. Eseguiamo il rollback dell'applicazione eseguendo:
$ kubectl rollout undo deployment/hello-micronaut
Se diamo un'occhiata all'output del servizio, torneremo alla versione iniziale "Hello World" .
14. Riepilogo
In questo passaggio hai configurato un semplice servizio Hello World Micronaut basato su Apache Groovy, lo hai eseguito direttamente da Cloud Shell, lo hai pacchettizzato come container con Jib e ne hai eseguito il deployment in Google Kubernetes Engine.
15. Complimenti!
Hai imparato a creare ed eseguire il deployment di un nuovo microservizio basato sul web Apache Groovy / Micronaut su Kubernetes su Google Kubernetes Engine.
Scopri di più
- Documentazione ed esempi di Jib: https://github.com/GoogleContainerTools/jib/
- Sito web dei micronaut: http://micronaut.io/
- Java su Google Cloud: https://cloud.google.com/java/
- Per esempi di Java: https://cloud.google.com/java/samples
- Per un tutorial più lungo e completo di Kubernetes, vedi bit.ly/k8s-lab, dove ti guiderà attraverso il deployment di un'applicazione full stack.
Licenza
Questo lavoro è concesso in licenza ai sensi di una licenza Creative Commons Attribution 2.0 Generic.