
Quand quelqu’un modifie manuellement une ressource — supprime un réseau via la console, change un paramètre en SSH — le state Terraform ne le sait pas. L’écart entre ce que le state décrit et ce qui existe réellement s’appelle le drift. terraform plan le détecte, terraform apply -refresh-only met le state à jour, et terraform import rattache une ressource existante que Terraform ne connaît pas encore. Ces trois mécanismes forment votre boîte à outils de diagnostic.
Prérequis : connaître la structure du state et savoir utiliser terraform state list et terraform state show.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Détecter le drift avec
terraform plan - Mettre à jour le state sans modifier l’infrastructure avec
terraform apply -refresh-only - Importer une ressource existante dans le state avec
terraform import - Utiliser le bloc
importcomme alternative déclarative (Terraform >= 1.5) - Automatiser la détection de drift avec
-detailed-exitcode
Qu’est-ce que le drift ?
Section intitulée « Qu’est-ce que le drift ? »Le drift (dérive) apparaît quand l’infrastructure réelle ne correspond plus à ce que le state décrit. Les causes les plus fréquentes sont :
| Cause | Exemple concret |
|---|---|
| Modification manuelle | Quelqu’un désactive l’autostart d’un réseau via la console |
| Action d’un autre outil | Un script Ansible modifie une configuration |
| Suppression externe | Un collègue supprime une VM directement |
| Expiration automatique | Un certificat ou une ressource temporaire expire |
Le drift n’est pas une erreur en soi — c’est une désynchronisation entre le state et la réalité. Le problème survient si vous ne le détectez pas : le prochain apply peut produire des résultats inattendus.
Détecter le drift avec plan
Section intitulée « Détecter le drift avec plan »terraform plan compare systématiquement le state avec l’infrastructure réelle avant de calculer les changements. Si une ressource a été modifiée en dehors de Terraform, le plan le signale.
Imaginons qu’un collègue désactive l’autostart d’un réseau directement en ligne de commande :
terraform planlibvirt_network.net: Refreshing state... [id=a12f1d21-0a1e-4af2-9b0b-2c7c59d043df]
Terraform used the selected providers to generate the following execution plan.
# libvirt_network.net will be updated in-place ~ resource "libvirt_network" "net" { ~ autostart = false -> true id = "a12f1d21-0a1e-4af2-9b0b-2c7c59d043df" name = "mon-reseau" }
Plan: 0 to add, 1 to change, 0 to destroy.Le plan montre autostart = false -> true : la valeur réelle (false) diffère de la valeur déclarée dans le code (true). Terraform propose de corriger le drift en remettant la valeur du code.
Deux réponses possibles face au drift
Section intitulée « Deux réponses possibles face au drift »Quand terraform plan détecte un drift, vous avez deux choix :
| Stratégie | Commande | Quand l’utiliser |
|---|---|---|
| Corriger le drift | terraform apply | La modification manuelle était une erreur — vous voulez remettre l’infrastructure conforme au code |
| Accepter le drift | terraform apply -refresh-only | La modification manuelle était intentionnelle — vous voulez mettre le state à jour pour refléter la réalité |
Mettre à jour le state avec refresh-only
Section intitulée « Mettre à jour le state avec refresh-only »N’utilisez plus terraform refresh dans les guides récents ou vos scripts : préférez terraform apply -refresh-only, qui montre les écarts détectés et demande une confirmation avant d’écrire dans le state.
terraform apply -refresh-only lit l’état réel de chaque ressource et met à jour le state sans modifier l’infrastructure. C’est l’inverse d’un apply classique : au lieu de rendre l’infrastructure conforme au code, il rend le state conforme à la réalité.
terraform apply -refresh-onlylibvirt_network.net: Refreshing state... [id=a12f1d21-0a1e-4af2-9b0b-2c7c59d043df]
Note: Objects have changed outside of Terraform
Terraform detected the following changes made outside of Terraform since thelast "terraform apply" command:
# libvirt_network.net has changed ~ resource "libvirt_network" "net" { ~ autostart = true -> false id = "a12f1d21-0a1e-4af2-9b0b-2c7c59d043df" name = "mon-reseau" }
Would you like to update the Terraform state to reflect these detected changes?
Apply complete! Resources: 0 added, 0 changed, 0 destroyed.Terraform vous montre les écarts détectés et demande confirmation. Après le refresh, le state reflète la réalité — mais votre code HCL contient toujours autostart = true. Le prochain plan proposera donc de corriger l’infrastructure.
Importer une ressource existante
Section intitulée « Importer une ressource existante »terraform import rattache une ressource qui existe déjà dans l’infrastructure au state Terraform. Le cas classique : une ressource créée manuellement ou par un autre outil que vous voulez désormais gérer avec Terraform.
Workflow d’import
Section intitulée « Workflow d’import »-
Écrire le bloc resource dans le code HCL
Avant d’importer, le bloc
resourcecorrespondant doit exister dans votre configuration :resource "libvirt_network" "legacy" {name = "legacy-manual-net"autostart = trueforward = {mode = "nat"}ips = [{address = "10.10.99.1"netmask = "255.255.255.0"dhcp = {ranges = [{start = "10.10.99.100"end = "10.10.99.200"}]}}]} -
Identifier l’ID de la ressource existante
Chaque provider utilise un format d’ID différent. Pour le provider libvirt, un réseau s’identifie par son UUID :
Fenêtre de terminal virsh net-info legacy-manual-netName: legacy-manual-netUUID: d227692a-646f-47a4-8b0a-fefbe48b6601Active: yesPersistent: yesAutostart: yesBridge: virbr-legacy -
Exécuter l’import
Fenêtre de terminal terraform import libvirt_network.legacy d227692a-646f-47a4-8b0a-fefbe48b6601libvirt_network.legacy: Importing from ID "d227692a-646f-47a4-8b0a-fefbe48b6601"...libvirt_network.legacy: Import prepared!Prepared libvirt_network for importlibvirt_network.legacy: Refreshing state... [id=d227692a-646f-47a4-8b0a-fefbe48b6601]Import successful!The resources that were imported are shown above. These resources are now inyour Terraform state and will henceforth be managed by Terraform. -
Vérifier avec un plan
Après l’import, un
terraform planpeut montrer des différences entre le state importé et votre code HCL :Fenêtre de terminal terraform planSi le plan affiche
No changes, la configuration correspond parfaitement. Sinon, ajustez votre code HCL pour correspondre à la réalité de la ressource, ou appliquez pour aligner l’infrastructure sur votre code.
Alternative déclarative : le bloc import (Terraform >= 1.5)
Section intitulée « Alternative déclarative : le bloc import (Terraform >= 1.5) »Depuis Terraform 1.5, vous pouvez déclarer un import directement dans le code HCL avec un bloc import. Cette approche est traçable dans le contrôle de version et reproductible en équipe.
import { to = libvirt_network.legacy id = "d227692a-646f-47a4-8b0a-fefbe48b6601"}
resource "libvirt_network" "legacy" { name = "legacy-manual-net" autostart = true # ... reste de la configuration}Le prochain terraform plan affiche :
# libvirt_network.legacy will be updated in-place # (imported from "d227692a-646f-47a4-8b0a-fefbe48b6601") ~ resource "libvirt_network" "legacy" { autostart = true name = "legacy-manual-net" ... }
Plan: 1 to import, 0 to add, 1 to change, 0 to destroy.Après le apply, la ressource est importée et le bloc import peut être retiré du code :
Apply complete! Resources: 1 imported, 0 added, 1 changed, 0 destroyed.Commande vs bloc import
Section intitulée « Commande vs bloc import »| Critère | terraform import | Bloc import {} |
|---|---|---|
| Version minimale | Toutes | Terraform >= 1.5 |
| Traçabilité VCS | Non (action ponctuelle) | Oui (dans le code) |
| Reproductibilité | Non | Oui (tout le monde applique) |
| Revue de code | Impossible | Possible via PR |
| Usage recommandé | Import rapide en solo | Projets en équipe |
Automatiser la détection de drift
Section intitulée « Automatiser la détection de drift »Le flag -detailed-exitcode
Section intitulée « Le flag -detailed-exitcode »terraform plan -detailed-exitcode retourne un code de sortie différent selon le résultat :
| Code de sortie | Signification |
|---|---|
0 | Pas de changement — infrastructure synchronisée |
1 | Erreur lors du plan |
2 | Changements détectés — drift ou modifications à appliquer |
Quand l’infrastructure est synchronisée :
terraform plan -detailed-exitcodeecho "Exit code: $?"No changes. Your infrastructure matches the configuration.Exit code: 0Quand un drift est détecté :
terraform plan -detailed-exitcodeecho "Exit code: $?" # libvirt_network.legacy will be updated in-place ~ resource "libvirt_network" "legacy" { ~ autostart = false -> true ... }
Plan: 0 to add, 1 to change, 0 to destroy.Exit code: 2Script de surveillance
Section intitulée « Script de surveillance »Vous pouvez intégrer -detailed-exitcode dans un script CI/CD ou un cron pour détecter le drift automatiquement :
#!/bin/bashterraform plan -detailed-exitcode -no-color > /dev/null 2>&1EXIT_CODE=$?
case $EXIT_CODE in 0) echo "OK : infrastructure synchronisée" ;; 1) echo "ERREUR : impossible d'exécuter le plan" exit 1 ;; 2) echo "ALERTE : drift détecté, lancer terraform plan pour les détails" exit 2 ;;esacCe script peut être exécuté périodiquement par un pipeline CI/CD pour vous alerter dès qu’une modification manuelle désynchronise l’infrastructure.
Dépannage
Section intitulée « Dépannage »| Symptôme | Cause probable | Solution |
|---|---|---|
Cannot import non-existent remote object | L’ID fourni ne correspond à aucune ressource existante | Vérifier l’ID exact (UUID, ARN, path) dans la console du provider |
| Plan affiche des changements après import | Le code HCL ne correspond pas exactement à la ressource réelle | Ajuster les attributs du bloc resource ou appliquer pour aligner |
Resource already managed by Terraform | La ressource est déjà dans le state | Vérifier avec terraform state list avant d’importer ; si vous voulez la rattacher autrement, la retirer d’abord explicitement avec terraform state rm |
refresh-only ne détecte rien | La ressource n’a pas été modifiée en dehors de Terraform | Comparer avec terraform state show et l’état réel |
No state file was found | Aucun apply effectué | Lancer terraform apply d’abord pour créer le state |
| Format d’ID inconnu pour l’import | Chaque provider a son propre format | Consulter la doc du provider, section « Import » de chaque ressource |
À retenir
Section intitulée « À retenir »- Le drift est l’écart entre le state et l’infrastructure réelle — causé par des modifications manuelles ou externes
terraform plandétecte le drift,terraform applyle corrige,terraform apply -refresh-onlyl’accepteterraform importrattache une ressource existante au state — le blocresourcedoit exister dans le code avant l’import- Le bloc
import(Terraform >= 1.5) est l’alternative déclarative, traçable en VCS et reproductible en équipe - Le format de l’ID d’import dépend du provider — consultez sa documentation
-detailed-exitcoderetourne0(synchronisé),1(erreur) ou2(drift) — idéal pour la CI/CD