Mais, en fait c'est quoi un GitLab Runner ? 🤔
Je vais aujourd'hui tenter l'exercice de simplifier au l'explication du fonctionnement des GitLab Runners. Cet article n'explique pas comment écrire un pipeline de CI (juste un petit peu), il a pour unique vocation d'expliquer le principe de fonctionnement des GitLab Runners.
Et non, l'image n'a aucun rapport avec le thème de l'article, mais en cherchant bien ...
Qu'est ce qu'un GitLab Runner ?
Définition non technique: Un GitLab Runner, c'est un composant de l'application GitLab qui permet d'effectuer les tâches d'intégration continue, de livraison continue, de déploiement continue, ... Aussi connues sous le nom des "tâches de CI/CD".
- Le GitLab Runner n'est pas unique, vous pouvez en installer plusieurs pour une même instance (serveur) de GitLab (et générallement cela se fait sur des machines différentes).
- Les GitLab Runners vont "scruter" le serveur GitLab, les groupes, les projets en attente d'un travail à faire (tâches de CI/CD à réaliser).
- Et dès qu'il y a "quelque chose à faire" (compilation, tests unitaires, packaging, ...) un ou plusieurs runners vont exécuter ces tâches.
Définition plus technique: Le GitLab Runner est un programme développé en Go que vous pouvez installer sur un serveur, un portable, une VM, un container, un cluster Kube. Ce runner va faire du "polling http(s)" de l'instance GitLab pour "découvrir" si il a quelque chose à faire.
Enregistrement et Executor
Pour qu'il fonctionne, vous devez "enregistrer" votre runner auprès de l'instance GiLab (du serveur GitLab ou sur GitLab.com). Cela permettra ensuite au runner de "montrer patte blanche" lorsqu'il va vouloir accéder à l'instance GitLab.
Url & Token
Concrètement pour s'enregistrer (cela se fait par une commande shell, mais nous y reviendrons plus tard), le runner aura besoin d'une URL (celle de l'instance GitLab) et d'un token (un peu comme un "Sésame").
Ces 2 informations sont simples à trouver et il y a 3 endroits possibles:
Si vous êtes sur un GitLab onpremises (installé sur vos serveurs), vous trouverez l'information au niveau des paramètres de CI/CD:
- de l'instance (il faut être administrateur), et vous pourrez enregistrer des runners utilisables par l'ensemble des projets
- des groupes (et sous-groupes), et vous pourrez enregistrer des runners utilisables par l'ensemble des projets d'un groupe
- des projets, et vous pourrez enregistrer des runners utilisables par un projet spécifiquement
Si vous êtes sur GitLab.com, vous trouverez l'information au niveau des paramètres de CI/CD:
- de votre organisation
- des groupes (et sous-groupes)
- des projets
Enregistrement(registration)
Une fois que vous disposez de vos 2 informations (URL et Token), vous allez pouvoir enregistrer votre runner. Pour cela il suffit d'utiliser la commande suivante:
gitlab-runner register \
--non-interactive \
--url "${GITLAB_URL}" \
--registration-token "${CICD_TOKEN}" \
--executor "docker" \
--docker-image alpine:latest \
--description "mon runner" \
--tag-list "docker,gitpod" \
--run-untagged="true" \
--locked="false"
🖐 ️ Bien sûr, remplacez${GITLAB_URL}
et${CICD_TOKEN}
par les valeurs que vous aurez copiées précédemment
Remarques:
- Donnez toujours une description de votre runner, c'est un peu comme son "petit nom" :
--description "mon runner"
- Le paramètre
--tag-list
n'est pas obligatoire, mais il vous permettra de spécifier plus tard si certains jobs ne doivent être effectués que par certains runners (pratique pour des runners avec des outils pré-installer ou pour répartit la charge -
--run-untagged="true"
signifie qu'un runner avec un tag peut aussi exécuter un job sans tag
Executor ?!?
Vous avez du remarquer ces 2 lignes:
--executor "docker" \
--docker-image alpine:latest \
L'executor d'un runner, c'est le "moteur d'exécution" que le runner va utiliser pour effectuer/exécuter vos tâches de CI/CD. GitLab CI propose plusieurs types d'executors dont notamment l'executor shell et l'executor docker (pour les autres, je vous laisse consulter la documentation):
- Dans le cas de l'executor shell, le runner va utiliser les ressources logicielles installées sur la machine où lui même a été installé (ce peut-être une machine physique ou virtuelle ou même un container) pour exécuter les jobs du pipeline.
- Dans le cas de l'executor docker, le runner va utiliser un ou des containers pour pour exécuter les jobs du pipeline (à savoir que vous pouvez définir une image de container différente pour chacun des jobs du pipeline et le paramètre
--docker-image
vous permet de définir une image par défaut à chager).- Bien sûr, Docker doit être installé sur la machine qui héberge le runner.
Refs:
- Registration: https://docs.gitlab.com/runner/register/index.html
- Executors: https://docs.gitlab.com/runner/executors/index.html
Vérification
Une fois le runner enregistré, si vous retournez dans les paramètre de CI/CD de l'instance, du groupe ou du projet, vous pourrez vérifier que votre runner a bien été enregistré:
Mais à quel moment le runner exécute-t-il les jobs (et donc le pipeline) ?
En général le runner "se met en marche automatiquement" à chaque fois que vous poussez une modification de code (git push
), on parlera d'exécution de pipeline.
Mais il est tout à fait possible de déclencher un pipeline:
- Manuellement : https://docs.gitlab.com/ee/ci/pipelines/#run-a-pipeline-manually
- Avec l'API GitLab : https://docs.gitlab.com/ee/ci/triggers/index.html
- En programmant son exécution à l'avance : https://docs.gitlab.com/ee/ci/pipelines/schedules.html
Une fois le runner "en marche", il va clôner le projet (pour l'avoir dans son espace d'exécution) et exécuter les différents jobs dessus et renvoyer du feedback à l'instance GitLab.
Mais comment expliquer au Runner ce qu'il doit faire ?
Ensuite, l'étape pour indiquer à un runner (ou à des runners - car vous pouvez avoir plusieurs runners qui "travaillent" sur le même projet) ce qu'il(s) doit(vent) faire, c'est de décrire un pipeline (donc un ensemble de jobs) qui vont s'exécuter étapes par étapes. Vous pourrez faire ça à l'aide d'un fichier nommé .gitlab-ci.yml
qui se trouve toujours à la racine du projet, et il ressemblera à ceci:
stages: # Liste des étapes(stages) pour les jobs et leur ordre d'exécution
- build
- test
- deploy
build-job: # Ce job s'exécute en 1er à l'étape "build"
stage: build
script:
- echo "Compiling the code..."
- echo "Compile complete."
unit-test-job: # Ce job s'exécute à l'étape "test"
stage: test # Il ne commencera que lorsque l'étape précédente "build" sera terminée avec succès
script:
- echo "Running unit tests... This will take about 60 seconds."
- sleep 60
- echo "Code coverage is 90%"
lint-test-job: # Ce job s'exécute aussi à l'étape "test"
stage: test # Il peut s'exécuter en même temps que le job "unit-test-job" (si vous avez plusieurs runners)
script:
- echo "Linting code... This will take about 10 seconds."
- sleep 10
- echo "No lint issues found."
deploy-job: # Ce job s'exécute aussi à l'étape "deploy"
stage: deploy # Il ne commencera que lorsque l'ensemble de l'étape précédente "test" sera terminée avec succès
script:
- echo "Deploying application..."
- echo "Application successfully deployed."
Donc,
- Les stages s'exécutent de façon successive dans le temps
- Les jobs s'exécutent en parallèle à l'intérieur d'un stage, mais par défaut on ne peut pas en maîtriser l'ordre
- Avec l'apparition du mot-clé 'needs', il est maintenant possible de maîtriser l'ordre d'exécution des jobs au sein d'un même stage
- Si vous n'avez qu'un seul runner, les jobs d'un stage ne s'exécuteront pas en parallèle
Et votre pipeline (ici en cours d'exécution) ressemblera à ceci:
Pour résumer
- A chaque changement de code "poussé" vers GitLab
1️⃣ - Le(s) ou les runner(s) "détectent" qu'ils ont du travail
2️⃣ - Le(s) ou les runner(s) vont clôner le projet et exécuter les différents jobs dessus
3️⃣ 4️⃣ - Et ensuite ils vont renvoyer les résultats à l'instance GitLab
5️⃣
Un jour, il faudra que je prenne le temps de refaire ce shéma que j'utilise et réutilise
Pour info, en Février, j'avais fait un twitch sur le sujet : "Mais, c’est quoi un runner?", dont la vidéo est ici https://youtu.be/KOxZZO2fPuU (et le post correspondant ici #58)
J'ai essayé dans l'article d'aujourd'hui d'être le plus clair possible. N'hésitez pas à me proposer toute idée d'amélioration.
👋
- Si vous avez aimé (ou pas) ce "post" n'hésitez pas à utiliser les emojis pour réagir
- N'hésitez pas non plus à laisser des commentaires ou poser des questions
- Enfin, vous pouvez utiliser ce lien Rss feed pour vous abonner à ce blog à base d'issues