Aller au contenu
English
Compte : non connecté, synchronisation possible Mon apprentissage
Selectionner le thème
English

Pipeline IaC et GitOps : du plan relu à l'apply

Par mis à jour le

Améliorer cette page

Un pipeline IaC sûr n'applique jamais « le code de la branche » : il applique le plan précis que quelqu'un a relu et approuvé. La séquence est courte : produire le plan, l'archiver, le faire relire, puis appliquer ce plan et rien d'autre, avec un état verrouillé pendant l'opération et des droits plus faibles pour le plan que pour l'apply. Cette leçon explique cette séquence, ses garde-fous, puis compare deux modèles : le push, où la CI applique, et le pull (GitOps), où un contrôleur réconcilie en continu. Le scénario est celui de l'équipe de quatre personnes : une application web (deux VM, une base, un réseau, un DNS) en dev et prod. Le pipeline ci-dessous vise la prod telle qu'elle sera une fois reprise en code (Reprendre une infrastructure existante) ; tant qu'elle reste manuelle, seul dev passe par lui.

  • enchaîner plan, archive, approbation, apply dans un pipeline ;
  • expliquer pourquoi on applique le plan approuvé et non le code ;
  • décrire le verrou d'état et la séparation des droits ;
  • comparer push et pull (GitOps) et choisir ;
  • lire un workflow d'illustration.

Les extraits de code sont des illustrations à lire, pas des étapes à exécuter.

La séquence tient en quatre temps : plan, archive, approbation, apply. Le pipeline calcule d'abord un plan (l'aperçu de ce que l'outil créera, modifiera ou détruira). Il l'enregistre ensuite comme artefact (un fichier conservé par la CI après l'exécution). Une personne le relit et l'approuve. Enfin, un second job applique ce fichier précis.

Le schéma suit cette séquence de haut en bas. Le chemin principal relie la pull request au job apply en passant par le fichier de plan archivé : c'est lui, et non le code de la branche, qui arrive à l'apply. Les deux sorties de droite sont les garde-fous : pas d'apply sans approbation, et un refus de l'outil si le plan est périmé.

Séquence d'un pipeline IaC sûr : après fusion de la pull request (validation, plan lu en commentaire), le job plan, avec des droits de lecture plus l'écriture du verrou de l'état, produit un fichier de plan archivé pour une durée courte avec un accès restreint ; une personne autre que l'auteur l'approuve, sinon aucun apply n'a lieu et le changement retourne à l'auteur ; le job apply applique ce fichier avec une identité en écriture, et l'outil refuse si l'état a changé depuis le plan, qu'il faut alors recalculer.Pull requestvalidation, plan lu en commentaireJob planlecture + verrou de l'étatfusionFichier de plan archivédurée courte, accès restreintApprouvé par une autrepersonne que l'auteur ?Pas d'apply :retour à l'auteurnonJob apply : ce fichier,identité en écritureouiPlan périmé :l'outil refuse, on recalculeétat changédepuis le plan
Source · SVG
Échap pour fermer, + et − pour zoomer, défilement pour se déplacer. 100 %

L'intérêt du fichier de plan est qu'il fige la décision. Entre le moment où le plan est relu et celui où l'apply s'exécute, d'autres changements peuvent avoir eu lieu : un collègue a modifié le code, une ressource a changé côté fournisseur. Un apply qui recalcule son propre plan appliquerait peut-être autre chose que ce qui a été lu. Avec un plan enregistré, l'outil applique exactement ce plan, ou refuse s'il est périmé (côté Terraform, un plan enregistré dont l'état a changé est rejeté comme obsolète). Le pipeline échoue plutôt que de surprendre.

Le fichier de plan peut contenir des valeurs sensibles, comme l'état. On le conserve peu de temps, avec un accès restreint, et on ne le publie jamais en clair dans une pull request. La relecture porte sur une version lisible du plan, pas sur ce fichier brut. Le geste exact côté Terraform est décrit dans Exécuter Terraform en automation et Le workflow Terraform.

Pourquoi verrouiller l'état et séparer les droits ?

Section intitulée « Pourquoi verrouiller l'état et séparer les droits ? »

Deux applys simultanés sur le même état se marcheraient dessus. Le verrou d'état (state lock) empêche cela : avant d'écrire, l'outil pose un verrou dans l'emplacement de stockage de l'état, et une seconde exécution attend ou échoue. Tous les stockages de l'état ne prennent pas le verrou en charge : la documentation de chaque backend (le stockage choisi pour l'état) le précise. Le pipeline ajoute une file d'attente par stack et par environnement, pour qu'une seule exécution d'apply tourne à la fois. La leçon Verrouiller le state Terraform détaille ce que le verrou bloque vraiment.

La séparation des droits tient en deux phrases. Calculer un plan demande un accès en lecture sur l'infrastructure, plus le droit d'écrire le verrou de l'état, car un plan Terraform le pose par défaut ; appliquer demande l'accès en écriture, réservé à un job protégé par une approbation. Et l'auteur d'un changement n'est jamais celui qui l'approuve pour la production.

Le détail de ces identités (moindre privilège, jetons à durée courte obtenus par OIDC, accès d'urgence) est l'objet de la leçon Identité et droits du moteur IaC. Côté pipeline, retenez surtout que la branche principale est protégée (pas de poussée directe, relecture obligatoire) : sans cela, la séparation des droits ne protège rien.

À quoi ressemble ce pipeline dans un workflow GitHub Actions ?

Section intitulée « À quoi ressemble ce pipeline dans un workflow GitHub Actions ? »

Le workflow ci-dessous illustre la séquence pour la prod. Il suppose un dépôt avec une configuration dans infra/envs/prod, un environnement de déploiement nommé production dont la protection exige une approbation, et un fichier de verrouillage de dépendances (.terraform.lock.hcl) versionné. L'étape d'authentification dépend du fournisseur ; elle est laissée en commentaire. Les jetons id-token: write servent à l'OIDC : le pipeline prouve son identité au fournisseur cloud, qui lui rend des droits temporaires plutôt qu'une clé stockée.

name: infra-prod
on:
push:
branches: [main]
paths: ["infra/envs/prod/**"]
permissions: {}
concurrency:
group: infra-prod
cancel-in-progress: false
defaults:
run:
working-directory: infra/envs/prod
jobs:
plan:
runs-on: ubuntu-24.04
permissions:
contents: read
id-token: write # jeton OIDC pour l'identité de plan (lecture + verrou de l'état)
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: hashicorp/setup-terraform@dfe3c3f87815947d99a8997f908cb6525fc44e9e # v4.0.1
with:
terraform_version: 1.16.5
# Authentification OIDC au fournisseur : propre à chaque cloud, hors périmètre ici.
- run: terraform init -input=false
- run: terraform plan -input=false -out=tfplan
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: plan-prod
path: infra/envs/prod/tfplan
retention-days: 1
apply:
needs: plan
runs-on: ubuntu-24.04
environment: production # protégé : approbation requise avant ce job
permissions:
contents: read
id-token: write # jeton OIDC pour une identité capable d'écrire
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: hashicorp/setup-terraform@dfe3c3f87815947d99a8997f908cb6525fc44e9e # v4.0.1
with:
terraform_version: 1.16.5
- uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
name: plan-prod
path: infra/envs/prod
# Authentification OIDC avec l'identité d'écriture.
- run: terraform init -input=false
- run: terraform apply -input=false tfplan

Lisez-le en cherchant les garde-fous. permissions: {} au niveau du workflow retire tout droit par défaut, puis chaque job demande le minimum. persist-credentials: false empêche le jeton Git de rester disponible pour les étapes suivantes. Chaque action est épinglée sur le commit exact, avec la version en commentaire. concurrency empêche deux exécutions simultanées. Le job apply est séparé du job plan et ne démarre qu'après l'approbation de l'environnement production.

Ce workflow est une base à adapter, pas un produit fini : il ne commente pas le plan dans la pull request, ne présente pas le plan sous forme lisible et n'exécute pas encore les contrôles de la leçon Policy as code. Ces ajouts viennent s'insérer avant l'approbation. Selon la documentation de GitHub, les reviewers requis et le délai d'attente d'un environnement ne sont disponibles, avec les offres Free, Pro et Team, que pour les dépôts publics ; pour un dépôt privé, il faut l'offre Enterprise. Vérifiez votre offre avant de compter sur cette approbation, sinon le job apply partirait sans relecture.

Push ou pull : la CI applique-t-elle, ou un contrôleur réconcilie-t-il ?

Section intitulée « Push ou pull : la CI applique-t-elle, ou un contrôleur réconcilie-t-il ? »

Le modèle push est celui du workflow ci-dessus : la CI se connecte à l'infrastructure et exécute l'apply. Dans le modèle pull, un contrôleur installé près de la cible lit le dépôt Git et corrige lui-même les écarts : c'est le GitOps, dont les principes sont posés dans GitOps : principes, ArgoCD vs Flux et mise en œuvre. La comparaison des deux modes, leurs effets sur la dérive, la latence et la surface d'attaque, est faite dans la leçon Push, pull ou agent ; elle n'est pas répétée ici.

Dans le scénario, les VM, la base, le réseau et le DNS sont de l'infrastructure cloud : l'équipe reste en push avec le pipeline ci-dessus. Si elle déploie ensuite l'application dans un cluster Kubernetes, un contrôleur (Argo CD ou Flux) peut prendre en charge ce périmètre, tandis que l'IaC de l'infrastructure sous-jacente reste en push. Les deux modèles coexistent, chacun sur le périmètre où il est naturel.

Le pull suppose que l'état voulu s'exprime en objets que le contrôleur sait réconcilier, ce qui est naturel pour Kubernetes et l'est beaucoup moins pour un réseau ou un DNS chez un fournisseur cloud.

Quelles erreurs fréquentes dans un pipeline IaC ?

Section intitulée « Quelles erreurs fréquentes dans un pipeline IaC ? »
  • Un apply qui recalcule son plan. Ce qui est appliqué peut différer de ce qui a été relu.
  • Un seul rôle pour tout. Une identité capable d'écrire dans chaque job transforme chaque pull request en risque pour la production.
  • Pas de file d'attente par environnement. Deux exécutions simultanées se disputent le verrou, ou pire, appliquent des plans croisés.
  • Un plan publié tel quel. Il peut contenir des valeurs sensibles ; on poste une version lisible et filtrée.
  • Une approbation de façade. L'approbateur valide sans lire le plan, ou c'est l'auteur qui s'approuve lui-même.
  • Une action ou une image non épinglée. Un pipeline qui exécute du code tiers mutable annule les garde-fous du reste.
  • Un pipeline sûr applique le plan approuvé : plan, archive, approbation, apply de ce fichier.
  • Le verrou d'état et une file d'attente par environnement empêchent deux applys simultanés ; un plan Terraform pose lui aussi le verrou par défaut.
  • Le plan demande des droits en lecture (plus l'écriture du verrou), l'apply des droits en écriture : deux identités, l'auteur n'est pas l'approbateur ; le détail est dans la leçon sur l'identité du moteur IaC.
  • En push, la CI applique ; en pull (GitOps), un contrôleur réconcilie en continu, ce qui convient surtout à Kubernetes (comparaison complète dans la leçon sur push, pull et agent).
  • Les actions de la CI s'épinglent sur un commit, avec permissions: {} par défaut et persist-credentials: false.

Vérifiez que l'essentiel de ce guide est acquis. Les questions portent uniquement sur ce qui vient d'être expliqué ici.

Contrôle de connaissances

Validez vos connaissances avec ce quiz interactif

6 questions
6 min.
70% requis

Informations

  • Le chronomètre démarre au clic sur Démarrer
  • Questions à choix multiples, vrai/faux et réponses courtes
  • Vous pouvez naviguer entre les questions
  • Les résultats détaillés sont affichés à la fin

Lance le quiz et démarre le chronomètre

Ce projet vous est utile ?

Les guides, formations, quiz et labs restent gratuits. Si vous les utilisez régulièrement, vous pouvez contribuer à leur maintenance et à leur développement.

Devenir membre de soutien (nouvel onglet) Soutenir une fois (nouvel onglet) En savoir plus

Suivez aussi le projet sur LinkedIn