Workflow Terraform : init, plan, apply et destroy
À la fin de ce tutoriel, vous aurez parcouru le cycle complet Terraform (
init→fmt/validate→plan→apply→destroy) sur un lab Free Tier friendly : un bucket S3 privé tagué en Regionca-central-1, avec lecture du plan (+/−/~), state local et preuve d’idempotence.Niveau : Débutant · Temps estimé : 35–45 min · Versions testées : Terraform 1.16.2 (série ≥ 1.9), AWS provider ~> 5.0 · Dernière vérification : 2026-09-10
Slug proposé :
terraform-workflow· Série : Terraform · Remplace / fusionne : #1615
Prérequis
- Avoir suivi Découvrir Terraform (
terraform-overview) — IaC, state, aperçu du workflow - Avoir suivi Installer Terraform (
installer-terraform) : binaire ≥ 1.9,terraform versionOK, profil AWS prêt - AWS CLI v2 configurée :
aws sts get-caller-identityréussit avec votre profil de lab - Un terminal et un éditeur ; droits de création S3 sur le compte (utilisateur IAM quotidien)
Coût estimé : quasi 0 € — un bucket S3 vide (stockage Free Tier / très faible). Destroy obligatoire en fin de lab. Gardez une alerte de budget AWS active.
Auth sans secrets dans le HCL. Utilisez
AWS_PROFILE/ SSO comme dans Install. Aucuneaccess_keydans les fichiers.tf.
Ce que nous allons construire
Lab workflow Terraform (ca-central-1)
├── versions.tf + providers.tf + main.tf
├── terraform init → .terraform/ + .terraform.lock.hcl
├── fmt + validate
├── plan (+ create) → apply (confirmation manuelle)
├── second plan (No changes) = idempotence
├── modification d’un tag → plan (~ update)
└── terraform destroy + vérif console / CLI
(Schéma à remplacer par une image locale Excalidraw / draw.io, alt : « Workflow Terraform : init, plan, apply, state et destroy ».)
Ce guide remplace le post #1615 par un lab original, en français, centré sur la lecture du plan et les bonnes pratiques (pas de -auto-approve en production).
Étape 1 — Créer le dossier projet et les fichiers
Choisissez un dossier dédié (évitez de mélanger avec d’autres labs) :
mkdir -p ~/terraform-workflow-lab && cd ~/terraform-workflow-lab
export AWS_PROFILE=lab # adaptez au nom de votre profil
export AWS_REGION=ca-central-1
aws sts get-caller-identity
Créez versions.tf :
terraform {
required_version = ">= 1.9.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
Créez providers.tf (Region Canada Central — pas de clés en dur) :
provider "aws" {
region = "ca-central-1"
# Auth via AWS_PROFILE / SSO / env — jamais access_key / secret_key ici
}
Créez main.tf — bucket privé avec tags. Le nom S3 doit être globalement unique : remplacez le suffixe :
resource "aws_s3_bucket" "lab_workflow" {
# Remplacez SUFFIXE-UNIQUE (ex. vos initiales + date)
bucket = "deh-lab-workflow-SUFFIXE-UNIQUE"
tags = {
Project = "devopselastichayway"
ManagedBy = "terraform"
Stage = "workflow"
Environment = "lab"
}
}
resource "aws_s3_bucket_public_access_block" "lab_workflow" {
bucket = aws_s3_bucket.lab_workflow.id
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
Vous avez un root module minimal : versions, provider, ressources. Aucun apply pour l’instant.
Étape 2 — terraform init : providers, .terraform et lock file
cd ~/terraform-workflow-lab
terraform init
Ce que Terraform fait (sans toucher au cloud métier) :
- Lit
required_providerset télécharge hashicorp/aws 5.x depuis le registry - Crée le dossier
.terraform/(plugins locaux — à ne pas committer) - Écrit
.terraform.lock.hcl(empreintes / versions exactes des providers — à committer en équipe) - Affiche un message du type « Terraform has been successfully initialized »
Relancer terraform init sur le même dossier est idempotent tant que les contraintes n’ont pas changé. Si vous clonez le repo ailleurs, init reconstitue .terraform/ grâce au lock file.
Ajoutez un .gitignore minimal :
.terraform/
*.tfstate
*.tfstate.*
crash.log
override.tf
Étape 3 — terraform fmt et terraform validate
Avant tout plan, soignez la forme et la syntaxe :
terraform fmt -recursive
terraform validate
fmtréécrit le HCL selon le style officiel (indentation, alignement). Idéal en pré-commit.validatevérifie la cohérence du graphe et des types après uninitréussi. Il ne parle pas encore à AWS pour créer des ressources.
Sortie attendue de validate : Success! The configuration is valid.
Étape 4 — terraform plan : lire le plan (+ / − / ~)
terraform plan
Terraform compare la config au state (encore vide) et interroge le provider pour préparer un diff. Aucune ressource n’est créée.
Lisez attentivement les symboles :
| Symbole | Sens |
|---|---|
+ |
create — ressource à créer |
− |
destroy — ressource à détruire |
~ |
update in-place — modification sans remplacement |
-/+ |
replace — destroy puis recreate (souvent à cause d’un argument ForceNew) |
Pour ce lab, attendez-vous à des + sur aws_s3_bucket.lab_workflow et aws_s3_bucket_public_access_block.lab_workflow, puis un résumé du type « Plan: 2 to add, 0 to change, 0 to destroy ».
Astuce : terraform plan -out=tfplan enregistre un plan binaire que vous pourrez appliquer tel quel (terraform apply tfplan) — utile en CI, optionnel ici.
Étape 5 — terraform apply (sans -auto-approve) et state local
terraform apply
Terraform réaffiche le plan et demande confirmation (yes). Ne passez pas -auto-approve la première fois : l’habitude de lire le plan protège contre les erreurs coûteuses.
Après confirmation :
- Les ressources sont créées en
ca-central-1 - Terraform écrit
terraform.tfstate(state local) : mapping nom logique ↔ ID réel - Des outputs éventuels s’affichent (nous n’en avons pas encore)
Vérification rapide :
aws s3api head-bucket --bucket "deh-lab-workflow-SUFFIXE-UNIQUE" --region ca-central-1
# ou listez les tags / le bloc d’accès public dans la console S3 (Region Canada Central)
Le state local convient au lab solo. En équipe, un backend distant (S3 + lock) arrivera dans un tuto dédié — ne committez jamais *.tfstate en clair.
Étape 6 — Second plan : No changes (idempotence)
terraform plan
Message attendu : « No changes. Your infrastructure matches the configuration. »
C’est l’idempotence déclarative : relancer plan/apply sans modifier les .tf ne recrée rien. Si vous voyez encore des creates, vérifiez que vous êtes dans le bon dossier et que le state n’a pas été déplacé/supprimé.
Étape 7 — Modifier un tag → plan en update (~)
Changez uniquement un tag dans main.tf, par exemple :
tags = {
Project = "devopselastichayway"
ManagedBy = "terraform"
Stage = "workflow"
Environment = "lab-updated" # modifié
}
Puis :
terraform fmt
terraform plan
Attendez un ~ update in-place sur le bucket (tags), pas un replace. Appliquez avec confirmation :
terraform apply
Relancez un dernier terraform plan : à nouveau « No changes ». Vous venez de vivre le cycle édition → plan → apply sur un changement mineur.
Étape 8 — terraform destroy et vérification
Le lab n’est terminé que lorsque les ressources sont détruites :
terraform destroy
Lisez le plan de destruction (− sur les deux ressources), tapez yes, puis vérifiez :
aws s3api head-bucket --bucket "deh-lab-workflow-SUFFIXE-UNIQUE" --region ca-central-1
# Attendu : erreur Not Found / 404 — le bucket n’existe plus
Le state local reflète l’absence de ressources (fichier vide ou quasi vide selon la version). Vous pouvez supprimer le dossier lab ensuite (étape Nettoyage).
Étape 9 — Checklist et bonnes pratiques workflow
- Toujours
initsur un nouveau clone / machine avant plan/apply. fmt+validateavant de partager une PR.- Lire le plan : create OK ? destroy inattendu ? replace sur une base de données ?
- Pas de
-auto-approveen production (ni en lab tant que vous apprenez). - State :
.gitignoresur.tfstate; lock file providers commité. - Region explicite (
ca-central-1ici) alignée surAWS_REGION/ profil. - Zéro secret dans le HCL ; profil nommé ou SSO.
- Tout lab qui
applyse termine pardestroy(ou ticket de suivi si volontairement conservé). - Noms S3 uniques ; tags
Project/ManagedBypour le inventaire.
Nettoyage
Si le destroy de l’étape 8 a réussi, il ne reste que les fichiers locaux :
cd ~ && rm -rf ~/terraform-workflow-lab
Si destroy a échoué (bucket non vide, droits manquants) : videz d’éventuels objets, relancez terraform destroy, ou supprimez le bucket dans la console ca-central-1, puis nettoyez le state. Vérifiez qu’aucune ressource « lab-workflow » ne traîne.
Erreurs fréquentes
| Symptôme | Cause | Correction |
|---|---|---|
BucketAlreadyExists / nom pris |
Nom S3 globalement unique | Changez le suffixe dans bucket = "..." |
No valid credential sources |
Profil / env non chargés | export AWS_PROFILE=… puis aws sts get-caller-identity |
| Plan dans la mauvaise Region | Region CLI ≠ provider | Alignez providers.tf et AWS_REGION sur ca-central-1 |
validate avant init |
Providers absents | Lancez terraform init d’abord |
Apply avec -auto-approve « par habitude » |
Risque de destroy silencieux | Confirmation manuelle ; lire les − |
State perdu / dossier copié sans .tfstate |
Terraform « oublie » les IDs | Ne déplacez pas le state à la légère ; backend distant plus tard |
.terraform/ commité dans Git |
Bruit + binaires | Ignorer .terraform/ ; garder .terraform.lock.hcl |
Quiz (3 questions)
1. Que crée principalement terraform init dans ce lab ?
- A. Le bucket S3 en production
- B. Le dossier
.terraform/et le lock file des providers - C. Un utilisateur IAM root
2. Que signifie un symbole ~ dans un plan Terraform ?
- A. Create d’une nouvelle ressource
- B. Update in-place (modification sans remplacement forcé)
- C. Échec du provider AWS
3. Pourquoi éviter -auto-approve en production ?
- A. Parce que la commande est dépréciée depuis Terraform 1.0
- B. Pour forcer la relecture du plan (creates / destroys / replaces) avant mutation
- C. Parce que le state local refuse cette option
Réponses : 1‑B · 2‑B · 3‑B
Pourquoi / quand pratiquer le workflow complet
init → fmt/validate → plan → apply → destroy est le réflexe métier. Sans lui, vous appliquez à l’aveugle ou laissez des ressources orphelines. Faites ce lab dès que Terraform répond (terraform version) et que votre profil AWS fonctionne en ca-central-1.
Pièges du cycle plan/apply
-auto-approveen production ou en lab « pour aller vite » : vous sautez la lecture du plan.- Relancer
applysans secondplanaprès une modification manuelle dans la console (drift). - Committer
terraform.tfstate: le state local contient des IDs et parfois des données sensibles. - Oublier
destroyen fin de lab : un bucket oublié coûte peu, un NAT Gateway beaucoup. - Interpréter
~(update) comme anodin : certains updates sont en réalité des replaces.
FAQ workflow
fmt est-il obligatoire ? Fortement recommandé : style stable, diffs Git lisibles. validate vérifie la syntaxe après init.
Que signifie « No changes » au second plan ? Idempotence : la config et le state décrivent déjà le cloud. C’est le signal que votre lab est sain.
Pourquoi confirmation manuelle à l’apply ? Pour forcer la relecture des + / − / ~. En CI, un plan artifact + revue remplace cette invite.
State local vs distant ? Local pour apprendre. En équipe / CI : backend S3 + verrouillage (tuto State).
Pour aller plus loin
- Doc officielle : Terraform CLI, Command: plan, AWS provider 5.x
- Sur ce site : après ce workflow, enchaînez Blocs HCL puis approfondissez providers et state distant
- Rappel : idempotence ≠ « rien ne peut mal se passer » — un mauvais plan lu trop vite reste le risque n°1
Maillage série Terraform (P2)
| ← Précédent | Installer Terraform (installer-terraform) |
| → Suivant | Blocs HCL (terraform-blocs-hcl) — à rédiger |
| Aussi | Découvrir Terraform (terraform-overview) · Providers / resources |
| Carte | Overview · Install · Workflow · Blocks · Providers · Variables · Locals · Outputs · State · Data sources · Loops · Conditionals · Dynamic blocks · Modules ×2 · Workspaces · Provisioners · EBS · ELB/ALB · IAM · RDS · VPC · Auto Scaling · Route 53 |
Cas réel — apply trop vite sur un nom S3 déjà pris
Le plan est vert, vous tapez yes, AWS rend BucketAlreadyExists. Ce n’est pas un bug Terraform : le nom est global. Changez le suffixe, relancez plan, ne « forcez » pas un import au hasard. Autre classique : un second plan qui recrée tout parce que vous avez changé de dossier sans emporter le state. Le state local est le contrat ; le déplacer sans le dire, c’est mentir à Terraform.
En équipe, -auto-approve dans un alias shell a déjà détruit un lab partagé. Gardez la confirmation manuelle tant que vous apprenez à lire − et -/+. En ca-central-1, alignez AWS_REGION et le bloc provider : un plan « vide » dans la mauvaise région est un faux sentiment de sécurité.
À retenir : workflow = lire le plan comme un diff de prod, même pour un bucket de lab.
Retour parcours Terraform — hub de la série et leçons sœurs.



