Aller au contenu
Infrastructure as Code medium
🔐 Alerte sécurité — Incident supply chain Trivy : lire mon analyse de l'attaque

Déclaratif vs impératif : comprendre l'approche Terraform

9 min de lecture

logo terraform

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.

  • 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

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 0
fi
# Créer le volume
qemu-img create -f qcow2 /var/lib/libvirt/images/mon-serveur.qcow2 20G
# Copier l'image de base
cp /home/bob/images/ubuntu-24.04-cloudimg.img \
/var/lib/libvirt/images/mon-serveur.qcow2
# Créer la VM
virt-install \
--name mon-serveur \
--memory 1024 \
--vcpus 1 \
--disk /var/lib/libvirt/images/mon-serveur.qcow2 \
--network default \
--import --noautoconsole

Ce 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.

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”.

Un code déclaratif est idempotent : l’appliquer une deuxième fois ne change rien si l’infrastructure correspond déjà à la description.

SituationScript impératifTerraform
Ressource absenteCréeCrée
Ressource déjà à jourErreur probableNe fait rien
Ressource partiellement crééeComportement imprévisibleDétecte et corrige
Ressource à modifierLogique manuelle requiseModifie automatiquement

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)

Déclaratif vs impératif : comment Terraform gère l'état souhaité

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 »

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.
  • 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.

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracing. Aujourd'hui, ce site ne couvre même pas mes frais d'hébergement, d'électricité, de matériel, de logiciels, mais surtout de cafés.

Un soutien régulier, même symbolique, m'aide à garder ces ressources gratuites et à continuer de produire des guides de qualité. Merci pour votre appui.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn