
Vous relancez un script qui crée une VM. Il échoue parce que la ressource existe déjà — ou pire, il la recrée en doublon. Et pour recréer l’environnement de staging identique à la prod, vous devez retrouver l’ordre exact des commandes exécutées il y a trois mois.
Terraform utilise une approche fondamentalement différente : au lieu de décrire les étapes pour configurer un serveur (impératif), vous décrivez l’état final voulu (déclaratif). Terraform lit l’état courant via le state et les APIs des providers, compare avec votre configuration HCL, puis propose les actions nécessaires pour converger vers l’état souhaité. Relancer Terraform ne change rien tant que la configuration, le state et l’infrastructure réelle sont déjà alignés. C’est l’idempotence par conception — un résultat très difficile à obtenir avec un script shell classique.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- La différence fondamentale : impératif (étapes) vs déclaratif (état final)
- L’idempotence : pourquoi relancer Terraform deux fois ne crée rien en double
- Comment Terraform calcule les changements : le mécanisme de diff avec le state
- Les limites du déclaratif : ce que Terraform ne gère pas et quand utiliser Ansible
Impératif : décrire les étapes
Section intitulée « Impératif : décrire les étapes »Analogie : une approche impérative, c’est donner une recette de cuisine étape par étape. « Mélanger les œufs, ajouter la farine, cuire… » Si vous oubliez une étape, le gâteau rate. Si vous lancez la recette deux fois, vous faites deux gâteaux (probablement pas ce que vous vouliez).
Dans une approche impérative, on écrit les actions à effectuer dans l’ordre :
#!/bin/bash# Script impératif pour créer une VM
# Vérifier si la VM existe déjàif virsh list --all | grep -q "mon-serveur"; then echo "La VM existe déjà" exit 0fi
# Créer le volumeqemu-img create -f qcow2 /var/lib/libvirt/images/mon-serveur.qcow2 20G
# Copier l'image de basecp /home/bob/images/ubuntu-24.04-cloudimg.img \ /var/lib/libvirt/images/mon-serveur.qcow2
# Créer la VMvirt-install \ --name mon-serveur \ --memory 1024 \ --vcpus 1 \ --disk /var/lib/libvirt/images/mon-serveur.qcow2 \ --network default \ --import --noautoconsoleCe script dit comment créer la VM. Les problèmes :
- Si la VM existe à moitié (disque créé, VM non), le script échoue ou crée une incohérence.
- Modifier la RAM nécessite d’écrire une logique supplémentaire.
- Supprimer la VM nécessite un autre script.
- Impossible de “rejouer” le script sans risque.
Déclaratif : décrire l’état final
Section intitulée « Déclaratif : décrire l’état final »Analogie : une approche déclarative, c’est donner un ordre de résultat : « Je veux un gâteau chocolat ». Qui prépare le gâteau, comment, dans quel ordre ? Ce n’est pas votre problème. Terraform prend l’ordre et calcule les étapes une fois qu’il voit ce qui existe déjà. Relancer la commande : le gâteau est déjà là, rien ne se passe. C’est idempotent.
Avec Terraform, on décrit ce qu’on veut :
resource "libvirt_volume" "disk" { name = "mon-serveur.qcow2" pool = "default" target = { format = { type = "qcow2" } } create = { content = { url = "/home/bob/images/ubuntu-24.04-cloudimg.img" } }}
resource "libvirt_domain" "vm" { name = "mon-serveur" type = "kvm" memory = 1024 memory_unit = "MiB" vcpu = 1 # ...}Terraform se charge de calculer les actions nécessaires pour atteindre cet état, depuis l’état courant. On ne dit pas “crée”, on dit “voici ce qui doit exister”.
La conséquence clé : l’idempotence
Section intitulée « La conséquence clé : l’idempotence »Un code déclaratif est idempotent : l’appliquer une deuxième fois ne change rien si l’infrastructure correspond déjà à la description.
| Situation | Script impératif | Terraform |
|---|---|---|
| Ressource absente | Crée | Crée |
| Ressource déjà à jour | Erreur probable | Ne fait rien |
| Ressource partiellement créée | Comportement imprévisible | Détecte et corrige |
| Ressource à modifier | Logique manuelle requise | Modifie automatiquement |
Comment Terraform calcule les changements
Section intitulée « Comment Terraform calcule les changements »Terraform compare deux états :
État souhaité (vos fichiers .tf) ↓État réel (lu depuis le state + l'API du provider) ↓Diff (ce que terraform plan affiche) ↓Actions (créer / modifier / détruire)Si la VM a déjà la bonne RAM et le bon nombre de vCPUs, terraform plan
affiche :
No changes. Your infrastructure matches the configuration.Si vous passez de 1024 à 2048 MiB de RAM dans le code :
~ resource "libvirt_domain" "vm" { ~ memory = 1024 -> 2048 }
Plan: 0 to add, 1 to change, 0 to destroy.Terraform sait quoi faire sans qu’on lui explique comment.
Ce que Terraform ne gère pas : l’intérieur des serveurs
Section intitulée « Ce que Terraform ne gère pas : l’intérieur des serveurs »Déclaratif n’est pas magique
Section intitulée « Déclaratif n’est pas magique »L’approche déclarative a des limites :
- Certains changements nécessitent une recréation : changer le nom d’une VM libvirt force sa destruction et recréation. Terraform le gère, mais c’est un impact à anticiper.
- Les opérations séquentielles complexes sont plus naturelles en impératif. Terraform gère les dépendances automatiques, mais pas les workflows applicatifs.
- Le state peut diverger de la réalité si des ressources sont modifiées en dehors de Terraform (console, CLI directe). Cette divergence s’appelle le drift.
À retenir
Section intitulée « À retenir »- Impératif : on décrit les étapes (créer, copier, démarrer).
- Déclaratif : on décrit l’état final souhaité.
- Terraform est déclaratif : il calcule lui-même les actions à effectuer.
- L’idempotence est une conséquence directe : rejouer le code ne casse rien.
- Terraform gère l’infrastructure. La configuration interne des serveurs se fait mieux avec des outils dédiés comme cloud-init, Packer ou Ansible.