Deployer une application Quarkus sur GKE avec GitLabCI
Tags: quarkus, gitlabci, kubernetes, gke
Published: 2020-07-16 15:16:38


Dans cet article, je vais vous montrer comment profiter de la puissance de Quarkus et de GitLab CI pour déployer facilement une API Rest sur un cluster Google Kubernetes Engine.


## 🚀 Quarkus

Si vous ne connaissez pas **Quarkus**, voici un lien d'un précédent article vous menant à un atelier [**🚀 Quarkus**](https://dev.to/jphi_baconnais/mes-premiers-tests-avec-quarkus-3jap).

### Création du projet

Tout d'abord, créons un projet Quarkus avec l'extension kubernetes :

```
mvn io.quarkus:quarkus-maven-plugin:1.5.2.Final:create \
    -DprojectGroupId=fr.jpbaconnais \
    -DprojectArtifactId=deployquarkusongkewithgitlab \
    -DclassName="fr.jpbaconnais.HelloWorldFromQuarkus" \
    -Dextensions="kubernetes, container-image-docker"
```

Lors du déploiement de l'application via un **mvn compile quarkus:dev** la ressource REST suivante **http://localhost:8080/hello** renvoie une réponse avec un code retour 200.

Nous allons faire quelques modifications pour que la suite se passe correctement.

Tout d'abord, supprimons le fichier .dockerignore. Modifions ensuite le fichier **src/main/docker/Dockerfile.jvm** pour y ajouter une étape de build maven qui sera la première étape à exécuter dans le dockerfile :

```
FROM maven:3.6.3 as builders
RUN mkdir /build
RUN mkdir /build/src
RUN chmod 777 -R /build/
COPY src /build/src/
COPY pom.xml /build/
WORKDIR /build
RUN mvn clean package
```

Modifions ensuite les deux lignes suivantes pour récupérer les jars générés dans ce nouveau stage docker :

```
COPY target/lib/* /deployments/lib/
COPY target/*-runner.jar /deployments/app.jar
```

par 

```
COPY **--from=builders** /build/target/lib/* /deployments/lib/
COPY **--from=builders** /build/target/*-runner.jar /deployments/app.jar
```

<br />

### La partie kubernetes

Nous allons modifier le fichier **application.properties** afin d'y ajouter des modifications sur le nom de l'image utilisées dans les pods :

```
quarkus.container-image.registry=registry.gitlab.com <ou votre url d'instance GitLab si vous êtes en auto hébergé>
quarkus.container-image.group=<votre identifiant gitlab> 
quarkus.container-image.name=<le nom de votre projet gitlab>
quarkus.container-image.tag=dev
```

De base, Quarkus renseigne des valeurs par défaut pour ces variables mais avec l'intégration via GitLabCI, je choisis de les modifier, vous verrez cela par la suite de cet article 😜.

Quarkus va nous mettre à disposition, grâce à l'extension kubernetes, deux fichiers lors de l'exécution d'un **mvn clean package** en plus des jars de l'application :

 - kubernetes.json
 - kubernetes.yaml
 
En local, si vous avez une version de docker-desktop ou bien minikube (ou autre), vous pourrez tout simplement déployer votre application via un **kubectl apply -f target/kubernetes/kubernetes.yml**.

```
kubectl get pods

NAME                                          READY   STATUS    RESTARTS   AGE
deployquarkusgkewithgitlab-7cc79f7f7d-24jrj   1/1     Running   25         6h9m
deployquarkusgkewithgitlab-7cc79f7f7d-9hzqn   1/1     Running   24         6h9m
deployquarkusgkewithgitlab-7cc79f7f7d-dl659   1/1     Running   24         6h9m
```

```
kubectl get deploy

NAME                         READY   UP-TO-DATE   AVAILABLE   AGE
deployquarkusgkewithgitlab   3/3     3            3           6h28m
```

```
kubectl get svc

NAME                         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
deployquarkusgkewithgitlab   ClusterIP   10.104.20.238   <none>        9999/TCP   6h28m
kubernetes                   ClusterIP   10.96.0.1       <none>        443/TCP    66d
```

Et l'exécution d'une commande curl sur notre ressource permet de voir un joli _Hello world from quarkus_.

![Exec kube](http://jeanphi-baconnais.gitlab.io/img/deploy_quarkus_gitlabci_exec_kube.png "Exec Kube")



<br />

## 🐬 Google Kubernetes Engine

Pour la partie GKE, je vais vous épargner l'étape de création de compte [**GKE**](https://cloud.google.com/kubernetes-engine?hl=fr).

Pour créer votre cluster kubernetes, vous avez deux options :

 - le créer via l'interface de GKE
 - le cluster par l'interface GitLab

Pour cet exemple je vais partir sur la seconde option et utiliser pleinement l'intégration kubernetes dans GitLabCI pour créer un cluster GKE. Pour commencer, rendez-vous sur le lien "Kubernetes" dans le menu vertical : 

![Create Cluster](http://jeanphi-baconnais.gitlab.io/img/deploy_quarkus_gitlabci_gke_create_cluster.png "Create Cluster")

Sélectionnons la création de cluster sur GKE :

![Create Cluster GKE](http://jeanphi-baconnais.gitlab.io/img/deploy_quarkus_gitlabci_gke_create_cluster-2.png "Create Cluster GKE")

Renseignons le nom du cluster souhaité :

![Put Cluster Name](http://jeanphi-baconnais.gitlab.io/img/deploy_quarkus_gitlabci_gke_create_cluster-3.png "Put Cluster Name")

Et voila ! 🤘

![Create Cluster](http://jeanphi-baconnais.gitlab.io/img/deploy_quarkus_gitlabci_gke_create_cluster-4.png "Quarkus")

Sur l'interface graphique de GKE, notre cluster est également visible : 

![Create Cluster](http://jeanphi-baconnais.gitlab.io/img/deploy_quarkus_gitlabci_gke_create_cluster-gke.png "Quarkus")

<br />

## 🦊 GitLab

La configuration d'un pipeline GitLabCI se fait via la création d'un fichier **.gitlab-ci.yml**. Nouveau coup de "pub" 😎, j'avais créé cet article pour bien [**🦊 débuter avec GitLabCI**](https://dev.to/jphi_baconnais/commencer-simplement-avec-gitlabci-53fa).

Nous allons donc créer un fichier **.gitlab-ci.yml** à la racine du projet. Dans ce fichier nous allons vouloir que notre script effectue :

 - une exécution des tests de notre application
 - une construction de notre image docker via la librairie [**Kaniko**](https://github.com/GoogleContainerTools/kaniko)
 - déployer notre application sur **Google Kubernetes Engine**


### Le CI/CD avec le fichier .gitlab-ci.yml

Pour effectuer nos 3 jobs, nous allons créer 3 stages :

```
stages:
  - test
  - build_and_push
  - deploy_gke
```

Pour le premier job, il suffit d'effectuer un **mvn clean verify** à partir d'une image maven 3.6.3 :

```
🩺 execute test :
    stage: test
    image: maven:3.6.3
    script:
      - mvn clean verify  -f deployquarkusongkewithgitlab/pom.xml
    artifacts:
        paths: 
            - deployquarkusongkewithgitlab/target/kubernetes
```

Nous fixons un artifact sur le répertoire **target/kubernetes** afin de limiter le nombre de fichiers disponibles après l'exécution du job mais aussi pour permettre aux autres jobs de pouvoir utiliser ces fichiers.

Pour la partie _build_ et _push_, la librairie **Kaniko** va nous faciliter la tâche :

```
🐳 build push image docker:
  stage: build_and_push
  image:
    name: gcr.io/kaniko-project/executor:debug-v0.19.0
    entrypoint: [""]
  script:
    - echo "{\"auths\":{\"$CI_REGISTRY\":{\"username\":\"$CI_REGISTRY_USER\",\"password\":\"$CI_REGISTRY_PASSWORD\"}}}" > /kaniko/.docker/config.json
    - /kaniko/executor --context $CI_PROJECT_DIR/deployquarkusongkewithgitlab --dockerfile $CI_PROJECT_DIR/deployquarkusongkewithgitlab/src/main/docker/Dockerfile.jvm --destination deployquarkusgkewithgitlab:dev
```

Il suffit de renseigner le chemin du Dockerfile, une destination et **Kaniko** va nous builder l'image et la pusher dans le repository souhaité. Dans mon utilisation, je vais utiliser le [registry de GitLab](https://docs.gitlab.com/ee/user/packages/container_registry/). Vous comprenez mieux pourquoi j'utilise le paramétrage Quarkus **quarkus.container-image** 😎.

Pour la dernière étape, on va tout simplement prendre une image [**cloud-sdk de Google**](https://hub.docker.com/r/google/cloud-sdk/) sur laquelle on va pouvoir appliquer notre fichier **kubernetes.yaml** généré par Quarkus.

```
🐋 deploy on gke:
  stage: deploy_gke
  image: google/cloud-sdk
  script:
    - kubectl apply -f deployquarkusongkewithgitlab/target/kubernetes/kubernetes.yml
  environment: gke
```

Le mot clé **environment** est important et est obligatoire pour avoir une intégration correcte. Cela vous permettra également d'avoir une visu de votre environnement dans le menu **environnement** :

![Environment](http://jeanphi-baconnais.gitlab.io/img/deploy_quarkus_gitlabci_gke_deploy-environment.png "Environment")


Dans le pipeline nous pouvons voir que le déploiement a bien été effectué :

![Deploy success](http://jeanphi-baconnais.gitlab.io/img/deploy_quarkus_gitlabci_gke_deploy.png "Deploy success")

et que notre infrastructure kubernetes est bien en place et visible sous GKE :

![GKE](http://jeanphi-baconnais.gitlab.io/img/deploy_quarkus_gitlabci_gke_deploy-gke.png "GKE")

Nos pods sont bien disponibles :

![Pods GKE](http://jeanphi-baconnais.gitlab.io/img/deploy_quarkus_gitlabci_gke_deploy-gke-pod.png "Pods GKE")

<br />

## Supervision 

Et en bonus, pour superviser notre infrastructure GKE, certaines métriques sont directement disponibles sous GitLab :

![Supervision](http://jeanphi-baconnais.gitlab.io/img/deploy_quarkus_gitlabci_gke_deploy-gke-health.png "HealthCheck")

<br />

Si vous avez des remarques sur cet article, n'hésitez pas à me les faire parvenir 😃


<br />