Environnement de test

Table of Contents

1 Introduction gitlab-ci et runners

  • Voir le cours sur l'intégration continue avec Gitlab (https://ramet.gitlab.io/r4.02-qualite-dev/gitlab-ci.html)
  • Voir également le cours sur l'orchestration de conteneurs avec docker/podman (https://moodle.u-bordeaux.fr/course/view.php?id=5358)
    • on a vu comment construire une image podman contenant un runner Gitlab configuré en mode shell
    • on va voir comment configurer un runner Gitlab en mode docker, mais configuré nativement pour utiliser podman
  • Mettre en place des runners de type shell et docker
  • Tester avec un job dans les 2 configurations

1.1 Forker le projet Heat, accès API Gitlab avec un token personnel

  1. Forker le projet Heat sur le Gitlab de l'IUT. Il devrait être visible à cette url : https://gitlab-ce.iut.u-bordeaux.fr/$USER/heat. Ajouter fpruvost et ramet comme "Maintainer" à votre projet cf. Manage -> Members -> Invite members. Si vous aviez déjà un fork de heat le supprimer via Settings -> General -> Advanced -> Delete project.
  2. Activer les pipelines (CI/CD) dans les settings (General, Visibility, project features, permissions) de votre projet Heat
  3. Désactiver les "Instance runners" : dans Settings, CI/CD, Runners, Instance Runners (colonne de droite), désactiver l'option Enable instance runners for this project
  4. Se créer un "Personal Access Token" (Preferences -> Access Tokens -> Add new token) sur le Gitlab de l'IUT avec accès api, puis le sauvegarder localement :

    echo "le token avec acces complet api" > ~/.gitlabtoken
    export TOKEN=`cat ~/.gitlabtoken`
    # vérifier que vous pouvez cloner votre dépôt heat
    git clone https://$USER:$TOKEN@gitlab-ce.iut.u-bordeaux.fr/$USER/heat.git
    cd heat
    

    Note : Ce token est personnel et doit être gardé secret, il permet de vous authentifier sur Gitlab. Il inclut les droits de lecture/écriture sur le registry Gitlab. Il n'est pas nécessaire pour cloner votre projet si vous avez déjà configuré une clé SSH sur votre compte Gitlab.

1.2 Installation de gitlab-runner

Installer une version récente de gitlab-runner (>=16.0):

cd $HOME
curl -L --output ./gitlab-runner "https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-amd64"
chmod +x ./gitlab-runner
export PATH=$PATH:$HOME
# puis démarrer le programme gitlab-runner
~/gitlab-runner run
# laissez le tourner, ouvrez un nouvel onglet dans le terminal pour la suite
# ctrl-c pour quitter

Pour le moment ça donne une erreur car le fichier de configuration config.toml n'existe pas encore. Il faut faire un premier enregistrement de runner pour le créer automatiquement.

1.3 Runner de type shell

Enregistrer un runner type shell executor via : Settings -> CI/CD -> Runners -> New project runner. Remplir les champs Tags "shell" et Runner description "IUT shell mode" puis valider Create runner. Ensuite sélectionner Operating system : Linux. Puis copier/coller la commande gitlab-runner register proposée dans Step 1 dans votre terminal. Exemple :

gitlab-runner register  --url https://gitlab-ce.iut.u-bordeaux.fr  --token glrt-iMzkBpbwCRpJ-vysaXA4

Suivre les étapes en tapant la touche entrée et indiquer executor: shell.

Puis redémarrer gitlab-runner :

~/gitlab-runner run

Il doit bien s'exécuter sans erreurs cette fois.

Dans votre fork de Heat, créer une branche git 'auto', se positionner dessus, puis ajouter le fichier .gitlab-ci.yml permettant de lancer un job sur chaque runner, par exemple pour juste vérifier que le job se lance bien :

job-shell:
  tags: ['shell']
  script: ls -la

Pour voir les logs des jobs gitlab-ci il faut se rendre sur la page Build -> Pipelines puis cliquer sur la puce du pipeline (dans la colonne Status) ou sur la puce d'un job en particulier (colonne Stages).

L'erreur suivante peut apparaître :

ERROR: Job failed: prepare environment: exit status 1. Check https://docs.gitlab.com/runner/shells/index.html#shell-profile-loading for more information

Pour régler le problème, ouvrir le fichier .bash_logout à la racine de votre home, puis commenter la section suivante :

#if [ "$SHLVL" = 1 ]; then
#    [ -x /usr/bin/clear_console ] && /usr/bin/clear_console -q
#fi

Vous pouvez relancer le job en cliquant sur le bouton "Retry all failed or cancelled jobs" sur la page des pipelines sur la droite ou en cliquant directement sur le job en échec puis bouton "Run again".

Le job doit passer en vert et le log doit afficher le résultat des commandes inscrites dans la section script du job :

environment_job_shell.png

Figure 1: job shell

Note : remarquer que gitlab clone automatiquement le projet sur la bonne branche 'auto' et vous positionne directement dans le dossier heat.

En mode shell les jobs sont directement lancés dans votre environnement utilisateur tandis qu'en mode docker les jobs sont lancés dans un conteneur d'une image docker (ou podman). Comme l'environnement shell n'est pas facilement configurable, car vous n'êtes pas administrateurs sur la session ubuntu, on travaillera exclusivement à partir d'une image docker/podman en mode conteneur par la suite.

1.4 Création du service gitlab-runner

A la place de gitlab-runner run gitlab-runner peut aussi être démarré comme un service. L'avantage sera d'avoir les gitlab runners automatiquement disponibles dans vos prochaines session Ubuntu.

Voici les commandes pour créer un service gitlab utilisateur :

mkdir -p ~/.config/systemd/user/

# copier le template vers ~/.config/systemd/user
curl https://automatisation-ramet-09f19b71cd035def286edcb4a35616cad4167379e2.gitlab.io/gitlab-runner.service -o ~/.config/systemd/user/gitlab-runner.service

sed -i -e "s#\$HOME#$HOME#g" ~/.config/systemd/user/gitlab-runner.service

systemctl --user daemon-reload
systemctl --user enable --now gitlab-runner.service

# verifier que le service gitlab-runner est bien actif avec
systemctl --user status gitlab-runner.service

Pour exécuter toutes ces commandes d'un coup vous pouvez utiliser le script config-gitlab.sh de la manière suivante :

source config-gitlab.sh

Cela va créer le fichier ~/.config/systemd/user/gitlab-runner.service à partir de gitlab-runner.service, remplacer $HOME par votre répertoire home (cf. echo $HOME) puis activer le service gitlab-runner.

1.5 Runner de type docker

Enregistrer un nouveau runner type docker executor via : Settings -> CI/CD -> Runners -> New project runner. Remplir les champs Tags "docker" et Runner description "IUT docker mode" puis valider Create runner. Ensuite sélectionner Operating system : Linux. Puis copier/coller la commande gitlab-runner register proposée dans Step 1 dans votre terminal. Exemple :

gitlab-runner register  --url https://gitlab-ce.iut.u-bordeaux.fr  --token glrt-iMzkBpbwCRpJ-vysaXA4

Suivre les étapes en tapant la touche entrée et indiquer executor docker et image par défaut : registry.u-bordeaux.fr/vhub/alpine:3.18. Un nouveau runner est créé et visible sur la page Settings -> CI/CD -> Runners -> Project runners.

Modifier le script .gitlab-ci.yml afin d'ajouter un nouveau job qui devra s'exécuter sur le runner docker, on utilise le système de tags pour cela. Le job shell précédent peut être commenté et ainsi non exécuté juste en ajoutant un point (.) devant le nom du job. Commiter et pousser puis observer le log du job (Build -> Pipelines).

.job-shell:
  tags: ['shell']
  script: ls -la

job-docker:
  tags: ['docker']
  image: registry.u-bordeaux.fr/vhub/alpine:3.18
  script: ls -la

Note : Pour s'assurer que les jobs seront bien lancé avec les runners configurés dans ce TP, il est nécessaire de désactiver les shared runners déjà installés au département. Pour cela, aller sur : Settings -> CI/CD -> Runners et désactiver l'option "Enable instance runners for this project" !

Le job doit être en erreur car docker n'est pas installé.

environment_job_docker_error.png

Figure 2: erreur job docker

En effet sur les machines de l'IUT docker n'est pas installé car podman est considéré comme une alternative plus sûre. Une configuration additionnelle de gitlab-runner est requise pour fonctionner avec podman (cf. https://docs.gitlab.com/runner/executors/docker.html#use-podman-to-run-docker-commands).

Voici les commandes pour créer un service podman utilisateur :

/mnt/roona/vms/vnet/bin/podman-init-storage

mkdir -p ~/.config/systemd
mkdir -p ~/.config/systemd/user

# copier les fichiers de /usr/lib/systemd/user/ vers ~/.config/systemd/user
cp /usr/lib/systemd/user/podman.service ~/.config/systemd/user/
cp /usr/lib/systemd/user/podman.socket ~/.config/systemd/user/

systemctl --user enable podman.socket
systemctl --user daemon-reload
systemctl --user start podman.socket

# verifier que le service podman est bien actif avec
systemctl status --user podman.socket

Vous pouvez utiliser le script config-podman.sh de la manière suivante :

source config-podman.sh

Puis modifier le fichier ~/.gitlab-runner/config.toml :

  1. Ajouter environment = ["FF_NETWORK_PER_BUILD=1"]
  2. Ajouter privileged = true
  3. Ajouter host = "unix:///run/user/76955/podman/podman.sock, résultat de systemctl --user status podman.socket (champs Listen)

Un exemple de configuration

[[runners]]
  name = "runner-docker"
  url = "https://gitlab-ce.iut.u-bordeaux.fr"
  id = 482
  token = "glrt-blablabla-1234567890"
  token_obtained_at = 2023-08-10T15:16:12Z
  token_expires_at = 0001-01-01T00:00:00Z
  executor = "docker"
  environment = ["FF_NETWORK_PER_BUILD=1"]
  [runners.cache]
    MaxUploadedArchiveSize = 0
  [runners.docker]
    host = "unix:///run/user/76955/podman/podman.sock"
    tls_verify = false
    image = "registry.u-bordeaux.fr/vhub/alpine:3.18"
    privileged = true
    disable_entrypoint_overwrite = false
    oom_kill_disable = false
    disable_cache = false
    volumes = ["/cache"]
    shm_size = 0
    network_mtu = 0

Puis redémarrer le service:

systemctl --user restart gitlab-runner

Relancer le job-docker en erreur. Il doit maintenant passer au vert.

environment_job_docker_success.png

Figure 3: job docker

Noter que le job est lancé dans un conteneur podman issu de l'image "registry.u-bordeaux.fr/vhub/alpine:3.18".

1.6 Mise en place d'un pipeline

Le programme heat est développé en langage C et nécessite une phase de compilation. Ainsi, mettre en place un pipeline de type job build, puis test.

Commiter et pousser ces modifications dans le fichier .gitlab-ci.yml.

stages:
  - build
  - test

default:
  image: registry.u-bordeaux.fr/vhub/alpine:3.18
  tags: ['docker']

build:
  stage: build
  script:
    - cmake -B build
    - cmake --build build
  cache:
    key: "$CI_COMMIT_REF_SLUG"
    untracked: true
    policy: push

test:
  stage: test
  needs: ["build"]
  script:
    - ctest --test-dir build --verbose
  cache:
    key: "$CI_COMMIT_REF_SLUG"
    untracked: true
    policy: pull

En l'état le job build va échouer car les dépendances du projet ne sont pas installées (gcc, cmake, etc). On va s'en occuper dans la section suivante.

Note : stages permet de définir les étapes intermédiaires du pipeline et d'y associer un ensembles de jobs. default permet de définir certaines propriétés qui seront utilisées dans tous les jobs. cache permet de sauvegarder des fichiers entre jobs ou pipelines successifs (untracked: true pour sauvegarder tous les fichiers en dehors de ce qui est indexé par git). Plus d'explications sont disponibles dans la documentation en relation avec le cache Gitlab.

2 Définir son environnement de test

2.1 Installation des dépendances dans les jobs gitlab-ci

Les images de base existantes sur internet sont rarement suffisantes pour satisfaire les besoins de notre logiciel. Il faut donc ajouter l'installation des dépendances spécifiques dans les scripts de test. Modifier la configuration pour ajouter l'installation des dépendances, ici apk add --update git make gcc g++ cmake, dans une section before_script mis dans la partie default (sera exécuté avant tous les jobs) puis commit+push.

default:
  image: registry.u-bordeaux.fr/vhub/alpine:3.18
  before_script: apk add --update git make gcc g++ cmake

environment_pipeline_build_test.png

Figure 4: Pipeline build, test

2.2 Construction d'une image podman en local

En l'état, chaque nouveau push dans des branches déclenchera l'installation des dépendances. Cela peut être long et gourmand en ressources lorsque le poids des dépendances est élevé. On va donc construire une image une fois pour toute contenant le bon environnement de test.

Construire une image docker en local (avec la commande podman) :

podman run -it registry.u-bordeaux.fr/vhub/alpine:3.18
# ajouter les paquets (apk add --update git make gcc g++ cmake), tester que heat compile, une fois terminé sortir avec ctrl+d

A présent que l'environnement des tests pour Heat est fonctionnel dans l'image on peut sauvegarder l'ensemble des commandes dans un fichier Dockerfile (la recette)

FROM registry.u-bordeaux.fr/vhub/alpine:3.18
RUN apk add --update git make gcc g++ cmake

puis taper :

podman build -t heat -f Dockerfile .

et vérifier que l'image se construit bien.

2.3 Stocker votre image sur le registry gitlab de heat

Pousser l'image sur le registry de votre projet gitlab, cf. Deploy -> Container Registry (l'option Container registry doit être activée dans Settings -> General -> Visibility, project features, permissions).

  • D'abord construire l'image avec la bonne convention de nommage pour pouvoir la pousser sur le registry. Le nom du registry est indiqué dans gitlab dans Deploy -> Container Registry, cf. Build image. En plus d'un nom, l'image est dotée d'une étiquette de version, par défaut latest.

    podman build -t gitlab-ce.iut.u-bordeaux.fr:5050/$USER/heat/testing -f Dockerfile .
    
  • Vous pouvez associer à cette image un numéro de version, ex. v0.1 en plus, à des fins d'archivages et de reproductibilité. En effet lorsque vous mettrez à jour l'image par défaut, latest, la précédente version sera écrasée sans possibilité de vérifier plus tard quelles étaient les versions des dépendances.

    podman tag gitlab-ce.iut.u-bordeaux.fr:5050/$USER/heat/testing gitlab-ce.iut.u-bordeaux.fr:5050/$USER/heat/testing:v0.1
    
  • Authentifiez-vous sur le registry Gitlab puis poussez l'image.

    export TOKEN="votre personnal access token, cf. https://gitlab-ce.iut.u-bordeaux.fr/-/profile/personal_access_tokens"
    export TOKEN=`cat ~/.gitlabtoken` # si vous l'avez stocké dans ce fichier
    podman login gitlab-ce.iut.u-bordeaux.fr:5050 -u $USER -p $TOKEN
    podman push gitlab-ce.iut.u-bordeaux.fr:5050/$USER/heat/testing
    podman push gitlab-ce.iut.u-bordeaux.fr:5050/$USER/heat/testing:v0.1
    

Vous retrouvez les images sur le gitlab dans Deploy -> Container Registry, et elle seront réutilisables par les jobs des pipelines.

2.4 Utiliser votre image dans les jobs gitlab-ci

Maintenant on voudrait pouvoir exploiter notre environnement défini dans l'image dans notre pipeline de tests.

Modifier son pipeline pour utiliser l'image docker qui vient d'être construite et stockée dans le registry Gitlab :

  • il suffit de changer le nom de l'image dans le .gitlab-ci.yml, en remplacant image: registry.u-bordeaux.fr/vhub/alpine:3.18 par image: gitlab-ce.iut.u-bordeaux.fr:5050/$USER/heat/testing (remplacer $USER par votre login)
  • pour être plus générique vous pouvez remplacer la longue adresse de l'image par image: $CI_REGISTRY_IMAGE/testing, CI_REGISTRY_IMAGE étant une variable d'environnement créé par Gitlab lors du job et qui contient le nom par défaut des images docker du registry associé au projet.

Vu que votre image contient déjà les dépendances requises pour la compilation de Heat vous pouvez simplifier le script .gitlab-ci.yml en supprimant les étapes concernant l'installation des dépendances (before_script) puis relancez le pipeline (commit+push) et vérifiez que les tests passent toujours.

Ajouter le paquet doxygen dans la liste des paquets à installer via le Dockerfile. Reconstruire et pousser l'image sur le registry.

podman build -t gitlab-ce.iut.u-bordeaux.fr:5050/$USER/heat/testing -f Dockerfile .
podman push gitlab-ce.iut.u-bordeaux.fr:5050/$USER/heat/testing

Activer la construction de la documentation avec l'option de configuration cmake -DHEAT_DOC=ON cf. cmake -B build -DHEAT_DOC=ON, commit+push.

Faites de même pour la dépendance MPI, ajoutez les paquets musl-dev openmpi openmpi-dev openssh dans les dépendances et activez l'option cmake -DHEAT_USE_MPI=ON, commit+push. En cas d'échec du job de test il faut ajouter des variables d'environnement au job, exemple :

test:
  stage: test
  needs: ["build"]
  variables:
    OMPI_ALLOW_RUN_AS_ROOT: "1"
    OMPI_ALLOW_RUN_AS_ROOT_CONFIRM: "1"
  script:
    - ctest --test-dir build --verbose
  cache:
    key: "$CI_COMMIT_REF_SLUG"
    untracked: true
    policy: pull

Remarquez qu'il est plus flexible de maintenir l'environnement de test via un fichier tel que le Dockerfile, car ainsi l'environnment est sauvegardé, partagé, et peut être re-déployé rapidement sur d'autres machines avec une simple commande docker. La maintenance au coup par coup d'une machine de test spécifique est pratique au départ mais il est difficile de suivre ce qui a été finalement installé, et si la machine plante définitivement il faut ré-installer une nouvelle machine spécifique ce qui peut être fastidieux.

En revanche la re-construction et le re-déploiement de l'image docker à la main à chaque mise à jour n'est pas passionnant. On va donc automatiser cette action.

3 Automatisation de la construction de l'image docker

On va ensuite ajouter un job Gitlab pour construire l'image docker et la pousser sur le registry comme 1ère étape. Modifier le nom du fichier de recette docker afin d'être plus spécifique, par exemple Dockerfile -> dockerfile-buildenv (par convention Dockerfile devrait être la recette permettant de déployer l'application installée, et pas son environnement de test). Sauvegarder ce nouveau fichier dockerfile-buildenv via un commit git. Modifier ensuite le fichier .gitlab-ci.yml et y ajouter une 1ère étape buildenv dans stage (avant build et test) ainsi qu'un nouveau job (cf. https://docs.gitlab.com/ee/user/packages/container_registry/build_and_push_images.html#use-gitlab-cicd) comme ci-dessous :

buildenv:
  stage: buildenv
  image: quay.io/podman/stable
  before_script:
    - podman login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
  script:
    - podman build -t $CI_REGISTRY_IMAGE/testing -f dockerfile-buildenv .
    - podman push $CI_REGISTRY_IMAGE/testing

Note : L'authentication nécessaire pour accéder au registry est gérée automatiquement pour un pipeline.

Pour information, en Docker, cela donnerait :

buildenv:
  stage: buildenv
  image: docker
  services:
    - docker:dind
  before_script:
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
  script:
    - docker build -t $CI_REGISTRY_IMAGE/testing -f dockerfile-buildenv .
    - docker push $CI_REGISTRY_IMAGE/testing

Si le job échoue avec un message d'erreur du type "dial tcp: lookup docker on… no such host" il faudra ajouter une ligne à votre fichier de configuration du runner. Editer le fichier ~/.gitlab-runner/config.toml et modifier le champs volume tel que volumes = ["/var/run/docker.sock:/var/run/docker.sock", "/cache"].

4 Maintenance de l'image

Réfléchir aux différentes conditions possibles pour le déclenchement de la reconstruction de l'image docker de test. Pourquoi reconstruire :

  1. Selon une politique interne de retrocompatibilité.
  2. Si on a besoin d'une version plus récente des dépendances (changement API, nouvelle fonctionnalité).
  3. Selon la cible client (contrainte sur l'environnement).
  4. Essayer de valider pour les LTS des OS ciblés (ex. Windows 10, Ubuntu 22.04), ne pas rester sur un vieil OS car les dépendances vont devenir figées nous empechant de traiter des mises à jour nécessaires avec les versions plus récentes.

4.1 Toujours tout reconstruire

C'est le cas par défaut dans notre situation actuelle, chaque nouveau commit poussé sur le serveur déclenche un nouveau pipeline dont le job buildenv. Pour changer cet état de fait, il faut ajouter des règles spécifiques au job Gitlab en question afin de le déclencher uniquement sous certaines conditions (cf. sections suivantes).

Cette stratégie permet de démontrer que nos tests sont valides dans un environnement dont on a testé le déploiement juste avant. Cela renforce le sentiment de robustesse. En revanche ce n'est envisageable que pour des cas où la ré-installation des dépendances à chaque pipeline est assez rapide (quelques minutes maximum). Dans le cas contraire cela peut devenir contre-productif et on envisagera de réduire le temps dû au déploiement de l'environnement de test (cf. sections suivantes).

4.2 Reconstruire qu'une partie

Dans certaines situations on peut choisir d'identifier une partie "stable" et une autre plus "en avance de phase" (avec des dépendances plus ou moins exotiques). Par exemple, sur certaines dépendances on peut avoir besoin d'une version non release (non numérotée, ex. branche master ou autre branche). Ainsi, on peut construire un environnement de base stable (template), qu'on ne construit qu'une fois de temps en temps et re-déployer la partie "en avance de phase" à chaque pipeline.

Dans cette optique, commentez le job de reconstrution de l'image (on va considérer que c'est la partie stable qui n'a pas besoin d'être ré-installée) et ajouter un job gtest installant la toute dernière version de googletest à chaque nouveau pipeline, exemple :

stages:
  - buildenv
  - gtest
  - build
  - test

default:
  image: $CI_REGISTRY_IMAGE/testing
  tags: ['docker']

.buildenv:
   stage: buildenv
   image: quay.io/podman/stable
   before_script:
     - podman login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
   script:
     - podman build -t $CI_REGISTRY_IMAGE/testing -f dockerfile-buildenv .
     - podman push $CI_REGISTRY_IMAGE/testing

gtest:
  stage: gtest
  script:
    - git clone https://github.com/google/googletest.git
    - cd googletest/
    - cmake -B build -S . -DCMAKE_INSTALL_PREFIX=$PWD/../gtest
    - cmake --build build
    - cmake --install build
  cache:
    key: "$CI_COMMIT_REF_SLUG"
    untracked: true
    policy: push

Modifier le fichier CMakeLists.txt afin de vérifier que googletest a bien été installé :

  • ajouter find_package(GTest REQUIRED) à la ligne 12 de CMakeLists.txt

Modifier le job build afin de pouvoir utiliser l'installation de googletest :

  • cmake -B build -DHEAT_DOC=ON -DHEAT_USE_MPI=ON -DCMAKE_PREFIX_PATH=$PWD/gtest
  • policy: pull-push

Commiter et pousser afin de valider ce nouveau pipeline.

Note : Une explication détaillée de l'option policy est disponible dans la documentation en relation avec le cache Gitlab.

4.3 Mise à jour de l'image stable

Avec une stratégie où l'on ne recontruit pas tout lors de chaque pipeline il faut décider d'une politique de mise à jour pour la construction de l'image de base "stable". Plusieurs possiblités s'offrent à nous pour déclencher la mise à jour.

4.3.1 Si Dockerfile change

Une première méthode consiste à mettre à jour l'image dès que la recette, c'est à dire le fichier dockerfile-buildenv, change.

Ajouter ce code dans buildenv (décommenter le job en enlevant le . de la ligne .buildenv:) commiter, pousser.

only:
  changes:
    - dockerfile-buildenv

Normalement buildenv n'est pas déclenché.

Maintenant ajouter le paquet curl à la liste des paquets à installer dans le dockerfile-buildenv, commiter, pousser. Observez que buildenv se déclenche bien.

Il est clair que si la recette change il faut mettre à jour l'image. En revanche si la recette ne change pas pendant longtemps cela implique que l'environnement sera figé dans le même temps et peut devenir trop ancien. Il faudra donc mettre à jour l'image de temps en temps manuellement via un docker (podman) build+push à partir de sa machine.

4.3.2 Manuellement (bouton manual)

Une seconde méthode consiste à ajouter un bouton dans le pipeline afin de laisser la liberté aux développeurs de mettre à jour quand ils le souhaitent.

Supprimer la partie only: changes: et ajouter when: manual au job buildenv et déclencher manuellement le job en allant sur la page des pipelines et en cliquant sur le bouton associé au job buildenv.

C'est une méthode flexible mais le risque est de ne pas faire la mise à jour assez souvent.

4.3.3 Périodique (schedule)

Une troisième méthode consiste à déclencher le job périodiquement. Pour cela il faut créer un pipeline spécifique de type schedule.

Dans Gitlab aller dans Build -> Pipeline schedules -> New schedule.

  • Description : buildenv
  • Interval Pattern : Every week
  • Cron Timezone : UTC+2 Paris
  • Target branch or tag : auto

Create pipeline schedule.

Remarquez la date de prochain déclenchement du pipeline dans la colonne Next Run.

Ensuite, modifier buildenv pour supprimer la partie when: manual et remplacer par :

only:
  - schedules

Commiter, pousser. Le job se déclenche sans buildenv. En effet dans cette configuration ce dernier ne sera lancé que lors du pipeline de type schedule, à la date décidée dans les paramètres du schedule buildenv. Il est possible de tester le schedule en cliquant sur le bouton Play dans la page des schedules. Vérifiez que cela fonctionne bien.

5 Optimisation de l'image

5.1 Réflexion sur la taille de l'image

Pour certains projet il y a beaucoup de dépendances et elles sont lourdes en terme de stockage. Il est donc important d'optimiser au mieux la taille de l'image.

Vérifier la taille occupée par les images et conteneurs podman avec la commande podman system df. Si l'image de base utilisée est par exemple ubuntu cela peut peser plusieurs gigas. Regarder image par image avec podman images.

Il existe fort heureusement des techniques pour réduire la taille des images docker :

Testez avec le fichier Dockerfile suivant :

FROM registry.u-bordeaux.fr/vhub/debian:12-slim
#FROM ubuntu:20.04

# Installing as root: docker images are usually set up as root.
# Since some autotools scripts might complain about this being unsafe, we set
# FORCE_UNSAFE_CONFIGURE=1 to avoid configure errors.
ENV FORCE_UNSAFE_CONFIGURE=1
ENV DEBIAN_FRONTEND noninteractive

RUN apt-get update -y
RUN apt-get install -y git curl make gcc g++ cmake doxygen musl-dev openmpi-bin openmpi-common libopenmpi-dev openssh-server openssh-client
RUN apt-get autoremove -y

Remarquez la nouvelle taille de l'image, environ 960 MB pour debian (890 MB pour ubuntu) au lieu de 340 MB dans le cas alpine.

5.2 Eviter l'exécution des jobs en mode root

Lorsqu'un programme ou service peut être lancé sans les privilèges root il est préférable de créer un utilisateur linux dans l'image et lancer les commandes de test avec cette identité.

Modifier la recette du dockerfile-buildenv en ajoutant :

# Create a group and user
RUN addgroup -S gitlab && adduser -S gitlab -G gitlab

# Create a directory where ci jobs are performed
RUN mkdir /builds && \
    chown -R gitlab:gitlab /builds && \
    chmod g+s /builds

# default user
USER gitlab

# default working directory
WORKDIR /builds

Il est maintenant possible d'enlever les variables d'environnement lors des ctest

#variables:
#  OMPI_ALLOW_RUN_AS_ROOT: "1"
#  OMPI_ALLOW_RUN_AS_ROOT_CONFIRM: "1"

Commit+push.

Author: Florent Pruvost (modifié par Pierre Ramet)

Created: 2024-10-21 Mon 14:58

Validate