Suite de ma série sur la certification Terraform Associate, après les modules. Sixième objectif de l’exam guide, “Implement and maintain state” : cet article couvre le backend local, le locking, le remote state, l’authentification et la gestion des secrets dans le state.
Qu’est-ce que le state
Le state est un fichier (terraform.tfstate, au format JSON) dans lequel Terraform stocke le mapping entre les ressources déclarées dans la configuration et les objets réels de l’infrastructure. C’est ce fichier qui permet à Terraform de savoir quoi créer, modifier ou détruire à chaque plan/apply, sans avoir à interroger l’ensemble du provider à chaque fois.
Backend local
Par défaut, Terraform utilise le backend local : le state est stocké dans un fichier terraform.tfstate à la racine du répertoire de travail.
- Simple à utiliser, aucune configuration requise.
- Ne convient pas au travail en équipe : pas de lock partagé, pas de state partagé entre collaborateurs, secret stocké en clair sur le poste local.
State locking
Avant toute opération qui écrit dans le state (apply, parfois plan), Terraform tente de le verrouiller pour empêcher deux opérations concurrentes de le corrompre.
- Le locking est supporté par la plupart des backends distants (S3, Azure Blob Storage, HCP Terraform…)
- Si le lock ne peut pas être acquis, Terraform bloque l’opération et indique qui détient le lock.
- L’option
-lock=falsepermet de désactiver ce comportement, à éviter en usage normal.
Backend distant
Un backend distant stocke le state en dehors du poste local (bucket S3, Azure Blob Storage, GCS, HCP Terraform…). Il se déclare dans un bloc backend, imbriqué dans le bloc terraform.
terraform {
backend "s3" {
bucket = "mon-bucket-tfstate"
key = "prod/network/terraform.tfstate"
region = "eu-west-1"
dynamodb_table = "terraform-locks"
encrypt = true
}
}
Avantages par rapport au backend local :
- State partagé entre plusieurs collaborateurs ou pipelines CI/CD.
- Locking natif.
- Chiffrement.
- Historique/versionning du state selon le backend.
Changer de backend nécessite de relancer terraform init, qui propose alors de migrer le state existant vers le nouveau backend.
HCP Terraform
HCP Terraform (anciennement Terraform Cloud) peut aussi servir de backend, via un bloc cloud plutôt que backend :
terraform {
cloud {
organization = "mon-org"
workspaces {
name = "prod-network"
}
}
}
En plus du stockage du state, HCP Terraform ajoute le locking, un historique des runs, et l’exécution du plan/apply à distance.
Authentification aux backends
Chaque backend a son propre mécanisme d’authentification, indépendant de celui des providers :
- S3 : credentials AWS (variables d’environnement, profil CLI, rôle IAM).
- Azure Blob Storage : Azure CLI, service principal, managed identity.
- HCP Terraform : token d’API, généralement stocké dans
~/.terraform.d/credentials.tfrc.jsonviaterraform login.
Ces credentials ne doivent jamais être codés en dur dans la configuration.
Effet de terraform refresh
terraform refresh (ou l’étape de refresh implicite lors d’un plan/apply) interroge les providers pour comparer l’état réel de l’infrastructure au state enregistré, et met à jour le state en conséquence.
- Ne modifie jamais l’infrastructure réelle, uniquement le fichier de state.
- Permet de détecter un drift (modification manuelle en dehors de Terraform).
- Peut être désactivé avec
-refresh=falsepour accélérer un plan quand on est sûr qu’il n’y a pas eu de changement externe.
Secrets dans le state
Le state contient les valeurs de toutes les ressources qu’il suit, y compris les attributs sensibles (mots de passe générés, clés, tokens), même si la variable ou l’output correspondant est marqué sensitive. Comme évoqué dans l’article sur la configuration, sensitive masque seulement l’affichage dans les logs et l’UI, il ne retire rien du state.
Bonnes pratiques :
- Toujours utiliser un backend distant chiffré at rest plutôt que le backend local.
- Restreindre l’accès au state via des contrôles d’accès (IAM, permissions du backend).
- Activer les logs d’audit du backend pour tracer les accès au state.
- Préférer
ephemeral/write-only quand c’est possible, pour éviter que la valeur n’atterrisse dans le state.
Commandes terraform state
Terraform fournit un sous-ensemble de commandes dédiées à l’inspection et la manipulation du state, sans passer par un apply :
terraform state list # liste les ressources trackées
terraform state show aws_instance.web # détail d'une ressource dans le state
terraform state mv aws_instance.web aws_instance.app # renomme/déplace une ressource dans le state
terraform state rm aws_instance.web # retire une ressource du state (sans la détruire)
terraform state pull # affiche le state distant au format JSON
terraform state push # écrase le state distant (usage avancé, à risque)
terraform state list est généralement la première commande à lancer pour retrouver l’adresse exacte d’une ressource avant d’utiliser show, mv ou rm.
Importer une ressource existante
terraform import rattache une ressource déjà existante (créée manuellement ou par un autre outil) à un bloc resource du state, sans la recréer.
terraform import aws_instance.web i-0abcd1234
- Le bloc
resource "aws_instance" "web" { ... }doit déjà exister dans la configuration : la commande ne fait qu’ajouter l’entrée au state, elle ne génère aucun HCL. - Il faut ensuite compléter le bloc à la main pour que la configuration corresponde à la ressource réelle, sinon le prochain
planproposera des changements pour aligner l’un sur l’autre. - Fonctionne ressource par ressource : pas d’import groupé avec la commande CLI.
Logs
Terraform expose des logs de debug via la variable d’environnement TF_LOG, utile pour diagnostiquer un comportement inattendu (au niveau du core ou d’un provider).
export TF_LOG=DEBUG
terraform plan
- Niveaux disponibles, du plus verbeux au moins verbeux :
TRACE,DEBUG,INFO,WARN,ERROR. TF_LOG_COREetTF_LOG_PROVIDERpermettent de cibler respectivement le cœur de Terraform ou les providers, indépendamment l’un de l’autre.TF_LOG_PATHredirige les logs vers un fichier plutôt que stdout/stderr :
export TF_LOG=TRACE
export TF_LOG_PATH=./terraform.log
- Penser à
unset TF_LOG(etTF_LOG_PATH) une fois le diagnostic terminé, sinon chaque commande reste verbeuse. - Ces logs tracent l’exécution du CLI (appels aux providers, résolution de la configuration…), sans lien avec le contenu du state.
Ce que je retiens
- Le backend local ne convient pas au travail en équipe : pas de locking partagé, secrets en clair sur le poste.
sensitive≠ absent du state : seulephemeralgarantit qu’une valeur n’y est jamais écrite.terraform refreshne touche jamais l’infrastructure réelle, seulement le fichier de state, pour détecter un drift.terraform importrattache une ressource existante au state sans la recréer, mais ne génère pas la configuration correspondante : à compléter à la main.TF_LOGcible le core ou les providers séparément (TF_LOG_CORE/TF_LOG_PROVIDER), et n’a aucun effet sur le contenu du state.
Prochaine (et dernière) étape de la série : HCP Terraform.
