Quand exécuter Terraform depuis son poste ne suffit plus

Vous gérez votre infrastructure avec Terraform depuis votre terminal. Cela fonctionne tant que vous êtes le seul à faire des modifications. Vous lancez terraform plan, vérifiez la sortie, exécutez terraform apply, et passez à autre chose. Le fichier d'état se trouve sur votre machine, et vous savez exactement ce que vous avez changé et quand.

Puis un collègue rejoint le projet. Il clone le dépôt, lance terraform init, et obtient un plan différent de celui que vous avez vu hier. Le fichier d'état sur son poste est obsolète. Quelqu'un applique une modification sans prévenir personne. Une semaine plus tard, plus personne ne se souvient qui a modifié les règles du groupe de sécurité, ni pourquoi.

C'est le moment où le workflow basé sur le poste local atteint ses limites. Les problèmes ne viennent pas de Terraform lui-même. Ils concernent la coordination, la visibilité et la responsabilité. Quand l'infrastructure est partagée, exécuter des commandes depuis des machines individuelles crée de la confusion, des risques et une dérive silencieuse.

Déplacer le workflow dans un pipeline

Au lieu d'exécuter terraform plan et terraform apply depuis le poste de chacun, vous pouvez déplacer ce workflow dans un pipeline CI/CD. Chaque modification d'infrastructure emprunte alors le même chemin, est enregistrée et peut être revue par l'équipe avant d'être appliquée.

L'approche par pipeline transforme les changements d'infrastructure en quelque chose de similaire aux changements de code applicatif. Vous écrivez la configuration, ouvrez une pull request, recevez des retours, et ce n'est qu'après approbation que le changement est appliqué. La différence est que Terraform ajoute une étape de planification qui montre exactement ce qui va se passer sur vos ressources cloud avant que quoi que ce soit ne s'exécute.

L'exemple suivant montre une configuration générique de pipeline CI qui implémente le workflow write-plan-apply :

stages:
  - validate
  - plan
  - apply

validate:
  stage: validate
  script:
    - terraform fmt -check
    - terraform validate
  only:
    - merge_requests

plan:
  stage: plan
  script:
    - terraform plan -out=plan.tfplan
  artifacts:
    paths:
      - plan.tfplan
  only:
    - merge_requests

apply:
  stage: apply
  script:
    - terraform apply plan.tfplan
  when: manual
  only:
    - main

Les trois étapes : Write, Plan, Apply

La façon la plus courante d'intégrer Terraform dans un pipeline est de diviser le workflow en trois étapes qui correspondent au flux naturel d'une modification.

Le diagramme de séquence suivant illustre comment les trois étapes interagissent :

sequenceDiagram participant Dev as Développeur participant PR as Pull Request participant Pipe as Pipeline CI participant Rev as Relecteur participant Infra as Infrastructure Dev->>PR: Ouvre une PR avec des changements de config PR->>Pipe: Déclenche le pipeline Pipe->>Pipe: Étape Write (fmt, validate) Pipe->>PR: Publie le résultat du plan en commentaire PR->>Rev: Demande une relecture Rev->>PR: Approuve ou rejette alt Approuvé PR->>Pipe: Le merge sur main déclenche apply Pipe->>Infra: terraform apply (plan sauvegardé) Infra-->>Pipe: Ressources mises à jour Pipe-->>Dev: Notification de succès else Rejeté PR-->>Dev: Modifications demandées end

Write : détecter les problèmes avant la relecture

L'étape Write commence lorsque quelqu'un modifie des fichiers de configuration Terraform et ouvre une pull request. À ce stade, le pipeline peut exécuter automatiquement des vérifications de base. terraform fmt vérifie que le code suit le formatage standard. terraform validate vérifie que la configuration est syntaxiquement correcte et que tous les arguments requis sont présents.

Ces vérifications sont l'équivalent infrastructure de l'exécution d'un linter sur du code applicatif. Elles détectent les erreurs simples tôt, avant qu'un relecteur humain ne passe du temps à examiner la pull request. Si le formatage est incorrect ou qu'un champ obligatoire manque, le pipeline échoue immédiatement, et l'auteur corrige avant que quiconque d'autre ne soit impliqué.

Plan : montrer ce qui va changer

Une fois la pull request ouverte, le pipeline exécute terraform plan automatiquement. La sortie du plan est ensuite publiée sous forme de commentaire sur la pull request. C'est là que la relecture devient pertinente.

La sortie du plan montre exactement ce que Terraform va faire : quelles ressources seront créées, lesquelles seront modifiées, et lesquelles seront détruites. Un relecteur peut voir qu'une pull request change le type d'instance de serveur de small à medium, ou ajoute une nouvelle règle de pare-feu, ou supprime un ancien groupe de sous-réseaux de base de données. Si quelque chose semble anormal, le relecteur rejette la pull request avant qu'aucun changement n'atteigne la production.

Cette étape est cruciale car elle fait passer la revue d'infrastructure de « faites-moi confiance, j'ai exécuté le plan » à « voici le plan, vérifiez par vous-même ». Le plan fait partie de la conversation de la pull request, et la décision d'approuver ou de rejeter est basée sur un résultat concret, pas sur la confiance.

Apply : exécuter uniquement après approbation

L'étape Apply ne s'exécute qu'après l'approbation et le merge de la pull request dans la branche principale. Le pipeline sur la branche principale exécute alors terraform apply en utilisant le plan qui a déjà été relu.

La façon la plus sûre de procéder est de sauvegarder la sortie du plan de l'étape précédente dans un fichier et de passer ce fichier à terraform apply. Cette technique s'appelle un plan sauvegardé. Elle garantit que l'apply exécute exactement les mêmes modifications qui ont été relues, et non un nouveau plan qui pourrait être différent parce que quelqu'un a poussé un autre commit entre la relecture et l'apply.

Sans plan sauvegardé, le pipeline exécuterait terraform plan à nouveau pendant l'étape Apply. Si la configuration a changé entre-temps, le nouveau plan pourrait être différent de ce qui a été relu. Cela irait à l'encontre du but même de la relecture.

Gérer l'état dans un pipeline

La gestion de l'état devient simple lorsque Terraform s'exécute dans un pipeline. Le fichier d'état doit être stocké dans un emplacement partagé, comme un bucket de stockage cloud ou un backend Terraform configuré une fois par l'équipe. Chaque fois que le pipeline exécute plan ou apply, il récupère l'état depuis cet emplacement partagé, et non depuis une copie locale qui pourrait être obsolète.

Le pipeline doit également activer le verrouillage d'état. Terraform peut verrouiller le fichier d'état pendant l'exécution d'un plan ou d'un apply, empêchant ainsi deux processus de modifier l'état simultanément. Sans verrouillage, deux pipelines pourraient exécuter apply en même temps, provoquant une corruption ou des résultats inattendus.

Ce que ce workflow vous apporte

Une fois que le workflow write-plan-apply s'exécute dans un pipeline, les modifications d'infrastructure suivent la même discipline que les modifications de code applicatif. Chaque changement passe par une pull request, est relu par les membres de l'équipe, est testé avec un plan automatisé, et ne s'exécute qu'après approbation. L'historique complet des modifications est enregistré dans Git et dans les logs du pipeline.

Vous ne vous demandez plus qui a changé un serveur ni quand cela s'est produit. Vous ne vous inquiétez plus des fichiers d'état obsolètes sur le poste de quelqu'un. Vous n'entendez plus « ça marche sur ma machine » à propos de l'infrastructure.

Liste de vérification pratique pour la mise en place

  • Configurez un backend distant pour le stockage d'état avant de mettre en place le pipeline. Le backend doit être accessible par l'exécuteur du pipeline.
  • Mettez en place le verrouillage d'état. La plupart des backends comme S3 avec DynamoDB ou GCS avec le versionnement d'objets le supportent nativement.
  • Ajoutez terraform fmt et terraform validate comme vérifications précoces dans le pipeline de pull request.
  • Exécutez terraform plan sur chaque pull request et publiez la sortie sous forme de commentaire.
  • Utilisez des plans sauvegardés. Stockez le fichier de plan comme artefact de pipeline et transmettez-le à l'étape Apply.
  • Limitez terraform apply pour qu'il ne s'exécute que sur la branche principale après le merge.
  • Assurez-vous que l'exécuteur du pipeline dispose des permissions minimales requises pour exécuter le plan et l'apply. N'utilisez pas d'identifiants administrateur.

Et ensuite

Une fois que le pipeline gère automatiquement le workflow write-plan-apply, la question suivante est de savoir comment gérer différents environnements. Les environnements de staging et de production utilisent rarement les mêmes valeurs de configuration. Le pipeline doit gérer des variables spécifiques à l'environnement, des fichiers d'état et des étapes d'approbation sans dupliquer l'intégralité du workflow pour chaque environnement.

Mais c'est un problème pour plus tard. Pour l'instant, l'étape importante est d'arrêter d'exécuter Terraform depuis des postes locaux et de commencer à traiter les changements d'infrastructure comme des changements de code. Le pipeline vous donne une source de vérité unique pour savoir ce qui a changé, qui l'a approuvé et quand cela a été appliqué. Cela suffit à éliminer la majeure partie de la confusion qui accompagne l'infrastructure partagée.