Terraform — State avancé
| Fiche express | |
|---|---|
| Type | Manipulation avancée du state Terraform |
| Inspection | terraform state list / show
|
| Réorganisation | terraform state mv / rm, bloc moved
|
| Adoption | terraform import, bloc import (1.5+, à vérifier)
|
| Voir aussi | Terraform — Concepts fondamentaux · Terraform — Boucles et méta-arguments |
Cette page suppose connues les bases du state (backend, verrouillage, drift), couvertes dans Terraform — Concepts fondamentaux. Elle traite des opérations avancées : inspecter et réorganiser le state, adopter une ressource créée hors Terraform, refactorer du code sans destruction/recréation, et découper un state monolithique.
Inspecter le state
# Lister toutes les ressources suivies
terraform state list
# Détail d'une ressource (attributs tels que connus du state)
terraform state show vsphere_virtual_machine.node[0]
terraform state list accepte un filtre (terraform state list module.rke2_cluster) pour explorer un module en particulier. C'est le premier réflexe avant toute opération de réorganisation, pour connaître l'adresse exacte des ressources en jeu.
Réorganiser le state : mv et rm
terraform state mv
Renomme une ressource dans le state, ou la déplace vers/depuis un module, sans toucher à l'infrastructure réelle. Indispensable après un refactoring du code (renommage d'une ressource, déplacement dans un module) pour éviter que Terraform ne planifie une destruction suivie d'une recréation.
# Renommage simple
terraform state mv vsphere_virtual_machine.node vsphere_virtual_machine.rke2_node
# Déplacement vers un module
terraform state mv vsphere_virtual_machine.node module.rke2_cluster.vsphere_virtual_machine.node
terraform state rm
Retire une ressource du state sans la détruire dans la réalité. La ressource continue d'exister côté provider, mais Terraform cesse de la gérer. Utile pour transférer la gestion d'une ressource vers un autre state, ou l'exclure définitivement de l'IaC.
terraform state rm vsphere_virtual_machine.legacy_node
Ces deux commandes n'éditent le state que localement à la commande (elles passent par le backend configuré, avec verrouillage) — elles ne modifient jamais l'infrastructure elle-même. C'est leur intérêt : corriger la représentation sans effet de bord réel.
Bloc moved (refactoring déclaratif)
Depuis Terraform 1.1 (à vérifier), le bloc moved déclare dans le code un renommage ou déplacement, en remplacement de l'appel manuel à terraform state mv. Avantage : le refactoring devient versionné et rejoué automatiquement par quiconque exécute plan/apply, sans commande à exécuter à la main sur chaque environnement/state.
moved {
from = vsphere_virtual_machine.node
to = vsphere_virtual_machine.rke2_node
}
Terraform lit ce bloc au plan suivant, constate que vsphere_virtual_machine.node existe dans le state mais plus dans le code, et associe silencieusement son état à la nouvelle adresse vsphere_virtual_machine.rke2_node — sans destruction/recréation. Le bloc peut rester dans le code au-delà de la migration (il documente l'historique) ou être retiré une fois tous les states migrés.
Fonctionne aussi pour un changement count → for_each, ou un déplacement vers/depuis un module — cas où terraform state mv serait fastidieux à écrire à la main pour de multiples instances.
Import d'une ressource existante
Une ressource créée hors Terraform (console web, script, legacy) peut être adoptée dans le state sans être recréée.
terraform import (commande impérative)
# Le bloc resource doit déjà exister dans le code, vide de tout attribut
resource "vsphere_virtual_machine" "legacy" {
# attributs à compléter après l'import, en s'alignant sur `terraform plan`
}
terraform import vsphere_virtual_machine.legacy vm-1042
Limite connue : l'import ne génère pas automatiquement la configuration HCL correspondante (avant Terraform 1.5, à vérifier) — il faut écrire le bloc resource à la main, puis itérer avec plan jusqu'à ce que le diff soit vide (le code décrit fidèlement l'existant).
Bloc import déclaratif (Terraform 1.5+, à vérifier)
Alternative versionnable, dans le même esprit que moved :
import {
to = vsphere_virtual_machine.legacy
id = "vm-1042"
}
Avec cette syntaxe, terraform plan -generate-config-out=generated.tf peut générer automatiquement un brouillon de configuration HCL à partir de l'état réel de la ressource (fonctionnalité récente, à vérifier selon la version et la couverture du provider) — ce qui réduit nettement le travail manuel par rapport à terraform import seul. Le bloc import, comme moved, est exécuté au plan/apply suivant et peut être retiré une fois l'import effectif.
Découper un state monolithique
Un state unique pour toute l'infrastructure devient vite un goulot d'étranglement : plan lent (toutes les ressources sont évaluées), rayon d'impact large en cas d'erreur, verrouillage qui bloque toute l'équipe pendant un apply. La pratique courante est de découper par périmètre (réseau, cluster, applicatif) en plusieurs states indépendants, chacun avec son propre backend/cycle de vie.
<mermaid> flowchart LR
subgraph S1[state: network]
N[VPC / réseaux]
end
subgraph S2[state: cluster]
C[RKE2 / Rancher]
end
subgraph S3[state: app]
A[Ressources applicatives]
end
S1 -->|terraform_remote_state| S2
S2 -->|terraform_remote_state| S3
</mermaid>
La donnée source de découplage (terraform state mv vers un state cible, ou export/réimport) transfère les ressources déjà existantes vers le nouveau state sans les recréer. Une fois les states séparés, la lecture croisée se fait via la data source terraform_remote_state, qui lit les outputs d'un autre state (en lecture seule, jamais d'écriture croisée) :
data "terraform_remote_state" "network" {
backend = "s3"
config = {
bucket = "tfstate-nexiat"
key = "network/terraform.tfstate"
region = "eu-west-3"
}
}
resource "rancher2_cluster_v2" "rke2" {
# ...
network_id = data.terraform_remote_state.network.outputs.vpc_id
}
Ce découplage impose une discipline : les outputs du state en amont deviennent une interface de fait consommée ailleurs — les renommer ou les supprimer casse silencieusement les states en aval tant qu'ils n'ont pas été mis à jour. C'est le prix du découpage, en échange de blast radius réduit et de plan/apply plus rapides et plus ciblés.