Continuous deployment

Vous avez probablement remarqué que nous avons automatisé la création d'une image Docker, et qu'elle réside maintenant dans notre registre de conteneurs sur Gitlab.

Maintenant, ce que nous voulons faire, c'est exécuter la bonne commande kubectl pour télécharger cette image dans notre cluster Kubernetes.

Est-ce qu'on peut automatiser ce processus dans notre .gitlab-ci.yml ? Oui !

Publier un image de prod

Nous allons ajouter une étape à notre pipeline: publish pour élever notre image déjà créée et testée (avec nos tests e2e) au statut de production, en créant un tag.

D'abord, nous allons protéger nos tags dans Gitlab, en précisant que seulement des tags d'un certain format puissent être déployé en production.

Naviguez dans Settings → Repository → Protected Tags. Tapez *.*.* dans la barre de recherche, puis cliquer sur "Create wildcard tag". Sélectionner le role Maintainers (seulement les utilisateurs privilégiés auront le droit à déployer); puis cliquer sur "Protect".

Retournez à votre .gitlab-ci.yaml, et ajoutez une phase publish :

stages:  
  - test
  - build
  - e2e-test  
  - publish

On ajoute une tâches de plus, qui sera prise en compte seulement si on crée un nouveau tag sur notre branch main. La première tâche va re-tagger notre image Docker avec la version précisé dans le nom de notre tag.

publish-job:
  stage: publish
  tags:
    - general
  rules:
    # Only if we create a tag
    - if: $CI_COMMIT_TAG
  image: docker:20.10.16
  services:
    - name: docker:20.10.16-dind
      alias: docker
  variables:
    IMAGE_TAG: $CI_REGISTRY_IMAGE/api-$CI_COMMIT_REF_NAME:$CI_COMMIT_SHORT_SHA
    LATEST_TAG: $CI_REGISTRY_IMAGE/api-prod:$CI_COMMIT_TAG
  script:
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
    # Créer l'image docker
    - docker build --pull -t $IMAGE_TAG -f ./config/docker/Dockerfile.prod .
    # Retagger l'image avec le tag fourni
    - echo "Retagging docker image..."
    - docker tag $IMAGE_TAG $LATEST_TAG     # Elever notre image au tag "latest"
    - echo "Push image with latest tag..."
    - docker push $LATEST_TAG               # Envoyer l'image à notre Container Repository
    - echo "Done."

Ajoutez cette tâche à votre pipeline, et ensuite créez un tag sur votre code dans Code → Tags. Normalement le tag représente la version, par exemple 1.0.1 :

Retournez dans Build → Pipelines, vous verrez le dernier pipeline aura recommencé avec une nouvelle tâche pour publier l'image avec le nom de notre tag. Une fois fini, naviguez dans Deploy → Container Registry. Vous verrez une nouveau dépôt api-prod qui contiendra toutes nos images de production.

Configurer l'accès k8s au Gitlab

Auparavant, nous avons déployé notre api manuellement via Docker Hub, en utilisant un dépôt public.

Cependant, Kubernetes doit maintenant accéder à notre registre de conteneurs privé GitLab pour récupérer les images nouvellement construites.

Nous devons configurer un accès pour k8s.

Commencez par créer un jeton d'accès que k8s pourra utiliser pour extraire des images de notre registre de conteneurs. Naviguez dans Settings → Access Tokens →, et créez un jeton d'accès uniquement pour k8s :

  • Pas de date d'expiration

  • Role : Developer

  • Scope : read_registry

Copiez le jeton d'accès.

Tester l'accès au registre de containers

Pour être certain d'avoir le bon jeton d'accès on peut essayer de récupérer une image déjà dans notre GitLab.

Naviguez dans Deploy → Container Registry, selectionnez un dépôt, et vous verrez les différents tags déjà publiés. Vous pouvez copier le chemin préci pour une image en cliquant sur le petit presse papier à coté d'un tag.

Si tout fonctionne sans erreur, vous avez les bons coordonnées pour récupérer des images de GitLab !

Retournez à votre Dev Container. Nous allons modifier notre configuration k8s pour pouvoir s'identifier auprès de notre GitLab :

Créons un secret sur le cluster qui permet de nous identifier sur GitLab :

Ensuite, nous allons modifier notre fichier deployment.k8s.yaml (la modification sur le 2 dernières lignes) :

Appliquer ce fichier en emettant :

Tout est prêt ! K8s sait désormais récupérer des images de notre GitLab.

Déployer sur k8s

Nous allons ajouter une étape à notre pipeline: deploy pour déployer notre image dans le cluster.

La tâche correspondante va connecter à notre cluster, et mettre à jour l'image utilisé par notre déploiement :

Prenez note de la phrase when: manual - j'ai choisi de faire la tâche manuellement, pour être sur de ne pas se tromper !!

Pour connecter à notre cluster, il faudrait s'identifier avec notre fichier kubeconfig. Il faudrait le fournir à GitLab en tant que secret avec le nom KUBECONFIG_PROD.

Naviguez dans **Settings → CI/CD → Variables **:

On ajoute notre variable KUBECONFIG_PROD :

Le type de variable est File, on le nomme KUBECONFIG_PROD, et on colle les contenus de kubeconfig.yaml que je vous ai passé.

Et, c'est tout bon, tout devrait être configuré.

Pour valider si tout fonctionne :

  1. Attendez que les tests sont terminés sans problème

  2. Créez un nouveau tag, et attendez que le build soit fait

  3. Manuellement déclencher le déploiement en retournant dans la pipeline, entrant dans la tâche "deploy", et en lançant le job.

Comment savoir si notre image a été déployée ? Retournez à votre DevContainer, et tapez dans le terminal :

Parmis les détails, vous devez voir l'image qui portera désormais la version que vous avez précisé dans le tag sur Gitlab !

Vérifiez que votre API fonctionne toujours :

Testons notre pipeline CI/CD

Nous allons modifier notre endpoint /info pour retourner une information supplémentaire. Dans src/controllers/InfoController.ts

Utilisez votre compte git pour faire un commit et push, créez un tag, et déployer l'image sur le cluster.

Une fois que le pipeline se termine, testons notre API:

Debogger

N'oubliez pas d'utiliser les outils kubectl pour déboguer votre deploiement.

Par exemple, vous ne voyez pas votre modification dans le résultat ?

  • Vérifiez que la bonne image est précisé avec kubectl get deployments

  • Vérifiez que les pods tournent correctement avec kubectl get pods. Si vous voyez un état d'erreur, type Image Pull Error ou Image Pull Backoff il se trouve que k8s n'arrive pas à récupérer l'image de Gitlab. Vérifier bien d'avoir fourni les bons codes d'accès dans le chapitre précédente !

Le .gitlab-ci.yml

Voici le fichier complet :

Mis à jour