Photo by Pankaj Patel on Unsplash

Intégration continue GitLab, OpenShift / Kubernetes

Aujourd'hui un article sur l'intégration continue. Je vais parler ici de ce que je mets en place sur mon "lab", mon infrastructure maison.

Pour rappel, l'intégration continue (CI ou Continuous Integration) est une pratique de développement consistant à réaliser des tests automatisés à chaque changement du code source, afin de détecter les problèmes techniques et les régressions fonctionnelles. Les tests en question peuvent être des tests unitaires, de qualité ou bien encore de sécurité du code.

Brique de base

Comme rappelé précédemment, l'intégration continue s'articule, en général, autour d'un dépôt de code source (git par exemple). La solution que j'ai choisi pour centraliser le code source, qui permet de travailler en équipe et de lancer les pipelines d’intégration continue est GitLab Community Edition.

Solution d'intégration continue

La solution que j'ai trouvé la plus logique et simple à adopter est GitLab CI. Les raisons principales motivant ce choix sont les suivantes :

  • Solution simple (je n'ai pas besoin d’une « usine à gaz » pour réaliser la CI)
  • S’intègre bien avec GitLab CE
  • Syntaxe assez lisible (fichier YAML dans le code source)

Mise en place de la solution de CI

Il existe pas mal de façon de faire tourner le code des applications via le runner GitLab CI. Dans la documentation officielle, il est question d’executor. Au moment de la rédaction de cet article, les possibilités sont les suivantes :

  • Shell
  • Docker
  • Docker Machine and Docker Machine SSH (autoscaling)
  • Parallels
  • VirtualBox
  • SSH
  • Kubernetes

J'ai installé et testé deux des méthodes cités pour les runners : Docker et Kubernetes.

Le choix de Docker s'est fait en adéquation avec mon environnement de développement. Le runner tourne dans une machine virtuelle qemu/kvm.

Plus récemment, j'ai expérimenté avec la solution Kubernetes et c'est là-dessus que je mets l'accent aujourd'hui. La documentation officielle (Intégration Kubernetes) est explicite et facilite grandement l'installation. GitLab interagit avec le cluster Kubernetes et ce dernier créé des pods (containers Docker) pour lancer les jobs de CI, envoie les logs et autre messages sur GitLab puis supprime ces pods temporaires.

L’intégration entre Kubernetes et Gitlab peut se faire dans un Groupe ou bien au sein d’un projet GitLab donné. C’est ce dernier cas qui est présenté ci-dessous :

gitlab openshift setup

Ici, nous avons intégré un cluster OpenShift (Kubernetes), nommé OpenShift avec le projet Taskbuster (dont j'ai déjà parlé ici).

Une fois l’intégration réalisée, il est possible en « un clic » d’installer des applications dont le fameux Gitlab Runner :

gitlab kubernetes apps

Une fois que c’est installé, le runner sur le cluster Kubernetes est automatiquement activé pour le projet. Voici un exemple de log pour un job de CI tournant dans le cluster :

gitlab kubernetes job

Ici, un runner (runner-xwayt8wb-project-73-concurrent-1lfjns) est créé pour exécuter les tâches de la CI. Il faut attendre son instanciation dans le cluster (quelques secondes), puis le job peut alors être exécuté. A la fin, le runner est supprimé. Si plusieurs jobs sont lancés en parallèle, alors le cluster créé des runners distincts.

Les possibilités offertes par la CI

Voici des exemples de possibilité que j'ai déjà exploré avec la CI :

  • Vérification de la présence de CVE dans les dépendances du projet
  • Validation du respect d’un standard de code (PEP8 pour du code python par exemple)
  • Tests unitaires
  • Tests fonctionnels

Le premier point fonctionne bien pour un projet actif. A chaque commit, la vérification des versions des paquets listés et installés par l'outil de gestion des dépendances (composer pour PHP, pip pour python etc.) permettra de valider qu’on est bien à jour et non vulnérable de ce point de vue.

La validation du standard de code est utile dans les Merge Requests pour s'assurer que le bout de code à ajouter est bien cohérent avec le reste du projet. C’est une vérification simple qui peut être effectuée en amont (énormément d’éditeurs de code propose ce type de fonctionnalité) mais ça ne fait pas de mal de l’avoir dans la CI également.

Les tests, unitaires et fonctionnels, parlent d’eux-mêmes. Ils permettent de vérifier que le code est sans erreur et d’éviter les régressions.

Ci-dessous, quelques exemples d’utilisation de l’intégration continue.

En exécutant les tests dans le pipeline de CI, il est possible facilement de lancer des tests sur plusieurs versions du langage de programmation. Ceci permet de valider plus sereinement une évolution du code source. Voici un exemple sur lequel les tests sont lancés en parallèle sur PHP 5.6 et 7.0 :

gitlab kubernetes job versions

Les tests passent sur les deux versions donc, dans le cadre d'une mise à jour vers php 7.0, tout devrait bien se passer.

Par ailleurs, il est possible de lancer des tests fonctionnels sur un service de base de données temporaire. Prenons l’exemple de notre projet web Python (Framework Django + base de données PostgreSQL).

Dans l’intégration continue GitLab, on peut déclarer un service de base données qui sera lié à notre runner de test.

Voici un extrait du fichier YAML d’intégration continue :

gitlab kubernetes job db yaml

Testing est le nom de la tâche à exécuter.

Services indique que l’on souhaite lier un service à notre container principal (l’image docker python:3.6 donnée plus bas). Le service que l’on créé ici est une base de données PostgreSQL (à l’aide de l’image docker postgres). Des variables d’environnement (variables) servent à paramétrer la base de données au lancement. Enfin, avant le script (before_script), on installe les dépendances du projet avec pip. Puis on lance les tests (script).

A l’exécution du pipeline, cela donne le résultat suivant :

gitlab kubernetes job db result

On voit que le runner créé une base temporaire puis la supprime.

Voici un aperçu de ce qu'il est possible de réaliser en mettant en place un pipeline de CI. Je vais continuer d'expérimenter de mon côté et espère pouvoir publier rapidement de nouveaux articles sur le sujet !

{{ message }}

{{ 'Comments are closed.' | trans }}