Utiliser le registre d'image Docker de Gitlab est une bonne chose. Mais il arrive régulièrement que l'espace disque soit vite saturé. Voyons comme il est possible d'éviter cela.
Pour un projet d'un client, nous avons mis en place un processus d'intégration continue (en anglais CI pour Continuous Intégration) et de déploiement continue (en anglais CD pour Continuous Delivery).
Dans le cadre du déploiement continue, nous utilisons Docker pour nous permettre le déploiement d'un environnement de test par fonctionnalité à tester. Pour chacune de ces branches, il est nécessaire de construire une image Docker contenant tous les outils nécessaires au bon fonctionnement de l'application PHP avec le code de l'application.
Chaque image est générée par le processus d'intégration continue qui enregistre en suite l'image dans un registre. Dans notre cas, c'est GitLab qui gère le service de registre pour les images Docker.
Bien évidement, une fois l'image Docker construite, elle est déployée sur les serveurs de tests mais ce n'est pas le sujet de cette article.
Rapidement, nous avons été confronté a un problème d'espace disque manquant sur le registre géré par GitLab. Il faut penser à supprimer les images Docker dans le registre à la fin du développement de la fonctionnalité. C'est manuel, c'est pénible et surtout il faut y penser. C'est encore plus contraignant quand il faut rechercher les images Docker inutiles.
C'est pour cela que j'ai décide d'automatiser la suppression des images et le nettoyage complet des environnements lors de l’arrêt d'un environnement de test.
Dans la CI GitLab, il est possible d'exécuter des commandes à différents moments selon ce qu'il se passe sur le projet. Lors de l'ouverture d'une demande de fusion (pull request ou merge request selon les outils) il est possible de déployer automatiquement l'application sur les serveurs de test et de déclarer un environnement.
Il est également possible d'exécuter des actions après la fusion de code dans la branche principale. C'est à ce moment que l'on détruit les environnements de test déployés plus tôt et qu'il est opportun de nettoyer le registre GitLab des images inutiles.
Cela ce traduit par cette configuration dans le fichier .gitlab-ci.yml situé à la racine du projet :
stop_staging:
environment:
name: ${CI_BUILD_REF_SLUG}
action: stop
script:
- # Le script de nettoyage ici
Pour réaliser cette action, nous avons besoin d'un TOKEN d'identification d'un utilisateur (ayant les droits nécessaires sur le registre du projet) de GitLab pour appeler les API de GitLab. Nous avons également besoin de l'outil en ligne de commande jq pour extraire des données dans du JSON et de curl pour réaliser les appels HTTP.
Pour obtenir le token, aller sur votre page de profil GitLab (cliquer sur votre avatar, puis "Edit Profile") puis cliquer sur le menu "Access Token".
Maintenant cliquer sur le bouton "New Token". Un formulaire s'affiche pour configurer le token. Nommer le "CI GitLab Registry Clean", puis cocher "API" dans la liste des "Scopes"
L'URL qui nous intéressent est celle nous permettant de supprimer un tag dans le registre des images de GitLab. Il s'agit de l'URL
DELETE /projects/:id/registry/repositories/:repository_id/tags/:tag_name
Quels sont les paramètres nécessaires pour l'appel de cette URL:
Voyons maintenant comment récupérer l'identifiant du registre pour le projet via cette URL:
GET /projects/:id/registry/repositories
Le seul paramètre nécessaire est l'ID GitLab du projet que nous avons dans la variable d'environnement CI_PROJECT_ID .
Pour tous les appels à l'API, nous avons besoin de deux autres éléments:
Réalisons maintenant la première requête avec cURL :
curl --silent --header "PRIVATE-TOKEN: ${REGISTRY_GARBAGE_COLLECTOR_TOKEN}" ${CI_SERVER_URL}/api/v4/projects/${CI_PROJECT_ID}/registry/repositories
La réponse est un texte JSON dans lequel il faut chercher. C'est là que l'utilitaire jq est utile. Il permet de rechercher des données dans un JSON selon des critères.
[
{
"id": 1,
"name": "",
"path": "group/project",
"project_id": 9,
"location": "gitlab.example.com:5000/group/project",
"created_at": "2019-01-10T13:38:57.391Z",
"cleanup_policy_started_at": "2020-01-10T15:40:57.391Z"
},
{
"id": 2,
"name": "releases",
"path": "group/project/releases",
"project_id": 9,
"location": "gitlab.example.com:5000/group/project/releases",
"created_at": "2019-01-10T13:39:08.229Z",
"cleanup_policy_started_at": "2020-08-17T03:12:35.489Z"
}
]
Le registre qui nous intéresse est celui qui correspond au projet "group/project". Donc nous devons récupérer l'ID 1.
La commande jq suivante permet d'extraire l'ID :
jq ".[] | select(.path==\"group/project\") | .id"
Chaque opération est séparée par un pipe "|", voici la lecture de la commande :
Maintenant enchainons ces étapes et enregistrons la valeur de retour dans une variable d'environnement :
export REGISTRY_ID=`curl --silent --header "PRIVATE-TOKEN: ${REGISTRY_GARBAGE_COLLECTOR_TOKEN}" ${CI_SERVER_URL}/api/v4/projects/${CI_PROJECT_ID}/registry/repositories | jq ".[] | select(.path==\"$CI_PROJECT_PATH\") | .id"`
Nous disposons de toutes les informations pour supprimer le tag dans le registre exécutons la requête avec cURL :
curl --silent --request DELETE --header "PRIVATE-TOKEN: $REGISTRY_GARBAGE_COLLECTOR_TOKEN" ${CI_SERVER_URL}/api/v4/projects/${CI_PROJECT_ID}/registry/repositories/${REGISTRY_ID}/tags/${CI_COMMIT_REF_SLUG}
Actuellement, l’enchaînement des deux requêtes fonctionne de manière très optimiste. Ajoutons une gestion d'erreur.
Le premier cas est l'absence de la variable d’environnement REGISTRY_GARBAGE_COLLECTOR_TOKEN .
Si le le token est bien présent, il est possible que la récupération de l'ID du registre ne fonctionne pas. Pour cela nous allons tester la variable REGISTRY_ID .
Voici le code complet :
stop_env_test:
environment:
name: ${CI_BUILD_REF_SLUG}
action: stop
script:
- |
if ! [[ -z $REGISTRY_GARBAGE_COLLECTOR_TOKEN ]]; then
# Installer ici jq et curl
export REGISTRY_ID=`curl --silent --header "PRIVATE-TOKEN: ${REGISTRY_GARBAGE_COLLECTOR_TOKEN}" ${CI_SERVER_URL}/api/v4/projects/${CI_PROJECT_ID}/registry/repositories | jq ".[] | select(.path==\"$CI_PROJECT_PATH\") | .id"`
if ! [[ -z $REGISTRY_ID ]]; then
curl --silent --request DELETE --header "PRIVATE-TOKEN: $REGISTRY_GARBAGE_COLLECTOR_TOKEN" ${CI_SERVER_URL}/api/v4/projects/${CI_PROJECT_ID}/registry/repositories/${REGISTRY_ID}/tags/${CI_COMMIT_REF_SLUG}
fi
fi
Même si GitLab ne prévoit pas nativement le nettoyage du registre, il est possible de réaliser cette action automatiquement dans la CI.
Il reste un dernier point, la suppression du tag dans le registre des images docker de GitLab ne permet pas la récupération réelle de l'espace disque. Vous devez exécuter périodiquement la commande gitlab-ctl registry-garbage-collect pour récupérer l'espace disque.
Besoin d'aide ? Une question ? Les commentaires sont les bienvenus !
To celebrate the release of Dataflow 5 for Symfony 7, here is some feedback on ...
🎯 Nous relevons le défi de lancer un grand concours : Vous faire gagner un ...
How to dynamically calculate shipping costs? The official documentation that explains how to create shipping ...
How to create a new product attribute type in Ibexa Commerce
A la recherche d'un poste de travail temporaire ou permanent ? Vous recherchez un environnement ...
Après une découverte de surface d'Ibexa Commerce, entrons plus dans le détail pour comprendre son ...
Ibexa DXP propose un module pour gérer des produits pour la réalisation d'un site e-commerce. ...
Voici une présentation d'IbexaMailing, un module qui ajoute la gestion des newsletters à Ibexa. IbexaMailing est ...
C'est la dernière occasion de vous souhaitez le meilleur pour cette année 2024 et surtout ...
To celebrate the release of Dataflow 5 for Symfony 7, here is some feedback on ...
🎯 Nous relevons le défi de lancer un grand concours : Vous faire gagner un ...
How to dynamically calculate shipping costs? The official documentation that explains how to create shipping ...
How to create a new product attribute type in Ibexa Commerce
A la recherche d'un poste de travail temporaire ou permanent ? Vous recherchez un environnement ...
Après une découverte de surface d'Ibexa Commerce, entrons plus dans le détail pour comprendre son ...
Ibexa DXP propose un module pour gérer des produits pour la réalisation d'un site e-commerce. ...
Voici une présentation d'IbexaMailing, un module qui ajoute la gestion des newsletters à Ibexa. IbexaMailing est ...
C'est la dernière occasion de vous souhaitez le meilleur pour cette année 2024 et surtout ...