DevOps Elastic Hayway
Document

SUBSCRIBE TO GET FULL ACCESS TO THE E-BOOKS FOR FREE 🎁SUBSCRIBE NOW

Professional Dropdown with Icon

SUBSCRIBE NOW TO GET FREE ACCESS TO EBOOKS

TerraformLesson 4 / 2410 min readUpdated September 13, 2026

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 Region ca-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 version OK, profil AWS prêt
  • AWS CLI v2 configurée : aws sts get-caller-identity ré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. Aucune access_key dans 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) :

  1. Lit required_providers et télécharge hashicorp/aws 5.x depuis le registry
  2. Crée le dossier .terraform/ (plugins locaux — à ne pas committer)
  3. Écrit .terraform.lock.hcl (empreintes / versions exactes des providers — à committer en équipe)
  4. 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
  • fmt réécrit le HCL selon le style officiel (indentation, alignement). Idéal en pré-commit.
  • validate vérifie la cohérence du graphe et des types après un init ré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

  1. Toujours init sur un nouveau clone / machine avant plan/apply.
  2. fmt + validate avant de partager une PR.
  3. Lire le plan : create OK ? destroy inattendu ? replace sur une base de données ?
  4. Pas de -auto-approve en production (ni en lab tant que vous apprenez).
  5. State : .gitignore sur .tfstate ; lock file providers commité.
  6. Region explicite (ca-central-1 ici) alignée sur AWS_REGION / profil.
  7. Zéro secret dans le HCL ; profil nommé ou SSO.
  8. Tout lab qui apply se termine par destroy (ou ticket de suivi si volontairement conservé).
  9. Noms S3 uniques ; tags Project / ManagedBy pour 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-approve en production ou en lab « pour aller vite » : vous sautez la lecture du plan.
  • Relancer apply sans second plan après une modification manuelle dans la console (drift).
  • Committer terraform.tfstate : le state local contient des IDs et parfois des données sensibles.
  • Oublier destroy en 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.

Share your love

Leave a Reply

Your email address will not be published. Required fields are marked *