Architecture DRY (Don't Repeat Yourself) sur GitLab
Le problème du pipeline monolithique
Au début d'un projet, un fichier .gitlab-ci.yml de 50 lignes fait très bien l'affaire. Mais lorsque l'entreprise grandit, que vous gérez le déploiement de 10 microservices, des tests de sécurité et des environnements multiples, votre fichier peut rapidement atteindre plusieurs milliers de lignes. Il devient alors un cauchemar à maintenir.
La philosophie DRY (Don't Repeat Yourself) s'applique aussi à l'infrastructure. GitLab propose plusieurs mécanismes pour découper, modulariser et réutiliser vos configurations CI/CD.
L'héritage de Jobs avec "extends"
Si plusieurs jobs utilisent la même image Docker, les mêmes variables ou les mêmes scripts de préparation, vous ne devez pas copier-coller ce code. Vous créez un template sous la forme d'un Job caché.
Astuce technique : Le point initial
Un job dont le nom commence par un point (ex: .mon_template) est ignoré par le moteur GitLab CI. Il ne sera jamais exécuté seul, il sert uniquement de modèle pour les autres.
Exemple d'industrialisation Docker :
# Définition du modèle commun
.docker_base:
image: docker:24.0
services:
- docker:24.0-dind
before_script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
tags:
- docker-builder
# Utilisation concrète du modèle
build_api:
extends: .docker_base
stage: build
script:
- docker build -t $CI_REGISTRY_IMAGE/api:$CI_COMMIT_SHA ./api
- docker push $CI_REGISTRY_IMAGE/api:$CI_COMMIT_SHA
build_frontend:
extends: .docker_base
stage: build
script:
- docker build -t $CI_REGISTRY_IMAGE/front:$CI_COMMIT_SHA ./frontend
- docker push $CI_REGISTRY_IMAGE/front:$CI_COMMIT_SHA
Pourquoi c'est mieux ? Si vous décidez de changer la version de Docker ou de modifier la méthode de connexion au registre, vous ne modifiez qu'une seule ligne dans le template et tous vos jobs de build sont mis à jour instantanément.
La modularité avec "include"
Le mot-clé include permet de fragmenter votre configuration. C'est l'outil indispensable pour centraliser les standards au sein d'une entreprise.
- local : Pour découper un fichier trop long en plusieurs petits fichiers thématiques dans le même projet.
- project : Pour importer des règles depuis un dépôt GitLab externe (ex: un dépôt "Security-Team" qui impose des scans sur tous les projets).
- template : Pour utiliser les modèles officiels fournis par GitLab (sécurité, qualité, etc.).
Regardons comment un expert DevOps découpe réellement son travail Gitlab CI. L'objectif est d'éviter le pipeline monolithique (un seul fichier géant de 2000 lignes) qui est impossible à maintenir.
Le spécialiste du build (ci/builders.yml)
Ce fichier est stocké dans un sous-dossier nommé ci/. Il ne contient que la logique de fabrication de l'application.
# Ce job est défini ici pour ne pas encombrer le fichier principal
job_construction_docker:
stage: build
image: docker:24.0
services:
- docker:24.0-dind
script:
- echo "Connexion au registre..."
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
- echo "Fabrication de l'image..."
- docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
Le Chef d'Orchestre (.gitlab-ci.yml)
C'est le fichier à la racine du projet. Il est très court car il se contente d'importer le travail des autres et de définir les étapes globales.
# 1. On importe la logique de build depuis notre fichier local
include:
- local: '/ci/builders.yml'
# 2. On définit l'ordre des étapes
stages:
- build
- test
- deploy
# 3. On définit les jobs restants (plus simples)
job_test_rapide:
stage: test
script:
- echo "Lancement des tests unitaires..."
- exit 0 # Succès fictif
Le secret des experts : L'écrasement (Override)
Si vous incluez un fichier contenant un job nommé job_test, vous pouvez redéfinir ce même job dans votre fichier principal pour changer juste une commande. GitLab prendra votre version locale en priorité. C'est l'outil parfait pour utiliser des templates standards tout en les personnalisant légèrement.
Le Catalogue CI/CD : Votre bibliothèque de composants
À quoi sert le Catalogue CI/CD ?
Dans les chapitres précédents, nous avons vu comment utiliser include pour importer des fichiers. Le Catalogue CI/CD est l'évolution moderne de ce concept. C'est une place de marché interne (ou publique) où vous pouvez trouver des briques de pipeline prêtes à l'emploi, appelées composants.
Au lieu de copier-coller des scripts complexes pour scanner votre code ou déployer sur Kubernetes, vous allez simplement "piocher" un composant certifié dans le catalogue. C'est un gain de temps massif car vous utilisez du code maintenu par d'autres experts, garantissant ainsi que vos pipelines respectent toujours les dernières normes de sécurité.
Comment accéder au catalogue ?
Pour consulter les composants disponibles pour vous et votre équipe, vous avez deux méthodes :
- Depuis la barre de recherche : Sélectionnez Search or go to, puis Explore, et enfin CI/CD Catalog.
- Depuis l'éditeur de pipeline : Si vous êtes déjà en train de modifier votre fichier .gitlab-ci.yml, un bouton CI/CD Catalog est directement disponible dans l'interface.
"Consultez le catalogue CI/CD"
Visibilité et Permissions
Tous les composants ne sont pas visibles par tout le monde. Leur accès dépend des réglages de visibilité du projet d'origine :
- Projets Privés : Les composants ne sont visibles que par les membres du projet (rôles Guest à Owner). Notez que pour utiliser concrètement le composant dans un pipeline, vous devez posséder au moins le rôle Reporter.
- Projets Internes : Visibles par tous les utilisateurs connectés à votre instance GitLab.
- Projets Publics : Visibles par n'importe qui ayant accès à l'instance, même sans être connecté.
Exemple d'utilisation d'un composant du catalogue :
include:
# Utilisation d'un composant de détection de secrets depuis le catalogue
- component: gitlab.com/components/secret-detection/secret-detection@1.0.0
inputs:
stage: test
Pourquoi privilégier le catalogue au "include: file" ?
Contrairement à un simple fichier inclus, les composants du catalogue sont encapsulés. Ils utilisent des inputs (entrées) qui agissent comme des arguments de fonction, ce qui évite que les variables du composant ne viennent écraser vos propres variables de projet par accident.
Bonnes Pratiques de l'Architecte DevOps
Pourquoi centraliser vos configurations ?
Dans une entreprise gérant des dizaines ou des centaines de projets, laisser chaque équipe écrire son propre fichier .gitlab-ci.yml est une erreur stratégique. Cela mène à une fragmentation technologique : chaque projet utilise une version différente de Docker, des scripts de déploiement disparates et des niveaux de sécurité inégaux.
L'approche de l'Architecte DevOps consiste à créer une "source unique de vérité". En centralisant la logique complexe dans un dépôt dédié, vous transformez la maintenance corrective en une tâche simple et instantanée pour toute l'organisation.
Mise en œuvre : Le projet "ci-templates"
La méthode consiste à créer un projet GitLab spécifique, par exemple nommé direction-technique/ci-templates, dont le seul but est d'héberger des fichiers YAML réutilisables.
Ce que l'on centralise dans ce dépôt :
- Les jobs de déploiement : Les commandes complexes pour Kubernetes, Terraform ou rsync vers vos serveurs.
- Les règles de Qualité (Linting) : Les configurations pour vérifier que le code respecte les normes de l'entreprise.
- La sécurité : L'inclusion des scanners SAST et de détection de secrets pré-configurés avec vos variables spécifiques.
Le fonctionnement technique : include:project
Pour utiliser ces standards, les développeurs n'ont plus qu'à importer le fichier distant dans leur propre projet.
# Dans le projet d'une équipe de développeurs
include:
- project: 'direction-technique/ci-templates'
ref: 'v2.4.0' # On pointe vers une version stable (un Git Tag)
file: '/templates/production-deploy.yml'
stages:
- build
- deploy
job_local_build:
stage: build
script:
- npm run build
# Le job de déploiement est "magiquement" importé et prêt à l'emploi
Les avantages d'un dépôt de standards
| Avantage | Description |
|---|---|
| Maintenance Unique | Si vous changez de serveur de production, vous modifiez le script dans ci-templates une seule fois. Tous les projets héritent de la mise à jour au prochain lancement. |
| Sécurité Globale | Vous garantissez que 100% des projets utilisent les mêmes scanners de vulnérabilités sans exception. |
| Montée en compétence | Les nouveaux développeurs n'ont pas besoin d'apprendre Kubernetes, ils utilisent simplement le template "clé en main" fourni par les experts DevOps. |
Conseil d'expert : Ne jamais pointer sur "main"
Lorsque vous utilisez include:project, utilisez toujours l'option ref pour cibler un tag (ex: v1.0.0). Si vous pointez sur la branche par défaut et que vous faites une modification cassante dans le dépôt de standards, vous risquez de bloquer simultanément tous les pipelines de l'entreprise.
Conclusion
La maîtrise de l'architecture DRY marque le passage d'une configuration artisanale à une véritable ingénierie de production. En utilisant l'héritage avec extends pour vos logiques internes et la modularité avec include pour vos standards externes, vous transformez un pipeline monolithique fragile en un système agile et scalable.
Grâce au Catalogue CI/CD et à la centralisation dans un dépôt de standards, vous garantissez désormais que chaque projet de votre organisation bénéficie des meilleures pratiques en matière de sécurité et de déploiement. Vous ne vous contentez plus de faire fonctionner du code, vous bâtissez une infrastructure robuste capable de soutenir la croissance de votre entreprise.
Cependant, une architecture propre n'est que la moitié du chemin. Pour que vos pipelines industrialisés puissent interagir avec le monde réel, ils doivent pouvoir communiquer de manière sécurisée avec vos serveurs. Dans le prochain chapitre, nous allons voir comment gérer les Environnements de déploiement et sécuriser vos accès distants grâce aux clés SSH.
Espace commentaire
Écrire un commentaire
Rejoignez la discussion
Vous devez être connecté pour poster un message.
22 commentaires
D'autres questions sur la modularité avant que je passe au prochain sujet sur les accès SSH ?
Catalogue direct. L'encapsulation via les
inputsrend le code beaucoup plus robuste qu'un simple include qui pollue ton namespace de variables.Pour les gros projets, vous préférez
include:fileou le catalogue ?Effectivement, les scripts sont remplacés. Pour fusionner, utilise des ancêtres YAML :
Le
extendsne fonctionne pas pour lesbefore_script, il les écrase au lieu de les fusionner, c'est relou.Oui, redéfinis simplement la variable dans ton fichier principal. Ta valeur locale prendra le dessus sur le template.
Est-ce que je peux surcharger une variable définie dans un template importé ?
Vérifie si ton fichier est bien dans le dépôt. Parfois, un mauvais
.gitignoreempêche le fichier d'être tracké par Git.J'ai une erreur 404 sur mon include. Le chemin est pourtant dans le dossier
ci/.Tu tagues tes releases dans le dépôt du composant. Ensuite, dans tes projets, tu appelles la version précise :
Ne jamais utiliser @main en prod.
Le catalogue CI/CD c'est bien, mais comment on versionne nos composants pour ne pas tout casser ?
T'as bien mis le point au début ?
Si t'oublies le point, GitLab le traite comme un job normal.
J'ai un souci avec mon job caché. Il n'est pas ignoré comme prévu.
Si ton projet est gros, arrête le
localet passe sur un dépôt de templates centralisé. Trop d'imports locaux, c'est la porte ouverte au chaos.J'ai tenté de modulariser avec
include:localmais mon fichier est devenu illisible avec trop d'imports.Utilise l'outil CI Lint dans l'interface GitLab. Ça valide la syntaxe YAML et l'expansion des
includeavant de push.Comment je peux débugger mon
.gitlab-ci.ymlsans lancer 50 pipelines qui échouent ?Oui, c'est le comportement attendu. GitLab fusionne les configurations. Si tu veux éviter ça, utilise les composants du catalogue qui isolent les
inputs.J'essaie d'utiliser
extendspour factoriser mes jobs mais mes variables locales écrasent tout, c'est normal ?C'était bien ça, le
refpointait sur une branche supprimée. Merci.Vérifie les permissions du projet distant. Si c'est un projet privé, ton runner doit avoir accès au dépôt. T'as bien configuré le
refsur un tag stable ?Super article. Par contre j'ai une erreur avec
include:project. Mon pipeline ne trouve pas le fichier distant alors que le chemin semble bon.