Un GitLab Runner en auto-scale(way)

L’objectif est de disposer d’un runner gitlab dont les capacités s’adaptent à la charge (auto-scale) et au calendrier (pourquoi faire tourner des serveurs les jours où on ne travaille pas ?) qu’on branchera ensuite sur gitlab.com ou une autre instance.
par Renaud Boyer, mis à jour le 30/11/2018

Pour cela nous allons configurer un « bastion » qui s’occupera d’instancier, via docker-machine (car il n’y a pas que kubernetes dans la vie), des serveurs chez Scaleway.

Ce guide est adapté de la procédure publiée par GitLab qui décrit la chose en anglais et pour des serveurs chez Digital Ocean.

On va avoir besoin d’un compte Scaleway et utiliser scaleway-cli (même si c’est tout à fait facultatif car le site permet de tout faire en quelques clics).

Création du bastion

Le bastion est un GitLab Runner normal, sauf qu’au lieu d'exécuter lui même les tâches (jobs) il va les déléguer à d’autres (docker-machine) et orchestrer le tout.

Pas de gros besoins pour cette machine, donc on va prendre un serveur Start 1-XS (1.99€/ mois pour du mono x86-64, 1 GB de RAM et 25 GB de stockage) qu’on appellera “bastion” et sur lequel on installera une Debian.

scw create --name=bastion --commercial-type=START1-XS debian-mini-stretch-25g
# retourne le UUID-de-la-machine
scw start UUID-de-la-machine

Une fois la machine démarrée, on s’y connecte en SSH pour y installer docker, docker-machine et gitlab-runner.

Pour récupérer l’ip du serveur c’est soit via l’interface web soit avec scw ps, colonne PORTS.

ssh root@ADRESSE_IP
apt update
apt upgrade -y
apt-get install -y apt-transport-https ca-certificates curl gnupg2 software-properties-common
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt-key add -
add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/debian $(lsb_release -cs) stable”
curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh | bash
apt install -y docker-ce gitlab-runner
base=https://github.com/docker/machine/releases/download/v0.16.0 &&
curl -L $base/docker-machine-$(uname -s)-$(uname -m) >/tmp/docker-machine &&
install /tmp/docker-machine /usr/local/bin/docker-machine

Configuration

La machine est prête, on peut maintenant passer aux réglages propres à propres à gitlab-runner.

Pour le connecter à une instance GitLab if faut récupérer un token (c’est dans réglages/ci-cd/runners) et suivre l’assistant de configuration :

ssh root@ADRESSE_IP 
gitlab-runner register
# Please enter the gitlab-ci coordinator URL (e.g. https://gitlab.com)
https://gitlab.com
# Please enter the gitlab-ci token for this runner
xxxxx
# Please enter the gitlab-ci description for this runner
bastion
# Please enter the gitlab-ci tags for this runner (comma separated):
(vide)
# Please enter the executor: ssh, docker+machine, docker-ssh+machine, ... :
docker+machine
# Please enter the Docker image (e.g. ruby:2.1):
python:3

Pour utiliser docker-machine avec scaleway on doit récupérer le pilote...

ssh root@ADRESSE_IP 
wget https://github.com/scaleway/docker-machine-driver-scaleway/releases/download/v1.5/docker-machine-driver-scaleway_1.5_linux_amd64.tar.gz
tar xf docker-machine-driver-scaleway_1.5_linux_amd64.tar.gz
chmod +x docker-machine-driver-scaleway
mv docker-machine-driver-scaleway /usr/local/bin/

… et disposer d’identifiants pour l’API :

  • Organization ID sur : https://cloud.scaleway.com/#/account
  • Secret key sur sur https://cloud.scaleway.com/#/credentials, bouton “new token”

On peut maintenant rentrer dans le vif de la configuration du runner. On va paramétrer notre bastion pour lancer des serveur de type C2M (8 x86-64, 16 GB, 50 GB à 0.036€ de de l’heure) à la demande. Il y a des limitations sur le nombre de machines dont on peut disposer sur son compte scaleway, si, par exemple, j’ai une limite de 5 serveurs C2M, je ne dois pas en demander 10.

ssh root@ADRESSE_IP
vim /etc/gitlab-runner/config.toml
concurrent = 4 On laisse 600 secondes une machine à ne rien faire avant de la supprimer (si on a plus que {IdleCount} lancées)
check_interval = 10 10s entre chaque appel à l’instance (divisé par le nombre de machines)
[session_server]
session_timeout = 1800
 
[[runners]]
name = "bastion"
url = "https://gitlab.com/"
token = "XXX"
executor = "docker+machine"
[runners.docker]
image = "python:3"
On retrouve ici les réponses données à l’assistant
[runners.machine] C’est à partir d’ici que cela devient intéressant...
IdleCount = 2

On souhaite toujours disposer de 2 machines prêtes à recevoir des tâches, ce qui veut dire que si, par exemple, 3 machines sont actuellement utilisées, docker-machine va en configurer deux de plus.

IdleTime = 600 On laisse 10 minutes une machine à ne rien faire avant de la supprimer pour revenir à {IdleCount}.
OffPeakPeriods = [
"* * 0-9,19-23 * * mon-fri *",
"* * * * * sat,sun *"
]
OffPeakTimezone = "Europe/Paris"
Entre 9h et 19h du lundi au vendredi on est en “heures de pointe”
OffPeakIdleCount = 0
OffPeakIdleTime = 3600
Hors heures de pointe on ne garde aucune machine d’avance. Par contre quand on en lance une, elle reste 1h en marche après avoir terminé sa tâche.
MaxBuilds = 100
MachineName = "bastion-%s"
 
MachineDriver = "scaleway"
MachineOptions = [
"scaleway-commercial-type=C2M",
"scaleway-region=par1",
“scaleway-image=da6ebdf0”,
"scaleway-token=SECRET_KEY",
"scaleway-organisation=ORGANIZATION_ID"
]
Les infos propres au driver docker-machine Scaleway : on veut des C2M hébergées à Paris avec Debian Stretch et on le demande poliment avec les jetons d’authentification récupérés plus haut.
[runners.cache]
[runners.cache.s3]
ServerAddress = "s3.nl-ams.scw.cloud"
AccessKey = "SECRET_KEY"
SecretKey = "ORGANIZATION_ID"
BucketLocation = "nl-ams"
BucketName = "bastion-runners-cache-123"
Insecure = true
[runners.cache.gcs]
Scaleway vient de mettre à disposition son Object Storage (compatible s3) en bêta, alors soyons fous, utilisons le pour faire un cache partagé entre les runners

 

Pour finir, on redémarre gitlab-runner et on peut regarder docker-machine faire son travail.

gitlab-runner restart
docker-machine ls

Les 2 serveurs vont être créés chez scaleway et docker-machine va prendre la main dessus pour y installer docker. Elles seront sollicitées par gitlab-runner au moment de lancer vos pipelnines, et il se chargera également de faire le ménage de temps en temps (couper les machines inutilisées, effacer celles qui ont fait 100 jobs, etc.).

Voilà, vous disposez maintenant d’un gitlab-runner capable d’encaisser un volume variable de travail, tout en optimisant les coûts (et en s’amusant avec docker-machine).

Références :

  • https://about.gitlab.com/2018/06/19/autoscale-continuous-deployment-gitlab-runner-digital-ocean/
  • https://docs.docker.com/install/linux/docker-ce/debian/
  • https://docs.gitlab.com/runner/install/linux-repository.html
  • https://docs.gitlab.com/runner/configuration/advanced-configuration.html
  • https://docs.gitlab.com/runner/configuration/autoscale.html