
Votre terraform apply échoue à mi-chemin avec une erreur cryptique :
la VM n’a pas pu démarrer car le réseau n’était pas encore prêt. Aucune
référence entre les deux ressources n’existe dans le code — Terraform
ne peut pas déduire l’ordre correct.
Terraform construit automatiquement un graphe de dépendances à
partir des références entre ressources. Quand resource A utilise
un attribut de resource B, Terraform sait que B doit exister avant A.
Mais certaines dépendances sont comportementales, pas structurelles :
un service doit être démarré, un réseau actif, un pare-feu appliqué
— sans qu’aucune référence d’attribut ne l’exprime. C’est précisément
pour ces cas qu’existe depends_on : forcer un ordre explicite là
où le graphe implicite est aveugle.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Comment Terraform détermine l’ordre de création via les références
- La différence entre dépendance implicite et explicite
- Quand utiliser
depends_on— et quand ne pas l’utiliser - Usage sur les ressources, les modules et les
datasources - Lab KVM : réseau NAT créé avant la VM via
depends_on
Prérequis
Section intitulée « Prérequis »- Bases des ressources Terraform (Déclarer des ressources)
- Notions de providers (Providers Terraform)
Dépendances implicites
Section intitulée « Dépendances implicites »Analogie : imaginez un chantier de construction. Si le plombier a besoin d’eau courante (du réservoir), il ne peut pas commencer avant que le réservoir soit installé. Terraform voit la référence (« le chef plombier dit qu’il a besoin du réservoir ») et ordonne automatiquement les étapes. C’est une dépendance implicite.
Terraform crée automatiquement une dépendance implicite dès qu’une ressource référence un attribut d’une autre ressource.
resource "libvirt_volume" "base" { name = "vm-base.qcow2" # ...}
resource "libvirt_domain" "vm" { devices = { disks = [{ source = { file = { file = libvirt_volume.base.path } } # ↑ référence → Terraform sait que base doit exister avant vm }] }}Terraform lit cette référence et en déduit :
libvirt_volume.base→ doit être créé avantlibvirt_domain.vmlibvirt_domain.vm→ doit être détruit avantlibvirt_volume.base
C’est le cas le plus courant : pas besoin de depends_on.
Dépendances explicites avec depends_on
Section intitulée « Dépendances explicites avec depends_on »Certaines dépendances ne passent pas par des attributs HCL. Elles sont comportementales, pas structurelles. Exemples :
- Un réseau doit être opérationnel avant qu’une VM soit créée dedans
- Un utilisateur IAM doit avoir ses permissions avant qu’un job soit lancé
- Un script d’initialisation doit être terminé avant qu’une ressource soit configurée
resource "libvirt_network" "lab_net" { name = "lab12-net" forward = { mode = "nat" } ips = [{ address = "10.99.12.1", netmask = "255.255.255.0" }]}
resource "libvirt_domain" "vm" { # ... devices = { interfaces = [{ source = { network = { network = libvirt_network.lab_net.name } } # Référence au nom du réseau, mais Terraform ne sait pas que # la ressource doit être PRÊTE (pas seulement son nom connu). }] }
depends_on = [libvirt_network.lab_net] # ← force l'attente complète}Exemple : VM sur un réseau NAT dédié
Section intitulée « Exemple : VM sur un réseau NAT dédié »Structure du lab
Section intitulée « Structure du lab »# main.tf — réseau NAT + VM avec depends_onresource "libvirt_network" "lab_net" { name = "lab12-net" autostart = false
forward = { mode = "nat" }
ips = [{ address = "10.99.12.1" netmask = "255.255.255.0" dhcp = { ranges = [{ start = "10.99.12.100", end = "10.99.12.200" }] } }]}
resource "libvirt_volume" "base" { name = "lab12-vm-base.qcow2" pool = "default" target = { format = { type = "qcow2" } } create = { content = { url = "/home/bob/images/ubuntu-24.04-cloudimg.img" } }}
resource "libvirt_domain" "vm" { name = "lab12-vm" 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.base.path } } target = { dev = "vda", bus = "virtio" } }] interfaces = [{ model = { type = "virtio" } source = { network = { network = libvirt_network.lab_net.name } } }] }
depends_on = [libvirt_network.lab_net] # libvirt_volume.base n'est PAS ici : la référence à .path # crée déjà une dépendance implicite — depends_on serait redondant.}Résultats réels
Section intitulée « Résultats réels »libvirt_volume.base: Creating...libvirt_network.lab_net: Creating...libvirt_network.lab_net: Creation complete after 0slibvirt_volume.base: Creation complete after 0slibvirt_domain.vm: Creating...libvirt_domain.vm: Creation complete after 0s [name=lab12-vm]
Apply complete! Resources: 3 added, 0 changed, 0 destroyed.
Outputs:network_gateway = "10.99.12.1"network_name = "lab12-net"vm_name = "lab12-vm"Terraform a créé libvirt_network et libvirt_volume en parallèle
(deux ressources sans dépendance entre elles), puis libvirt_domain seulement
après que les deux soient terminées.
Visualiser le graphe de dépendances
Section intitulée « Visualiser le graphe de dépendances »terraform graph | dot -Tpng > graph.pngRequiert graphviz. Chaque flèche représente une dépendance. depends_on
ajoute des flèches en pointillés.
Sans graphviz, lire le plan suffit — Terraform affiche l’ordre d’exécution :
libvirt_network.lab_net: Creating... ← 1er (pas de déps)libvirt_volume.base: Creating... ← 1er (en parallèle)libvirt_domain.vm: Creating... ← après les deux précédentsdepends_on sur les modules
Section intitulée « depends_on sur les modules »module "database" { source = "./modules/database"}
module "application" { source = "./modules/application"
depends_on = [module.database] # Tout le module database est terminé avant que # les ressources du module application soient créées.}depends_on sur les data sources
Section intitulée « depends_on sur les data sources »Un data source qui dépend d’une ressource créée dans le même plan :
resource "aws_iam_role" "lambda" { name = "lambda-role" # ...}
data "aws_iam_policy_document" "lambda" { depends_on = [aws_iam_role.lambda] # Attend que le rôle existe avant de le lire statement { actions = ["sts:AssumeRole"] principals { type = "Service", identifiers = ["lambda.amazonaws.com"] } }}## Quand NE PAS utiliser depends_on
| Situation | Solution correcte ||-----------|------------------|| Ressource B référence un attribut de A | Référence implicite (`A.attribut`) — `depends_on` inutile || Module B utilise des outputs du module A | `module.a.output_name` — dépendance implicite créée || Vous voulez un "ordre logique" sans vraie dépendance | Ne pas ajouter `depends_on` — Terraform s'en charge |
`depends_on` explicite **désactive le parallélisme** entre les ressourcesconcernées et peut produire des plans plus conservateurs (davantage devaleurs en `known after apply`, remplacements évitables). Ajouter desdépendances inutiles ralentit les apply et réduit la qualité du plan.
## Règle pratique
Poser la question : *"Si je supprimais `depends_on`, Terraform pourrait-iltenter de créer la ressource avant que sa dépendance soit opérationnelle ?"*
- **Oui** → `depends_on` justifié- **Non** → une référence d'attribut implicite suffit
## À retenir
1. Les **références** (`ressource_a.attribut`) créent des dépendances implicites automatiquement2. `depends_on` est pour les dépendances **comportementales** — non visibles dans le HCL3. Terraform crée les ressources indépendantes **en parallèle** — `depends_on` le désactive4. Sur des modules : `depends_on = [module.nom]` attend la fin de toutes les ressources du module5. Sur des data sources : utile quand la ressource source est créée dans le même plan
## Prochaines étapes
<CardGrid>
<LinkCard title="lifecycle : contrôler le remplacement des ressources" description="create_before_destroy, prevent_destroy, ignore_changes : maîtriser le cycle de vie des ressources." href="/docs/infra-as-code/provisionnement/terraform/ecrire-code/lifecycle-terraform/"/>
<LinkCard title="Votre première infrastructure" description="Créer une VM complète sur KVM avec Terraform : lab guidé de A à Z." href="/docs/infra-as-code/provisionnement/terraform/premieres-infras/premiere-infrastructure/"/>
</CardGrid>