img

Générales

Mettez à l'échelle vos runners GitLab de manière simple et sécurisée avec docker-autoscaler


Lors de la mise en place de pipelines d’intégration continue et de déploiement continu, nous avons besoin de runners afin d’exécuter les différentes actions composant ces dernières.


Description :

Introduction

Lors de la mise en place de pipelines d’intégration continue et de déploiement continu, nous avons besoin de runners afin d’exécuter les différentes actions composant ces dernières.

Aussi, GitLab propose différents exécuteurs qui répondent à des besoins spécifiques. Je vous propose d’en détailler certains ci-dessous afin d’en comprendre les principales différences ainsi que les besoins auxquels ils répondent.

Deux principaux aspects sont généralement à prendre en compte lors de la mise en place de runners : la sécurité et la scalabilité. Nous allons donc voir comment GitLab répond à ces problématiques en proposant un nouvel exécuteur : le docker autoscaler.

Etat de l’art - les exécuteurs

GitLab propose différentes méthodes afin d’exécuter des jobs de pipelines, permettant de répondre à divers besoins, en fonction du contexte et des contraintes de chacun. Détaillons ici les exécuteurs principaux que nous avions à disposition jusqu’à présent.

L’exécuteur shell

Cet exécuteur permet d’exécuter des jobs dans un shell, sur la machine où est installé GitLab runner. Il présente l’avantage d’être simple à mettre en place, mais présente aussi de nombreux inconvénients.

Tout d’abord, il faut que la machine soit préconfigurée avec les outils dont vous avez besoin dans vos jobs, ou alors il faut installer ces différents outils au niveau de chaque job. Cependant, les jobs étant exécutés sur la même machine, les actions de l’un impacte directement les actions des autres, et il n’est pas possible d’utiliser différentes versions d’un même outil sans reconfiguration systématique au niveau de chaque job.

De plus, comme nous venons de le voir, un job en impacte directement un autre étant donné qu’ils sont exécutés sur la même machine, et ce sans aucun cloisonnement. Cela représente donc un important risque de sécurité : un utilisateur malveillant pourrait sans aucune difficulté impacter les jobs des autres et potentiellement voler des secrets ou autres informations sensibles présentes dans ces jobs.

Enfin, cet exécuteur ne peut répondre à des besoins importants de mises à l’échelle, étant donné que l’on a qu’une seule machine qui exécute les jobs.

L’exécuteur Docker

Cet exécuteur est similaire au précédent, dans le sens où les jobs sont exécutés sur la même machine que le GitLab runner. En revanche, chaque job est lancé dans un conteneur, ce qui permet d’assurer un cloisonnement entre les processus et donc d’améliorer significativement la sécurité.

En réalité, le cloisonnement, rendu possible grâce aux namespaces linux, ne s’arrête pas aux processus. Si cela vous intéresse, j’avais abordé ce sujet dans cet article.

De plus, il est possible de spécifier à GitLab l’image docker utilisée pour chaque job, ce qui permet d’avoir les outils strictement nécessaires et appropriés, et d’avoir potentiellement des versions différentes du même outil entre différents jobs.

Cependant, comme l’exécuteur shell, cet exécuteur ne peut répondre à des besoins importants de mises à l’échelle.

D’autre part, les jobs étant exécutés dans des conteneurs, il est parfois nécessaire que ces derniers soient lancés en mode privilégié, afin de permettre des actions comme de la construction d’images docker avec docker in docker, ou encore l’utilisation de testcontainers. Ce cas d’usage représente un risque élevé de sécurité étant donné qu’il est possible de s’échapper d’un tel conteneur et d’accéder à l’hôte, permettant de fait d’accéder aux autres jobs s’exécutant sur cette même machine.

L’exécuteur Kubernetes

Cet exécuteur permet d’exécuter des jobs dans des pods sur un cluster Kubernetes.

Il présente les mêmes avantages et inconvénients que l’exécuteur précédent, à savoir le cloisonnement des processus dans des conteneurs, la possibilité de spécifier une image docker pour chaque job, et le risque élevé de sécurité lors de l’utilisation de pod privilégié.

Le principal avantage de cet exécuteur par rapport à l’exécuteur docker est la mise à l’échelle permise grâce à Kubernetes. En effet, GitLab runner crée un pod par job, et profite ainsi des nombreux serveurs composant le cluster. De plus, une majorité de clusters Kubernetes implémente des solutions de mise à l’échelle automatique des nœuds, comme nous l’avons vu dans un précédent article avec Karpenter.

L’exécuteur docker+machine

Cet exécuteur permet d’exécuter des jobs dans des conteneurs, et est donc très similaire à l’exécuteur docker.

La principale différence avec ce dernier réside dans la mise à l’échelle. GitLab runner va créer des machines virtuelles à la volée, permettant de répartir les jobs sur différentes machines, dont le nombre varie en fonction de la demande.

La particularité de l’exécuteur docker+machine est la possibilité de n’exécuter qu’un seul job par machine. Ainsi, l’utilisation de conteneurs privilégiés est bien moins risquée étant donné qu’un seul job est exécuté à la fois, et que la machine est détruite à la fin, remplacée par une nouvelle.

Cet exécuteur répond donc aux principaux besoins énoncés en introduction, à savoir la sécurité et la scalabilité. Cependant, Docker l’a déprécié pour progressivement l’abandonner, obligeant GitLab à créer un fork afin de continuer à le maintenir. Dès la création de ce fork, GitLab a annoncé qu’ils ne corrigeraient que les problèmes critiques et ne proposeraient aucune nouvelle fonctionnalité, n’ayant probablement pas la bande passante pour reprendre l’entièreté du projet.

C’est ainsi qu’est né le besoin d’un nouvel exécuteur.

Une nouvelle solution - l’exécuteur docker-autoscaler

Ce nouvel exécuteur est similaire à l’exécuteur docker+machine, puisque qu’il s’agit de son successeur.

GitLab a fait le choix de repartir sur un projet from scratch, et de prendre une approche un peu différente de ce qui était fait avec docker+machine.

Tout d’abord, tout comme son prédécesseur, il enveloppe l’exécuteur docker afin de lancer des jobs dans des conteneurs et de bénéficier des mêmes options et fonctionnalités.

Afin de contrôler une flotte de serveurs, GitLab passe par l’utilisation de plugins. Ces plugins permettent de supporter différents fournisseurs de cloud, tels que AWS, Azure et GCP. Il s’agit d’un binaire à installer en plus de GitLab runner, en fonction du fournisseur choisi.

Il est important de noter que les plugins pour AWS, Azure et GCP sont actuellement en beta.

En plus de ces plugins, GitLab runner a besoin de quelques ressources. Par exemple, pour AWS, cet exécuteur a besoin des ressources suivantes :

  • Une AMI contenant docker : elle sera utilisée pour initialiser chaque nouvelle EC2
  • Un autoscaling group : il sera géré par GitLab runner qui ajoutera ou supprimera des instances en fonction de la demande en jobs côté GitLab
  • Une politique IAM : elle sera utilisée par GitLab runner afin de pouvoir modifier les caractéristiques de l’autoscaling group et se connecter aux différentes instances

 

On entend parfois parler de “runner manager”, qui est le processus responsable de créer le nécessaire (instances, pods, conteneurs, …) afin d’exécuter des jobs GitLab. Un runner de type “kubernetes” peut exécuter plusieurs jobs en parallèle sur plusieurs pods, mais il apparaît comme un seul runner dans l’interface de GitLab. Ce processus peut s’exécuter n’importe où (dans un cluster Kubernetes, dans une EC2, …), dès lors qu’il a les droits nécessaires afin de créer des instances / pods / conteneurs en fonction du type d’exécuteur choisi (politique IAM ci-dessus).

Comme vous pouvez le constater, GitLab a essayé de simplifier au maximum la configuration, ce qui est plutôt réussi.

Mettre en place des runners GitLab avec l’exécuteur docker-autoscaler

Maintenant que vous en savez plus, nous allons passer à la pratique en déployant des runners GitLab avec l’exécuteur docker-autoscaler sur le cloud d’AWS.

Prérequis

Vous devez avoir accès à un compte AWS.

Bien que GitLab runner puisse être déployé de différentes manières (chart Helm, conteneur, service linux, etc), je vous recommande de le déployer à l’aide du chart Helm officiel dans un cluster Kubernetes si vous en disposez d’un. J’ai donc au préalable déployé un cluster EKS.

Bien évidemment, si vous ne disposez pas de cluster Kubernetes, il est beaucoup plus simple et rapide de déployer GitLab runner dans une EC2 ou un conteneur Fargate. La configuration GitLab runner reste sensiblement la même.

Commentaires

Mounir Ikine

03 Feb 2025

Great info

Ajouter un commentaire

Newsletter

Abonnez-vous à notre newsletter pour être à jour de toutes nos actualités !