Malgré une minimisation rigoureuse du blast radius, des états segmentés et des garde-fous dans le cycle de vie, l'incident finit tôt ou tard par se produire : un terraform apply supprime par erreur des ressources en production - ou un terraform destroy affecte plus que prévu.
Que faire lorsque le mal est déjà fait ?
Dans le dernier article de cette série, je vous ai expliqué comment minimiser le blast radius. Dans cette suite, je vous présente des techniques éprouvées pour restaurer des états Terraform corrompus et limiter les dégâts après un incident.
1. Opération à cœur ouvert : State Surgery
Lorsque des ressources existent encore physiquement mais ne sont plus correctement référencées dans le fichier d’état, il ne reste qu'une solution : une intervention chirurgicale en ligne de commande. La technique dite de State Surgery permet de nettoyer manuellement les états Terraform et de les réaligner avec la réalité.
⚠️ Important : Cette méthode requiert une compréhension approfondie de la logique de Terraform et de l’état réel de l’infrastructure. Elle est puissante, mais dangereuse si elle est utilisée à la légère. Créez donc toujours une sauvegarde complète de l’état actuel avant toute modification manuelle !
Vous pouvez sauvegarder l’état actuel avec la commande CLI suivante :
$> terraform state pull > state-backup-$(date +%Y%m%d-%H%M%S).json
Ensuite, vous pouvez supprimer des ressources spécifiques de l’état, sans supprimer la ressource cloud correspondante. Dans cet exemple, la ressource concernée s’appelle aws_instance.problematic_instance :
$> terraform state rm aws_instance.problematic_instance
Ajoutez ensuite une nouvelle ressource dans votre manifeste Terraform pour refléter la ressource restaurée (ici, nous utilisons le nom aws_instance.recovered_instance). Cela peut être une ressource vide ou une copie complète de l’ancienne ressource, selon ce qui a été endommagé.
Vous pouvez ensuite réimporter la ressource concernée à l’aide de son identifiant unique (ici l’exemple i-1234567890abcdef0) sous le nouveau nom :
$> terraform import aws_instance.recovered_instance i-1234567890abcdef0
Alternativement, il est aussi possible de déplacer une ressource existante dans le nouvel état vers une autre position. Cela peut être une autre partie de l’infrastructure ou un autre module Terraform :
$> terraform state mv aws_instance.misplaced_resource aws_instance.correct_scope
2. Reconstruction progressive : Partial Import Strategies
Dans des scénarios complexes - comme après une panne partielle dans un état volumineux - un simple import ne suffit souvent pas. Une restauration structurée et progressive via les Partial Import Configurations (disponibles depuis Terraform 1.5) est alors recommandée.
Déroulement
a. Identifier les ressources concernées à l’aide de -detailed-exitcode
$> terraform plan -detailed-exitcode
La commande terraform plan -detailed-exitcode est une variante spécifique de la commande standard terraform plan. Elle fournit des codes de sortie plus détaillés, ce qui est particulièrement utile dans les pipelines d’automatisation et CI/CD.
Fonctionnement :
- terraform plan affiche normalement les modifications que Terraform appliquerait à votre infrastructure, sans effectuer de changements réels.
- Avec l’option -detailed-exitcode, le comportement des codes de sortie change pour fournir un résultat plus précis :
Code de sortie | Signification |
---|---|
0 | Aucune modification ; l’infrastructure correspond à la configuration. |
1 | Une erreur est survenue (par exemple : erreur de syntaxe, erreur du provider, etc.). |
2 | Des modifications sont prévues ; le plan proposé modifierait l’infrastructure. |
À retenir : Un code de sortie 2 indique des ressources modifiées. Celles-ci nécessitent donc une attention particulière.
Cette fonctionnalité n’est pas toujours mentionnée dans les tutoriels simples, mais elle est largement utilisée dans les équipes qui automatisent leurs workflows Terraform et garantit des changements d’infrastructure robustes et prévisibles.
b. Définir la configuration d’import
Créez maintenant une configuration pour les ressources concernées :
import { to = aws_vpc.recovered_vpc id = "vpc-12345678" } import { to = aws_subnet.recovered_subnet[0] id = "subnet-12345678" }
c. Réaliser un import automatisé et générer la configuration à l’aide de -generate-config-out
La commande terraform plan -generate-config-out=<file> est une fonctionnalité expérimentale introduite avec Terraform v1.5. Elle permet de générer des fichiers de configuration Terraform (au format HCL) pour les ressources définies dans des blocs import, mais qui n’existent pas encore dans votre configuration.
Cette fonctionnalité est particulièrement utile lorsque vous souhaitez importer une infrastructure existante dans Terraform, car elle vous aide à générer automatiquement le code de configuration nécessaire à partir de l’état réel des ressources.
$> terraform plan -generate-config-out=generated.tf
[...] $> terraform apply
Terraform exécute les étapes suivantes :
- Il analyse les blocs import dans la configuration.
- Pour chaque ressource à importer qui ne dispose pas encore d’une configuration, Terraform génère un bloc de ressource HCL avec une sélection d’arguments et de valeurs aussi précise que possible.
- La configuration générée est écrite dans le fichier spécifié (dans cet exemple, generated.tf). Vous devez fournir un chemin de fichier nouveau ; l’utilisation d’un fichier existant entraînera une erreur.
- Après exécution de la commande, Terraform affiche le plan pour l’import de vos ressources et indique où la configuration générée a été enregistrée.
terraform plan -generate-config-out=<file> est un outil puissant et expérimental permettant de générer des configurations Terraform à partir de ressources existantes définies dans des blocs import. Cela facilite la mise sous gestion Terraform d’une infrastructure jusqu’alors non gérée. Vérifiez et ajustez toujours le code généré avant utilisation.
d. Contrôle de réalité : réconciliation de l’état avec -refresh-only et -refresh=true
Lorsque l’état Terraform diverge de la réalité mais que toutes les ressources existent encore, un alignement entre l’état et l’infrastructure réelle est recommandé. Ce processus, appelé Refresh, permet de détecter et parfois même de corriger automatiquement les écarts (drift).
# Actualisation de l’état sans modification $> terraform apply -refresh-only # Comparaison entre état et infrastructure réelle $> terraform plan -refresh=true
La commande terraform plan -refresh=true génère un plan d’exécution pour l’infrastructure gérée par Terraform, avec l’instruction explicite de rafraîchir l’état Terraform avant de générer le plan (refresh).
Détails de comportement
- Par défaut, Terraform met à jour le fichier d’état lors de l’exécution de terraform plan afin de le synchroniser avec l’infrastructure externe réelle avant d’évaluer les modifications à appliquer.
- Avec l’option -refresh=true, vous indiquez explicitement à Terraform de réaliser cette mise à jour. Cela est généralement redondant, car c’est le comportement par défaut, mais cela garantit que toute modification effectuée en dehors de Terraform (par exemple via la console cloud) sera bien détectée et intégrée dans le plan.
- Pendant le rafraîchissement, Terraform interroge toutes les ressources gérées pour mettre à jour le fichier d’état avec leur état actuel. Il compare ensuite cet état mis à jour avec vos fichiers de configuration afin de déterminer quelles actions (ajout, modification, suppression) seraient nécessaires pour aligner l’infrastructure réelle avec la configuration souhaitée.
Comparaison avec -refresh=false
Option | Comportement |
---|---|
-refresh=true | L’état est mis à jour avec l’infrastructure réelle avant la planification (comportement par défaut). |
-refresh=false | La mise à jour de l’état est ignorée, ce qui peut accélérer la planification mais omet les modifications externes. |
e. Détection de dérive en mode script avec -detailed-exitcode
La commande terraform plan -detailed-exitcode permet de générer un plan d’exécution Terraform avec un comportement particulier au niveau des codes de retour (exit codes). Cette technique est idéale pour une utilisation dans des pipelines CI/CD ou comme vérification préalable avant un terraform apply en production.
#!/bin/bash
terraform plan -detailed-exitcode if [ $? -eq 2 ]; then echo "Configuration drift detected – manual review required" fi
Explication des codes de retour
Lorsque vous exécutez terraform plan -detailed-exitcode, Terraform :
- Affiche les actions prévues (ajouts, modifications, suppressions) nécessaires pour aligner votre infrastructure avec la configuration.
- Retourne un code de sortie spécifique selon le résultat du plan :
Code de retour | Signification |
---|---|
0 | Aucune modification ; l’infrastructure correspond à la configuration. |
1 | Une erreur est survenue (ex. : erreur de syntaxe, problème du provider). |
2 | Des modifications sont à appliquer (ajout, modification ou suppression de ressources). |
Conclusion
Comme vous avez pu le constater dans cet article, un terraform destroy qui échappe à tout contrôle malgré toutes les précautions n’est pas une fatalité.
Bien au contraire, à l’ère pré-Terraform, l’impact de telles erreurs était souvent bien pire, car aucun outil intégré ne permettait alors de corriger rapidement les dégâts. On se retrouvait souvent dans une situation du type : “Nous sommes hors ligne pour l’instant, nous allons reconstruire le service manuellement pendant un ou deux jours, puis essayer de comprendre ce qui s’est passé”.
Il est toutefois indéniable que même avec Terraform, la restauration d’un état opérationnel corrompu (State) ou de ressources détruites ou mal configurées reste une tâche techniquement exigeante, qui nécessite une expertise approfondie.
Dans le prochain volet de cette série d’articles, nous verrons quels outils Terraform propose pour détecter et éviter en amont les risques liés à un blast radius trop important.