
Le state Terraform est le fichier qui relie votre code au monde réel. Sans
lui, Terraform ne sait plus quelles ressources il gère et tente de tout recréer.
Mais le state fait plus qu'une simple table de correspondance, et c'est là que
sont les pièges : il garde les secrets en clair, il ne détecte une dérive
que s'il a rafraîchi le monde réel juste avant, et il se protège contre
certaines réécritures par deux champs, serial et lineage.
Toutes les affirmations mesurables de ce guide (valeurs de serial, présence du
backup, codes de sortie, messages de terraform state push) ont été rejouées
sur Terraform v1.15.4, avec hashicorp/local et hashicorp/random, sur un
state local.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Les trois raisons d'être du state : mapping, dépendances, cache
- Le contenu du state,
serialetlineagecompris - Les secrets en clair : ce que
sensitivemasque, ce qu'il ne cache pas - La dérive : pourquoi elle ne se voit qu'avec un
refresh - Les commandes d'écriture du state et les garde-fous
À quoi sert le state : trois raisons, pas une
Section intitulée « À quoi sert le state : trois raisons, pas une »La doc officielle donne trois rôles au state, là où on n'en retient souvent qu'un :
- Le mapping : associer chaque adresse (
random_password.db) à l'objet réel. - Les métadonnées : mémoriser les dépendances entre ressources. C'est ce qui donne l'ordre de destruction quand une ressource a déjà disparu du code, « the order cannot be determined from the configuration alone ».
- La performance : le state sert de cache d'attributs. Sur une grosse
infrastructure,
-refresh=falseet-targetaccélèrent les opérations, au prix d'un state potentiellement périmé.
Ce que contient le state
Section intitulée « Ce que contient le state »Le state est un JSON nommé terraform.tfstate, au format version: 4. Il porte
à la racine version, terraform_version, serial, lineage, outputs,
resources et check_results. Chaque instance de ressource porte en plus
schema_version, sensitive_attributes, dependencies et private.
serialest un compteur d'écritures du state, pas d'apply. Terraform réécrit le state plusieurs fois par opération : sur une configuration à deux ressources, le premierapplylaisseserial: 3, l'applysuivant qui modifie une ressource laisseserial: 6.lineageest l'UUID de la lignée du state. Il a un usage bien réel (voir les garde-fous plus bas), ce n'est pas un identifiant décoratif.
Le backup terraform.tfstate.backup n'existe pas après le premier
apply : il n'est créé qu'à la première réécriture du state, et porte alors
le serial précédent (3 quand le courant vaut 6).
Le secret est en clair dans le state
Section intitulée « Le secret est en clair dans le state »C'est le malentendu le plus dangereux. Marquer une valeur sensitive ne la
retire pas du state : « Terraform stores values with the sensitive argument
in both state and plan files, and anyone who can access those files can access
your sensitive values ».
Pire, l'outil entretient une fausse confiance. Vérifié sur 1.15.4 :
terraform state show random_password.db # result = (sensitive value)terraform show -json | jq '...result' # le mot de passe EN CLAIRterraform state show masque la valeur, alors que le fichier de state et
terraform show -json la contiennent en clair. Le même attribut figure dans
sensitive_attributes de l'instance : la marque existe, la protection
non.
La dérive ne se voit qu'avec un refresh
Section intitulée « La dérive ne se voit qu'avec un refresh »C'est le trou le plus grave pour un profil Professional (sous-objectif 1e).
Terraform ne surveille pas votre infrastructure : il ne voit une dérive (un
changement fait hors Terraform) que lorsqu'il rafraîchit le state en relisant
le monde réel, ce qu'un plan fait par défaut. Vérifié sur 1.15.4, après
modification d'un fichier géré hors Terraform :
| Commande | Code de sortie | Ce que ça prouve |
|---|---|---|
terraform plan -detailed-exitcode | 2 | la dérive est vue (refresh) |
terraform plan -refresh=false -detailed-exitcode | 0 | le state seul ne voit rien |
La détection vient donc du rafraîchissement, pas du state. Une CI qui court
avec -refresh=false pour aller vite peut rater une dérive.
Pour rafraîchir sans planifier de changements, terraform apply -refresh-only
demande une confirmation avant de réécrire le state. La commande terraform refresh est dépréciée au profit de -refresh-only.
Lire et écrire le state : les commandes
Section intitulée « Lire et écrire le state : les commandes »On ne lit et n'écrit le state que par les commandes terraform state, jamais
en éditant le fichier :
| Commande | Rôle |
|---|---|
state list, state show | lister, inspecter (show masque les secrets) |
state pull, state push | exporter, importer le state complet |
state mv | renommer une ressource sans destruction |
state rm | retirer une ressource du state (sans la détruire) |
state mv est ce qui permet de renommer une ressource sans destruction :
vérifié, un mv donne un plan vide, là où un simple renommage dans le code
planifie 1 à créer et 1 à détruire (préférez cependant le bloc moved,
déclaratif).
Les garde-fous : serial et lineage
Section intitulée « Les garde-fous : serial et lineage »Contrairement à une idée reçue, le serial n'est pas le mécanisme de
concurrence : la protection contre deux opérations simultanées est un verrou
posé par le backend (Error acquiring the state lock), pas une comparaison de
serial. Le garde-fou du serial vit ailleurs, sur terraform state push :
- pousser un state de serial inférieur est refusé :
cannot import state with serial 3 over newer state with serial 6(sortie 1, state courant intact) ; - pousser un state de lineage différent est refusé, avec un message
distinct :
cannot import state with lineage "..." over unrelated state with lineage "...". C'est la protection contre l'écrasement par le state d'un autre projet.
Le verrouillage est automatique sur toute opération susceptible d'écrire le
state, y compris avec le backend local (« using system APIs »). -lock=false
est déconseillé ; terraform force-unlock existe pour un verrou resté bloqué, et
affiche un avertissement.
Reprendre un état perdu : le bloc import
Section intitulée « Reprendre un état perdu : le bloc import »Si le state est perdu, Terraform veut tout recréer. La réponse moderne n'est pas
le terraform import en ligne de commande, « manuel et fastidieux », mais le
bloc import déclaratif (Terraform 1.5+), appliqué par terraform apply :
import { to = aws_s3_bucket.data id = "mon-bucket-existant"}Combiné à terraform plan -generate-config-out=bucket.tf, il génère même la
configuration à partir de l'objet importé. C'est la réponse actuelle au state
perdu, et elle est revue à l'examen.
Le .gitignore : ce qui se commite, et ce qui non
Section intitulée « Le .gitignore : ce qui se commite, et ce qui non »Le state ne se commite jamais. La règle usuelle couvre les states, backups et states de workspaces d'une seule ligne :
*.tfstate*.tfstate.*.terraform/À l'inverse, .terraform.lock.hcl doit être versionné : c'est lui qui fige
les versions de providers pour toute l'équipe.
À retenir
Section intitulée « À retenir »- Le state a trois rôles : mapping, dépendances, cache d'attributs.
serialcompte les écritures, pas lesapply; le backup n'apparaît qu'à la première réécriture.- Un secret marqué
sensitivereste en clair dans le state ;state showle masque, mais le fichier etshow -jsonle révèlent. Seulephemerall'exclut. - La dérive ne se détecte qu'avec un refresh (
plan= 2,-refresh=false= 0). - Les garde-fous vivent sur
state push:serialinférieur etlineagedifférent sont refusés. La concurrence, elle, est gérée par le verrou.
FAQ : questions fréquentes
Section intitulée « FAQ : questions fréquentes »Les questions ci-dessous portent sur les pièges du state : le secret qu'on croit
protégé, la dérive qu'on croit détectée, et le rôle réel du serial. Chaque
réponse donne la vérification correspondante.
Réponse courte
Non.sensitive masque l'affichage ; la valeur reste en clair dans le state.Détail
La doc est nette : « Terraform stores values with thesensitive argument in both state and plan files ». Le fichier terraform.tfstate et terraform show -json contiennent le secret en clair. Seuls ephemeral et les arguments write-only l'excluent du state. Chiffrez le state au repos et protégez le backend.Réponse courte
state show est une vue humaine qui masque ; show -json et le fichier contiennent la valeur en clair.Détail
terraform state show random_password.db # result = (sensitive value)
terraform show -json | jq '...result' # la valeur en clair
Le même attribut figure dans sensitive_attributes de l'instance : la marque existe, mais elle ne cache rien du contenu du state.Réponse courte
Non. La concurrence est gérée par un verrou (Error acquiring the state lock), pas par le serial.Détail
Le garde-fou duserial vit sur terraform state push : pousser un état de serial inférieur est refusé (cannot import state with serial 3 over newer state with serial 6). Le verrouillage, lui, est automatique sur toute écriture, y compris avec le backend local.Réponse courte
Parce qu'unplan sans refresh se fie au state seul : la dérive ne se voit qu'avec un rafraîchissement.Détail
| Commande | Code |
|---|---|
plan -detailed-exitcode |
2 (dérive vue) |
plan -refresh=false -detailed-exitcode |
0 (rien vu) |
-refresh=false pour aller vite peut donc rater une dérive.Réponse courte
Non. « Do not directly edit this file » : une édition manuelle casse leserial ou les dépendances.Détail
Utilisez les commandesterraform state : list, show, pull, push, mv, rm. Par exemple state mv renomme une ressource sans destruction (plan vide), là où un renommage dans le code planifie 1 à créer et 1 à détruire.Réponse courte
Avec un blocimport (Terraform 1.5+), appliqué par terraform apply.Détail
import {
to = aws_s3_bucket.data
id = "mon-bucket-existant"
}
Combiné à terraform plan -generate-config-out=bucket.tf, il génère aussi la configuration. C'est la réponse moderne au state perdu, préférée au terraform import en ligne de commande, manuel et fastidieux.Réponse courte
terraform.tfstate : jamais. .terraform.lock.hcl : toujours.Détail
*.tfstate
*.tfstate.*
.terraform/
Le state contient l'état réel et des secrets en clair : il ne se commite pas. Le lock file .terraform.lock.hcl, au contraire, se versionne : il fige les versions de providers pour toute l'équipe.Pour aller plus loin
Section intitulée « Pour aller plus loin »- Verrouiller le state Terraform : Ce que le verrou rejette réellement, et le fichier résiduel qui ne bloque rien.
- terraform state mv : Le renommage d'une ressource dans le state, sans destruction ni recréation.
- Diagnostiquer le state Terraform : Serial, lineage et dérive, quand le state ne correspond plus à l'infrastructure.