Terraform est devenu le standard de facto pour gérer l’infrastructure Cloud en tant que code. Mais avec un outil aussi puissant vient une responsabilité proportionnelle. Un terraform apply mal configuré peut détruire une base de données en production, créer des ressources fantômes qui coûtent des milliers d’euros par mois, ou exposer des secrets sensibles dans le state.
Voici les dix erreurs les plus fréquentes, illustrées par des cas réels.
1. Stocker le state en local
Le fichier terraform.tfstate est le cerveau de Terraform. Il mappe vos ressources déclarées aux ressources réelles dans le Cloud. Le stocker localement, c’est courir à la catastrophe : si un collègue fait un apply depuis sa machine pendant que vous faites le vôtre, vous vous retrouvez avec un state corrompu et des ressources orphelines.
Solution : utilisez toujours un backend distant avec verrouillage (locking) S3 + DynamoDB sur AWS, GCS sur GCP, ou Terraform Cloud.
terraform {
backend "s3" {
bucket = "company-tf-state"
key = "prod/network/terraform.tfstate"
region = "eu-west-1"
dynamodb_table = "terraform-locks"
encrypt = true
}
}
2. Ne pas versionner les providers
Sans contrainte de version, terraform init peut récupérer la dernière version d’un provider qui introduit des breaking changes. Le plan du lendemain matin peut détruire et recréer des ressources que vous pensiez stables.
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.30"
}
}
}
La notation ~> 5.30 accepte 5.31, 5.32 mais pas 6.0. Vérrouillez également la version de Terraform lui-même avec required_version = ">= 1.6, < 2.0".
3. Ignorer le terraform plan en CI/CD
Des équipes qui valident des Pull Requests sans afficher le plan Terraform dans la review. Résultat : un destroy non intentionnel passe en revue sans que personne ne le remarque.
Solution : intégrez terraform plan comme commentaire automatique sur chaque PR avec des outils comme Atlantis ou Terraform Cloud. Les reviewers voient exactement ce qui va être créé, modifié ou détruit.
4. Un seul workspace pour tout
Tout dans un seul état Terraform signifie que le rayon d’impact d’une erreur est maximal. Un bug dans la configuration réseau peut impacter votre base de données de production si tout est dans le même apply.
Solution : décomposez votre infrastructure en modules indépendants avec des states séparés réseau, sécurité, bases de données, applications. Utilisez terraform_remote_state pour partager les outputs entre modules.
5. Hardcoder des secrets dans les fichiers .tf
# NE JAMAIS FAIRE
resource "aws_db_instance" "main" {
password = "SuperSecret123!"
}
Ces valeurs finissent dans le state (non chiffré par défaut), dans Git, et dans les logs CI/CD.
Solution : utilisez des variables d’environnement (TF_VAR_db_password), AWS Secrets Manager, HashiCorp Vault, ou le paramètre sensitive = true combiné à un backend chiffré.
6. Utiliser count au lieu de for_each pour les collections
# Dangereux
resource "aws_subnet" "main" {
count = length(var.subnets)
cidr_block = var.subnets[count.index]
}
Si vous supprimez le deuxième élément de la liste, Terraform veut détruire le subnet 2 et recréer le subnet 3 avec l’ancien index. Avec des bases de données ou des instances critiques, c’est catastrophique.
Solution : utilisez for_each avec une map l’identifiant de chaque ressource est alors stable, indépendant de sa position.
7. Ne jamais utiliser prevent_destroy
Les ressources critiques bases de données, buckets S3, clusters Kubernetes méritent une protection explicite contre la destruction accidentelle.
resource "aws_rds_cluster" "main" {
lifecycle {
prevent_destroy = true
}
}
Terraform retournera une erreur si quelqu’un tente de détruire cette ressource, forçant une décision consciente.
8. Ignorer les moved blocks lors des refactors
Renommer un module ou déplacer une ressource sans bloc moved fait croire à Terraform que l’ancienne ressource doit être détruite et la nouvelle créée. En production, cela peut signifier la suppression d’un cluster de base de données.
moved {
from = aws_instance.web
to = module.web_server.aws_instance.main
}
9. Ne pas tester les modules Terraform
Des modules Terraform non testés accumuler de la dette technique silencieusement. Un changement dans un module peut casser des dizaines d’usages.
Solution : utilisez Terratest (Go) ou terraform test (natif depuis Terraform 1.6) pour valider vos modules avec de vraies ressources Cloud dans un environnement éphémère.
10. Oublier le tagging des ressources
Sans tags cohérents, impossible d’allouer les coûts par équipe, de distinguer les ressources de production des ressources de développement, ou d’automatiser le nettoyage des ressources orphelines.
locals {
common_tags = {
Environment = var.environment
Team = var.team
ManagedBy = "terraform"
CostCenter = var.cost_center
}
}
Définissez un module de tags partagé que tous vos modules utilisent c’est la fondation de toute politique FinOps sérieuse.
Conclusion
Terraform est un levier de productivité extraordinaire, à condition de l’utiliser avec rigueur. Ces dix pratiques backend distant, versions verrouillées, séparation des states, protection des ressources critiques forment le socle d’une utilisation responsable en production. La bonne nouvelle : elles s’apprennent une fois et s’appliquent partout.
