Skip to content

Gitlab-CI Autoscale avec AWS

Auteur : Philippe Le Van - @plv@framapiaf.org

Date : 7 octobre 2022

Introduction

Qu'est-ce que la CI (Continuous integration) ?

La CI (ou intégration continue) est un système qui permet de lancer des traitements sur un code à chaque fois qu'on pushe une nouvelle version dans GIT.

Nous utilisons Gitlab comme repository GIT et Gitlab est livré avec une CI qui s'appelle Gitlab-ci.

Concrêtement quand on fait un git push, gitlab-ci détecte qu'une nouvelle version vient d'être poussée. Le système applique alors les recettes décrites le fichier .gitlab-ci.yml à la racine du projet.

Un git push déclenche une pipeline dans gitlab-ci. Cette pipeline est en général composée de plusieurs jobs (build, check de coding style, tests, deploy, ...).

Autoscaling dans la CI ?

Le principe de l'autoscaling et que l'on peut lancer autant de taches de CI que l'on souhaite sans avoir de rallentissement dans nos traitements.

Concrêtement chez nous, à chaque fois qu'un job est créé, nous créons une machine virtuelle chez AWS et nous lançons le job sur cette machine.

Que fait-on dans une CI ? Docker, build, test, deploy

Nos projets sont développés puis déployés avec Docker.

Les tâches typiques d'une CI dans un projet dockerisé sont :

  • job build : la création d'une image docker qui permet de faire tourner son projet
  • job tests : le lancement des tests unitaires / fonctionnels du projet
  • job deploy : le déploiement du projet en production ou en validation suivant la branche déployée

Exemple de fichier .gitlab-ci.yml (très simplifié, c'est juste pour voir à quoi ça peut ressembler)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
stages:
  - build
  - tests
  - deploy

before_script:
  - docker info
  - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY

build-job:
  stage: build
  script:
    - docker-compose build --pull
    - docker push $CI_REGISTRY_IMAGE/ci:latest

test-job:
  stage: tests
  script:
    # on installe les dépendances d'un projet php
    - docker-compose run --rm web composer install
    # vérification du coding style
    - docker-compose run --rm web make _phpcs
    # lancement des tests unitaires
    - docker-compose run --rm web bin/phpunit

deploy-job:
  stage: deploy
  script:
    - ./deploy.sh

Runners

Un runner est un serveur que l'on fait tourner sur une machine et qui peut lancer un job sur la demande de gitlab-ci.

Concrêtement, on installe un logiciel gitlab-runner sur une machine. On l'enregistre auprès de gitlab-ci. A partir de là, à chaque fois qu'un git push est effectué, les jobs décrits dans .gitlab-ci.yml sont envoyés au runner qui se charge de les lancer.

On fait tourner le ou les runners sur des machines différentes de la machine de Gitlab pour que le lancement des jobs ne rallentissent pas Gitlab.

Aller plus loin

Cette introduction générale donne le principe général d'une CI. Pour aller plus loin, je vous conseille de regarder directement la documentation de gitlab-ci.

La section suivante est beaucoup plus complexe et suppose que vous avez bien compris le principe d'une CI.

Autoscaling

Le principe de l'autoscaling est de créer de nouvelles machines virtuelles (VM) à chaque fois qu'un job est lancé.

Schéma général

Schéma général de la CI autoscale

Etapes du montage

Etape 1, flèche bleue : installer gitlab

Gitlab prend pas mal de ressources, on l'installe sur un serveur dédié.

(Chez nous on l'installe avec Ansible et Docker)

Etape 2, flèche bleue : installer un runner "docker+machine"

Les runners de Gitlab-ci ont plusieurs modes de fonctionnement. Là on va choisir le mode docker+machine.

En gros le Runner qu'on installe ne va pas servir à lancer les jobs lui même. Il va utiliser un outil qui s'appelle "docker machine" pour créer une machine virtuelle chez AWS et lancer le job là bas.

Gitlab publie une image docker pour installer un runner : c'est gitlab/gitlab-runner. Le problème c'est que cette image ne contient pas l'exécutable de "docker-machine". Nous avons créé une image kibatic/gitlab-runner-bastion qui se base gitlab/gitlab-runner et qui installe docker-machine.

Etape 3, flèche bleue : créer un bucket AWS S3 pour le cache

Pour accélérer la CI, on utilise des systèmes de cache. Mais dans le cas de l'autoscaling, les traitements sont lancés sur des VM différentes. Il faut donc enregistrer le cache sur un système partagé quelque part.

Dans la pratique nous avons créé un bucket S3 pour enregistrer le cache.

Etape 4, flèche verte : enregistrement du runner

C'est une procédure qui permet de relier le runner à Gitlab. Il suffit de suivre la procédure documentée par Gitlab.

Création de la machine virtuelle et lancement du job (les flèches rouges)

Création d'une machine virtuelle

Parfois une machine virtuelle déjà créée est déjà disponible. Mais si ça n'est pas le cas :

  • le runner lance docker-machine pour créer une instance EC2
  • une fois la machine créée, le runner installe le daemon docker
  • une fois docker installé, le runner installe un "executor", chez nous c'est une image kibatic/gitlab-runner basée sur une debian. Cette image contient notamment les clients docker et docker-compose. Ces clients docker vont interagir avec le daemon docker présent dans l'instance EC2 pour lancer des traitements docker.

Lancement des jobs

Le runner commence par gérer les caches (c'est un sujet compliqué que je ne vais détailler ici).

Le runner lance ensuite les jobs à l'intérieur des exécutors dans la machine virtuelle EC2.

Références pour aller plus loin