Déployer une application Java Spring Boot dans Kubernetes sur Google Kubernetes Engine

1. Avant de commencer

Kubernetes est un projet Open Source qui peut s'exécuter dans de nombreux environnements différents : ordinateurs portables, clusters multinœuds haute disponibilité, clouds publics, déploiements sur site, instances de machines virtuelles (VM) et solutions Bare Metal.

Dans cet atelier de programmation, vous allez déployer une application Web Java Spring Boot simple sur Kubernetes sur GKE. L'objectif est d'exécuter votre application Web en tant qu'application répliquée sur Kubernetes. Vous allez utiliser le code que vous développez sur votre machine, le transformer en image de conteneur Docker et exécuter cette image sur GKE.

Vous utiliserez GKE, un service Kubernetes entièrement géré sur Google Cloud, qui vous permettra de vous concentrer sur l'expérience de Kubernetes plutôt que sur la configuration de l'infrastructure sous-jacente.

Si vous souhaitez exécuter Kubernetes sur un ordinateur local, tel qu'un ordinateur portable de développement, optez pour Minikube, qui propose une configuration simple d'un cluster Kubernetes à nœud unique à des fins de développement et de test. Si vous le souhaitez, vous pouvez utiliser Minikube dans cet atelier de programmation.

L'atelier de programmation utilise l'exemple de code du guide Créer une application avec Spring Boot.

Prérequis

  • Connaissance des outils et du langage de programmation Java
  • Connaissance des éditeurs de texte Linux standards tels que Vim, Emacs et nano

Objectifs de l'atelier

  • Empaqueter une application Java simple en tant que conteneur Docker
  • Créez votre cluster Kubernetes sur GKE.
  • Déployez votre application Java sur Kubernetes sur GKE.
  • Augmentez la capacité de votre service et déployez une mise à niveau.
  • Accédez au tableau de bord, une interface utilisateur Kubernetes basée sur le Web.

Prérequis

2. Préparation

Configuration de l'environnement au rythme de chacun

  1. Connectez-vous à la console Google Cloud, puis créez un projet ou réutilisez un projet existant. (Si vous ne possédez pas encore de compte Gmail ou Google Workspace, vous devez en créer un.)

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • Le nom du projet est le nom à afficher pour les participants au projet. Il s'agit d'une chaîne de caractères non utilisée par les API Google. Vous pourrez toujours le modifier.
  • L'ID du projet est unique parmi tous les projets Google Cloud et non modifiable une fois défini. La console Cloud génère automatiquement une chaîne unique (en général, vous n'y accordez d'importance particulière). Dans la plupart des ateliers de programmation, vous devrez indiquer l'ID de votre projet (généralement identifié par PROJECT_ID). Si l'ID généré ne vous convient pas, vous pouvez en générer un autre de manière aléatoire. Vous pouvez également en spécifier un et voir s'il est disponible. Après cette étape, l'ID n'est plus modifiable et restera donc le même pour toute la durée du projet.
  • Pour information, il existe une troisième valeur (le numéro de projet) que certaines API utilisent. Pour en savoir plus sur ces trois valeurs, consultez la documentation.
  1. Vous devez ensuite activer la facturation dans la console Cloud pour utiliser les ressources/API Cloud. L'exécution de cet atelier de programmation est très peu coûteuse, voire sans frais. Pour désactiver les ressources et éviter ainsi que des frais ne vous soient facturés après ce tutoriel, vous pouvez supprimer le projet ou les ressources que vous avez créées. Les nouveaux utilisateurs de Google Cloud peuvent participer au programme d'essai sans frais pour bénéficier d'un crédit de 300 $.

Activer Cloud Shell

  1. Dans Cloud Console, cliquez sur Activer Cloud Shell 853e55310c205094.png.

55efc1aaa7a4d3ad.png

Si vous démarrez Cloud Shell pour la première fois, un écran intermédiaire vous explique de quoi il s'agit. Si un écran intermédiaire s'est affiché, cliquez sur Continuer.

9c92662c6a846a5c.png

Le provisionnement et la connexion à Cloud Shell ne devraient pas prendre plus de quelques minutes.

9f0e51b578fecce5.png

Cette machine virtuelle contient tous les outils de développement nécessaires. Elle comprend un répertoire d'accueil persistant de 5 Go et s'exécute dans Google Cloud, ce qui améliore considérablement les performances du réseau et l'authentification. Une grande partie, voire la totalité, de votre travail dans cet atelier de programmation peut être effectué dans un navigateur.

Une fois connecté à Cloud Shell, vous êtes authentifié et le projet est défini sur votre ID de projet.

  1. Exécutez la commande suivante dans Cloud Shell pour vérifier que vous êtes authentifié :
gcloud auth list

Résultat de la commande

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

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
  1. Exécutez la commande suivante dans Cloud Shell pour vérifier que la commande gcloud connaît votre projet:
gcloud config list project

Résultat de la commande

[core]
project = <PROJECT_ID>

Si vous obtenez un résultat différent, exécutez cette commande :

gcloud config set project <PROJECT_ID>

Résultat de la commande

Updated property [core/project].

3. Obtenir le code source

Après le lancement de Cloud Shell, vous pouvez utiliser la ligne de commande pour cloner l'exemple de code source dans le répertoire d'accueil.

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

4. Exécuter l'application en local

  1. Assurez-vous que la version de JAVA_HOME est correcte:
$ export JAVA_HOME=/usr/lib/jvm/java-1.17.0-openjdk-amd64
  1. Vous pouvez démarrer l'application Spring Boot normalement avec le plug-in Spring Boot.
$ ./mvnw -DskipTests spring-boot:run
  1. Une fois l'application démarrée, cliquez sur Aperçu sur le Web1a94d5bd10bfc072.png dans la barre d'outils Cloud Shell, puis sélectionnez Prévisualiser sur le port 8080.

6252b94905f3f7bd.png

Un onglet s'ouvre dans votre navigateur et se connecte au serveur que vous venez de démarrer.

9b6c29059957bd0.jpeg

5. Empaqueter l'application Java en tant que conteneur Docker

Vous devez ensuite préparer votre application pour qu'elle s'exécute sur Kubernetes. La première étape consiste à définir le conteneur et son contenu.

  1. Créez le fichier JAR déployable pour l'application.
$ ./mvnw -DskipTests package
  1. Activez l'API Artifact Registry pour stocker l'image de conteneur que vous allez créer.
$ gcloud services enable artifactregistry.googleapis.com
  1. Créez un dépôt Docker s'il n'en existe pas déjà un. Vous devez créer un dépôt avant de pouvoir y transférer des images:
$ gcloud artifacts repositories create codelabrepo     --repository-format=docker --location=us-central1 
  1. Le format de votre image est le suivant:

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

Par exemple, si vous avez créé le dépôt dans l'emplacement us-central1 nommé codelabrepo et que vous souhaitez nommer votre image hello-java:v1, l'image sera:

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

  1. Utilisez Jib pour créer l'image de conteneur et la transférer vers 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. Vous devriez pouvoir voir l'image de conteneur répertoriée dans la console en accédant à la page Images Artifact Registry dans la console Cloud. Vous disposez désormais d'une image Docker disponible au niveau du projet, que Kubernetes peut consulter et orchestrer, comme vous le verrez dans quelques minutes.
  2. (Facultatif) Une fois l'opération terminée (le téléchargement et l'extraction peuvent prendre un certain temps), testez l'image à l'aide de la commande suivante. Celle-ci exécutera un conteneur Docker en tant que daemon sur le port 8080 à partir de l'image de conteneur que vous venez de créer. Si vous rencontrez des problèmes d'autorisation, exécutez d'abord 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. Vous pouvez encore une fois profiter de la fonctionnalité d'aperçu sur le Web de Cloud Shell.

6252b94905f3f7bd.png

  1. La page par défaut doit s'afficher dans un nouvel onglet. Après avoir vérifié que l'application s'exécute localement dans un conteneur Docker, vous pouvez arrêter le conteneur en cours d'exécution en appuyant sur Control+C.

6. Créer votre cluster

Vous êtes prêt à créer votre cluster GKE. Un cluster se compose d'un serveur d'API Kubernetes géré par Google et d'un ensemble de nœuds de calcul. Les nœuds de calcul sont des VM Compute Engine.

  1. Tout d'abord, assurez-vous que les fonctionnalités de l'API associées sont activées.
$ gcloud services enable compute.googleapis.com container.googleapis.com
  1. Créez un cluster avec deux nœuds n1-standard-1 (cette opération prend quelques minutes).
$ gcloud container clusters create hello-java-cluster \
  --num-nodes 2 \
  --machine-type n1-standard-1 \
  --zone us-central1-c

Une fois l'opération terminée, vous devez voir le cluster créé.

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

Vous devriez maintenant disposer d'un cluster Kubernetes entièrement fonctionnel et basé sur GKE.

758c7fca14f70623.png

Il est maintenant temps de déployer votre application conteneurisée sur le cluster Kubernetes. À partir de maintenant, vous utiliserez la ligne de commande kubectl (déjà configurée dans votre environnement Cloud Shell). Pour le reste de l'atelier de programmation, les versions du client et du serveur Kubernetes doivent être 1.2 ou ultérieures. kubectl version affiche la version actuelle de la commande.

7. Déployer votre application sur Kubernetes

  1. Un déploiement Kubernetes peut créer, gérer et faire évoluer plusieurs instances de votre application à l'aide de l'image de conteneur que vous avez créée. Déployez une instance de votre application sur Kubernetes à l'aide de la commande kubectl run.
$ kubectl create deployment hello-java --image=us-central1-docker.pkg.dev/$GOOGLE_CLOUD_PROJECT/codelabrepo/hello-java:v1
  1. Pour afficher le déploiement que vous avez créé, exécutez simplement la commande suivante:
$ kubectl get deployments

NAME         DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
hello-java   1         1         1            1           37s
  1. Pour afficher les instances d'application créées par le déploiement, exécutez la commande suivante:
$ kubectl get pods

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

À ce stade, votre conteneur doit s'exécuter sous le contrôle de Kubernetes, mais vous devez quand même le rendre accessible depuis l'extérieur.

8. Autoriser le trafic externe

Par défaut, le pod n'est accessible que par son adresse IP interne dans le cluster. Pour rendre le conteneur hello-java accessible en dehors du réseau virtuel Kubernetes, vous devez exposer le pod en tant que service Kubernetes.

  1. Dans Cloud Shell, vous pouvez exposer le pod au réseau Internet public en créant un service Kubernetes LoadBalancer.
$ kubectl create service loadbalancer hello-java --tcp=8080:8080

Notez que vous exposez directement le déploiement, et non le pod. Le service obtenu équilibrera alors la charge du trafic entre tous les pods gérés par le déploiement (dans le cas présent, un seul pod, mais vous ajouterez d'autres instances répliquées ultérieurement).

Le maître Kubernetes crée l'équilibreur de charge ainsi que les règles de transfert, les pools cibles et les règles de pare-feu Compute Engine associés pour rendre le service entièrement accessible depuis l'extérieur de Google Cloud.

  1. Pour trouver l'adresse IP publiquement accessible du service, demandez simplement à kubectl de répertorier tous les services du 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. Vous devriez maintenant pouvoir accéder au service en pointant sur http://<EXTERNAL_IP>:8080 dans votre navigateur.

9. Effectuer le scaling de votre service

L'une des fonctionnalités puissantes proposées par Kubernetes est la facilité avec laquelle vous pouvez faire évoluer votre application. Supposons que vous ayez soudainement besoin de davantage de capacité pour votre application. Vous pouvez simplement demander au contrôleur de réplication de gérer un nouveau nombre d'instances répliquées pour vos instances d'application.

$ 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

Notez l'approche déclarative. Plutôt que de démarrer ou d'arrêter de nouvelles instances, vous déclarez le nombre d'instances à exécuter en permanence. Les boucles de rapprochement Kubernetes s'assurent simplement que la réalité correspond à votre demande et prennent des mesures si nécessaire.

10. Déployer une mise à niveau sur votre service

À un moment donné, l'application que vous avez déployée en production nécessitera des corrections de bugs ou des fonctionnalités supplémentaires. Kubernetes peut vous aider à déployer une nouvelle version en production sans affecter vos utilisateurs.

  1. Ouvrez l'éditeur de code en cliquant sur Ouvrir l'éditeur 2109d75686c889a.png dans le menu Cloud Shell.
  2. Accédez à src/main/java/com/example/springboot/HelloController.java et modifiez la valeur de la réponse.
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. Utilisez Jib pour créer et transférer une nouvelle version de l'image de conteneur. La création et le transfert de l'image mise à jour doivent être beaucoup plus rapides, car vous tirez pleinement parti de la mise en 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

Vous êtes prêt à ce que Kubernetes mette à jour votre contrôleur de réplication de manière fluide vers la nouvelle version de l'application.

  1. Pour modifier le libellé de l'image pour votre conteneur en cours d'exécution, vous devez modifier le déploiement hello-java existant et remplacer l'image us-central1-docker.pkg.dev/PROJECT_ID/codelabrepo/hello-java:v1 par un autre.

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

  1. Vous pouvez utiliser la commande kubectl set image pour demander à Kubernetes de déployer la nouvelle version de votre application sur l'ensemble du cluster, instance par instance, avec des mises à jour progressives.
$ 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. Vérifiez à nouveau http://EXTERNAL_IP:8080 pour vous assurer qu'il renvoie la nouvelle réponse.

11. Rollback

Petit problème… Vous avez fait une erreur avec une nouvelle version de l'application ? La nouvelle version contient peut-être une erreur et vous devez effectuer rapidement un rollback. Avec Kubernetes, vous pouvez facilement revenir à l'état précédent. Effectuez un rollback de l'application en exécutant la commande suivante:

$ kubectl rollout undo deployment/hello-java

L'ancienne réponse doit s'afficher lorsque vous vérifiez à nouveau http://EXTERNAL_IP:8080.

12. Félicitations

Vous avez appris à créer et à déployer une nouvelle application Web Java dans Kubernetes sur GKE.

Nettoyage

$ 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

En savoir plus