
Vous lancez terraform apply et votre infrastructure change — mais vous
ne savez pas exactement ce qui s’est passé. Ou pire : vous avez appliqué
sans regarder le plan, et Terraform a détruit une ressource que vous
vouliez conserver.
Analogie : le workflow Terraform fonctionne comme la procédure d’un chirurgien. Avant d’opérer, il examine les radios (plan). Il ne dit jamais « j’ai une idée, opérons immédiatement » (apply). Entre la décision et le geste, il y a toujours un moment de vérification. Le plan est cette étape critique : vous lisez exactement ce qui va changer avant d’activer les changements.
En pratique, le cycle quotidien Terraform s’articule autour de 4
commandes : init, plan, apply, destroy. Le
core workflow officiel
HashiCorp est Write → Plan → Apply ; init est un prérequis
d’initialisation et destroy une commande complémentaire. Ce cycle est
conçu pour rendre chaque changement d’infrastructure prévisible et
contrôlable. Le plan vous montre exactement ce qui va changer
avant que quoi que ce soit soit modifié. Comprendre ce que signifient
les symboles +, -, ~ dans la sortie du plan est la compétence
fondamentale pour utiliser Terraform en production sans mauvaises
surprises.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Le rôle de chaque commande :
init,validate,plan,apply,destroy - Lire un plan Terraform : interpréter les
+,-,~avant d’appliquer - Exécuter un cycle complet : de l’initialisation à la destruction sur KVM/libvirt
- Les pièges du workflow : quand
applyéchoue à mi-chemin et comment récupérer
Prérequis
Section intitulée « Prérequis »- Terraform ≥ 1.11 installé (guide d’installation)
- KVM/libvirt opérationnel (pour reproduire l’exemple)
- Image Ubuntu 24.04 cloud disponible localement
Le cycle complet en un coup d’œil
Section intitulée « Le cycle complet en un coup d’œil »Chaque étape correspond à une phase du cycle de vie d’une infrastructure.
Étape 1 — terraform init
Section intitulée « Étape 1 — terraform init »terraform init est toujours la première commande à lancer dans un nouveau
projet, ou après l’ajout d’un provider. Elle :
- Télécharge les providers déclarés dans le bloc
required_providers - Initialise le backend (local par défaut)
- Prépare le répertoire
.terraform/
terraform initRésultat attendu :
Initializing the backend...Initializing provider plugins...- Finding dmacvicar/libvirt versions matching "~> 0.8"...- Installing dmacvicar/libvirt v0.9.7...
Terraform has been successfully initialized!Étape 2 — terraform validate
Section intitulée « Étape 2 — terraform validate »terraform validate vérifie que la configuration est syntaxiquement
valide et cohérente en interne. Il ne contacte pas les API distantes
des providers et ne lit pas le remote state, mais il nécessite un
répertoire déjà initialisé (terraform init).
terraform validateRésultat attendu :
Success! The configuration is valid.En cas d’erreur :
│ Error: Unsupported argument││ on main.tf line 12, in resource "libvirt_volume" "disk":│ 12: format = "qcow2"││ An argument named "format" is not expected here.Utilisez validate systématiquement avant plan pour détecter les fautes
de frappe et les attributs manquants. Si vous ne voulez pas configurer le
backend, lancez terraform init -backend=false au préalable.
Étape 3 — terraform plan
Section intitulée « Étape 3 — terraform plan »terraform plan lit l’état courant des objets distants via les providers,
compare la configuration au state existant, puis calcule les actions
nécessaires pour faire correspondre l’infrastructure à la configuration.
terraform planL’output liste les ressources à créer (+), modifier (~) ou supprimer (-) :
Terraform will perform the following actions:
# libvirt_volume.disk will be created + resource "libvirt_volume" "disk" { + name = "lab-01.qcow2" + pool = "default" ... }
Plan: 1 to add, 0 to change, 0 to destroy.Étape 4 — terraform apply
Section intitulée « Étape 4 — terraform apply »terraform apply exécute les changements affichés par plan. Par défaut, il
demande une confirmation interactive.
terraform applyPour automatiser (scripts, CI/CD) :
terraform apply -auto-approveRésultat attendu :
libvirt_volume.disk: Creating...libvirt_volume.disk: Creation complete after 1s [id=/var/lib/libvirt/images/lab-01.qcow2]
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.Terraform met à jour le fichier terraform.tfstate après chaque apply réussi.
Étape 5 — terraform destroy
Section intitulée « Étape 5 — terraform destroy »terraform destroy supprime toutes les ressources gérées par le state
courant. C’est l’opération inverse d’apply.
terraform destroyOu sans confirmation :
terraform destroy -auto-approveExemple complet testé sur KVM/libvirt
Section intitulée « Exemple complet testé sur KVM/libvirt »Voici un exemple inspiré d’une configuration testée avec le provider libvirt 0.9.7 sur KVM.
versions.tf :
terraform { required_version = ">= 1.11.0" required_providers { libvirt = { source = "dmacvicar/libvirt" version = "~> 0.8" } }}main.tf :
provider "libvirt" { uri = "qemu:///system"}
resource "libvirt_volume" "disk" { name = "workflow-demo.qcow2" pool = "default" target = { format = { type = "qcow2" } } create = { content = { url = "/home/bob/images/ubuntu-24.04-cloudimg.img" } }}
resource "libvirt_domain" "vm" { name = "workflow-demo" type = "kvm" memory = 512 memory_unit = "MiB" vcpu = 1
os = { type = "hvm" type_arch = "x86_64" type_machine = "q35" }
devices = { disks = [ { source = { file = { file = libvirt_volume.disk.path } } target = { dev = "vda" bus = "virtio" } } ] interfaces = [ { model = { type = "virtio" } source = { network = { network = "default" } } } ] }}
output "vm_name" { value = libvirt_domain.vm.name}Exécution du cycle complet :
terraform initterraform validate # Success! The configuration is valid.terraform plan # Plan: 2 to add, 0 to change, 0 to destroy.terraform apply -auto-approvevirsh list --all # workflow-demo shut offterraform destroy -auto-approveCe que Terraform retient entre deux apply
Section intitulée « Ce que Terraform retient entre deux apply »Après chaque apply, Terraform écrit un fichier terraform.tfstate qui
enregistre la correspondance entre la configuration et les objets
d’infrastructure. Lors du prochain plan, il combine plusieurs sources :
Vos fichiers .tf → état souhaitéterraform.tfstate → correspondance connue par TerraformAPI provider → état courant observéPlan → actions proposéesLe state n’est pas « ce qui existe » — c’est la mémoire de Terraform
sur les objets qu’il gère. plan s’appuie aussi sur la lecture de
l’infrastructure réelle via les providers. Sans le state, Terraform ne
peut pas savoir quels objets il gère — il ne faut pas le supprimer
manuellement.
Le state est traité en détail dans Gérer le state Terraform.
Les commandes complémentaires
Section intitulée « Les commandes complémentaires »| Commande | Rôle |
|---|---|
terraform fmt | Reformate les fichiers .tf selon le style officiel |
terraform output | Affiche les valeurs des outputs après apply |
terraform show | Affiche le state courant de manière lisible |
terraform console | REPL interactif pour tester des expressions |
terraform state list | Liste les ressources dans le state |
À retenir
Section intitulée « À retenir »- Le workflow est toujours
init→validate→plan→apply. planest non destructif : il ne fait qu’afficher les changements.applymodifie l’infrastructure et met à jour le state.destroysupprime toutes les ressources gérées.- Le state est le lien entre votre code et l’infrastructure réelle.