Terraform en équipe : découpage de l'état, rayon d'impact et plans relus
Comment découper l'état Terraform, exécuter les plans en CI et n'appliquer que ce qui a été relu, pour que les changements d'infrastructure deviennent routiniers plutôt que risqués.
Les exemples sont génériques et illustratifs. Ils ne proviennent d'aucun environnement client : adaptez seuils et réglages à votre propre système.
Le fichier d'état est la vraie frontière
Chaque terraform apply peut modifier n'importe quoi dans l'état sur lequel il travaille. C'est donc l'état, et non le module, qui est l'unité de risque. Avec un seul état pour tout un environnement, une coquille dans un enregistrement DNS et une modification de la base de production passent par le même plan — et ce plan met des minutes à être calculé.
Découper par cycle de vie et rayon d'impact
Regroupez les ressources qui changent ensemble et tombent en panne ensemble. Un découpage courant sépare, pour chaque environnement :
- Fondations : comptes, réseaux, zones DNS — modifiés rarement.
- Données : bases, buckets, files — modifiés avec précaution et protégés contre la suppression.
- Calcul et services : clusters, fonctions, load balancers — modifiés souvent.
Chaque couche lit les sorties de la couche inférieure et ne gère jamais ses ressources. Les environnements partagent les mêmes modules mais ont un état et des identifiants distincts, pour qu'un apply en staging ne puisse pas toucher la production.
État distant, verrouillage et versions
- Stockez l'état dans un backend distant avec verrouillage et versionnement activés — jamais dans Git, jamais sur un portable.
- Commitez le fichier de verrouillage des dépendances (.terraform.lock.hcl) et figez les versions des modules, pour qu'un plan aujourd'hui et un plan le mois prochain exécutent le même code.
- Protégez les ressources avec état par prevent_destroy et par la protection contre la suppression du fournisseur.
Un plan à chaque pull request, appliquer ce qui a été relu
Exécutez terraform plan en CI pour chaque changement et publiez le résultat sur la pull request. Après approbation, appliquez le plan enregistré au lieu de replanifier, pour que la production reçoive exactement ce que les relecteurs ont lu ; si l'état a changé entre-temps, Terraform refuse le plan périmé. Le pipeline doit s'authentifier avec des identifiants de courte durée via une fédération OIDC, pas avec des clés de longue durée stockées comme secrets.
terraform init -input=false
terraform plan -input=false -lock-timeout=5m -out=tfplan
terraform show -no-color tfplan > plan.txt # attach to the pull request
# after approval, applying the same saved plan:
terraform apply -input=false tfplan
Détecter la dérive à intervalles réguliers
Des changements dans la console arrivent encore, généralement pendant les incidents. Une tâche planifiée qui exécute terraform plan -detailed-exitcode les repère : le code de sortie 0 signifie aucun changement, 2 signifie que l'infrastructure réelle diffère du code et 1 signifie une erreur. Transformez un 2 en ticket, puis intégrez le changement au code ou annulez-le.
Les règles avant l'apply
Des règles comme « aucun bucket public » ou « chaque ressource porte un tag de propriétaire » sont mieux vérifiées par une machine que par un relecteur en fin de longue journée. Des outils de policy as code comme Open Policy Agent, via Conftest, peuvent évaluer la forme JSON du plan (terraform show -json) en CI et bloquer la fusion.