Introduction

L’intégration continue (CI) et la livraison continue (CD) représentent un ensemble de pratiques permettant aux équipes de développement d’appliquer leurs modifications de code de manière plus fréquente, reproductible et fiable. L’implémentation la plus courante du CI/CD est l’utilisation d’un pipeline (une suite d’étapes) dans un orchestrateur (outil qui exécute les actions définies dans les étapes du pipeline).

L’orchestrateur peut rapidement devenir incapable de supporter la totalité de la charge, d’où le recours à une architecture technique distribuée dans laquelle la charge de travail de construction des projets est distribuée sur plusieurs agents.

Dans cet article, on va voir comment kubernetes facilite l’implémentation de cette architecture avec deux orchestrateurs jenkins et gitlab-ci.

Jenkins

pré-requis :
  • cluster kubernetes
  • helm

Si vous n’avez pas un cluster kubernetes, vous pouvez en avoir un, gratuitement et rapidement, grâce à GKE. Il suffit juste d’avoir un compte google.

Installer Jenkins
  1. A l’aide du client helm, installez Jenkins avec toute la configuration nécessaire :
    helm install --name jenkins-k8s --set master.serviceType=NodePort stable/jenkins --namespace ci-cd-k8s
    • helm : helm CLI
    • jenkins-k8s : nom de la release helm.
    • master.serviceType : type du service kubernetes.
    • stable/jenkins : nom de la chart helm

    A la fin de l’exécution de la commande helm, une note indique comment récupérer le mot de passe de l’utilisateur ‘admin’ :

    NOTES:
    1. Get your 'admin' user password by running:
      printf $(kubectl get secret --namespace blog jenkins-k8s -o jsonpath="{.data.jenkins-admin-password}" | base64 --decode);echo
    2. Get the Jenkins URL to visit by running these commands in the same shell:
      NOTE: It may take a few minutes for the LoadBalancer IP to be available.
            You can watch the status of by running 'kubectl get svc --namespace blog -w jenkins-k8s'
      export SERVICE_IP=$(kubectl get svc --namespace blog jenkins-k8s --template "{{ range (index .status.loadBalancer.ingress 0) }}{{ . }}{{ end }}")
      echo http://$SERVICE_IP:8080/login
    
    3. Login with the password from step 1 and the username: admin
  2. Vérifiez que le service Jenkins est bien installé :
    kubectl get svc -n ci-cd-k8s

    Vous allez avoir un résultat comme suit :

    NAME                TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)          AGE
    jenkins-k8s         NodePort    10.52.0.129                 8080:31508/TCP   83m
    jenkins-k8s-agent   ClusterIP   10.52.1.222                 50000/TCP        83m
  3. Obtenez l’adresse IP publique de l’un de vos nœuds et connectez-vous à l’url suivante :http://adresse_ip_publique_d_un_noeud:node_port/login

    N.B: si vous utilisez un cloud provider n’oubliez pas d’ouvrir le flux d’entrée à ce port.

Configurer Jenkins

Si vous venez de créer Jenkins via helm, ignorez cette partie et passez directement à l’étape suivante.

L’objectif de cette section est de vous montrer comment configurer Jenkins pour lancer ses agents sur un cluster kubernetes.

  1. Via l’interface de gestion des plugins de Jenkins, vérifiez si vous avez déjà le plugin kubernetes installé sinon installez le comme suit:
    1. Allez dans http://jenkins_url/pluginManager/
    2. Allez dans l’onglet “Disponibles” et dans le filtre chercher ‘kubernetes’.
    3. Sélectionnez le plugin puis cliquez sur installer.

  2. Une fois le plugin installé, vous pouvez configurer les paramètres de votre cluster kubernetes. Via l’interface de configuration de Jenkins, allez en bas de la page. Dans la section “cloud”, cliquez sur “ajouter un nouveau cloud” puis “kubernetes”.

    les paramètres obligatoires sont :

    • Name: nom à attribuer à cette configuration.
    • Kubernetes URL: L’URL de votre cluster kubernetes. Si votre master Jenkins est déployé sur le même cluster kubernetes, l’url est https://kubernetes.default. Sinon vous pouvez récupérer l’URL via la commande suivante :
      kubectl cluster-info | grep master

      ou bien si vous utilisez GKE via la console.

    • Kubernetes Namespace: namespace où les slaves seront créés.
    • Credentials: Si le master Jenkins est sur le même cluster kubernetes, vous n’avez besoin de définir ce champ. Sinon, vous devez créer un identifiant (uername/password) pour vous connecter. Pour les utilisateurs de GKE, vous pouvez récupérer les identifiants via la console web. Un autre moyen de connexion consiste à récupérer le token de serviceaccount qui a les droits de création de pods dans le namespace spécifié précédemment et créer un identifiant Jenkins de type ‘Secret Text’.Vous pouvez tester la connexion avec le bouton ‘Test Connection’
    • Jenkins URL: l’URL de votre master Jenkins.
    • Jenkins tunnel: jenkis_hostname:50000 tunnel utilisé pour communiqué avec l’agent.

    On va se limiter à ces paramètres pour l’instant.

Créer un pipeline

Dans l’exemple suivant, on va exécuter deux pipelines : Le premier avec la description de l’agent au niveau du Jenkinsfile. Le deuxième avec la description de l’agent centralisée au niveau de la configuration Jenkins.

Pod template dans le Jenkinsfile
  1. Créer un nouveau job Jenkins de type ‘Multibranch Pipeline’, afin d’utiliser différentes branches, avec un nom de votre choix.
  2. Cliquez ‘Add source’ ->Git puis copiez l’URL du projet github spring-petclinic. En effet, c’est un fork du projet publique spring-petclinic. Jenkins va scanner toutes les branches en cherchant les Jenkinsfile. L’exécution des branches contenant les Jenkinsfile commence automatiquement. Ce qui nous intéresse est la branche ‘k8s-master-slave’.

    N.B: Le Jenkinsfile définit un pod qui pointe vers un volume ‘maven-repo-pvc’ afin d’éviter de télécharger les dépendances maven à chaque exécution. Si vous avez déjà un volume maven, vous pouvez adapter le code, sinon un fichier yaml vous permet de créer rapidement le volume demandé.
  3. Vérifiez l’avancement de l’exécution du pipeline ‘k8s-master-slave’.

Si vous jetez un coup d’oeil sur le Jenkinsfile, vous allez remarquer le pod template utilisé pour la création des agents. Il est possible d’extraire cette définition et la mettre au niveau de la configuration Jenkins. Ceci peut être pratique au cas où vous utilisez assez souvent le même pod ou dans les projets qui ne contiennent pas un Jenkinsfile.

Pod template dans la configuration Jenkins

Si vous avez installer Jenkins en utilisant helm, un pod template est créé par défaut. Sinon, via l’interface de configuration de Jenkins, dans la section ‘Cloud’, vous pouvez ajouter un pod template.

Les paramètres de base sont :

  • Name: Nom de votre template.
  • Namespace: le même que celui du Cloud configuré précédemment.
  • Labels: Le libellé utilisé pour identifier l’agent.
  • Containers: Les conteneurs du pod. Nous allons définir deux contenurs jnlp (indispensable pour la connexion de l’agent) et maven (juste pour l’exemple).
    • jnlp
      • Name : jnlp
      • Docker image : jenkins/jnlp-slave:3.35-5-alpine
      • Working directory : /home/jenkins/agent
      • Command to run : il faut la laisser vide pour le conteneur jnlp.
      • Arguments to pass to the command: il faut la laisser vide pour le conteneur jnlp.
    • maven
      • Name : maven
      • Docker image : maven:3.3.9
      • Working directory : /home/jenkins/agent
      • Command to run : /bin/sh -c (contrairement à jnlp, il faut surcharger la commande de base du conteneur, car l’image maven exécute la commande mvn à son démarrage, donc le conteneur va se terminer dès son initialisation).
      • Arguments to pass to the command: cat
  • Volumes: on va monter le volume maven-repo-pvc de type ‘Persistent Volume Claim’.

Plus de détails pour chaque champ dans la documentation du plugin.

Lancez maintenant le job ‘k8s-default-slave’. La seule différence de code avec job ‘k8s-master-slave’ est au niveau du Jenkinsfile. En effet, vous avez juste besoin du label du pod.

Gitlab-ci

Pour utiliser le service gitlab-ci de gitlab, il faut avoir un gitlab runner qui va exécuter les jobs et envoyer le résultat à gitlab. Gitlab Runner implémente plusieurs exécuteurs. On va s’intéresser, dans cet article, à l’exécuteur kubernetes.

pré-requis
  • cluster kubernetes
  • helm
  • gitlab
Créer un projet gitlab
  • Créez un projet gitlab (gitlab.com ou votre propre gitlab).
  • Clonez le projet spring-petclinic.
  • Poussez le code vers votre projet.
    $ git clone https://github.com/nextek-fr/spring-petclinic.git
    $ git remote add gitlab http://xx.xx.xx.xx/spring-petclinic-demo.git
    $ git push gitlab master
Installer gitlab runner
  • Récupérez les informations nécessaire pour créer le runner. Via votre projet gitlab, allez dans : Settings->CI/CD->Runners->Expand
    N.B: Le runner peut être spécifique, par groupe ou partagé. Dans cet exemple, nous allons créer un runner spécifique, c.a.d, lié à un seul projet. Plus de détails concernant la configuration d’un runner dans la documentation gitlab.
  • Personnalisez la commande suivante avec vos valeurs :
    cat > values.yaml <
    
  • Exécutez la commande helm suivante :
    helm install --namespace  --name gitlab-runner -f values.yaml gitlab/gitlab-runner
    • helm : helm CLI
    • namespace : namespace kubernetes qui contiendra le runner.
    • gitlab-runner : nom de la release helm.
    • gitlab/gitlab-runner : nom de la chart helm
    • values.yaml : fichier définissant certains paramètres comme l’url de gitlab et le token d’enregistrement.
  • Vérifiez qu’un pod gitlab runner a été créé et qu’un runner s’affiche au niveau de la configuration projet.
Configurer le runner

Cette partie est optionnelle. En effet, elle consiste à définir un volume qui sera partagé ultérieurement par les builds.

  • Modifiez la configmap gitlab-runner-gitlab-runner.
    kubectl edit cm -n gitlab gitlab-runner-gitlab-runner
  • Ajoutez le bout de code suivant à la fin du fichier ‘entrypoint’.
    cat >>/home/gitlab-runner/.gitlab-runner/config.toml <
    
  • Supprimez le pod gitlab-runner. Un nouveau sera créé avec la nouvelle configuration.
Exécuter un pipeline

Allez dans CI/CD → pipelines et cliquez Run Pipeline.

Conclusion

Face à la popularité de Kubernetes qui est en train de devenir un élément incontournable du processus de développement des applications cloud native, les orchestrateurs ont développé des nouvelles fonctionnalités afin de l'intégrer. Certains nouveaux orchestrateurs comme Tekton et Jenkins-X ont pris kubernetes comme base de fonctionnement.

Bravo ! Vous avez été jusqu'au bout de l'article :) Pour aller plus loin, recevrez notre study guide contenant la sélection de références concoctée pour vous par nos experts

Icons designed by Freepik.