infra / terraform
Backend distant : S3 et verrouillage DynamoDB
Explication
Ce que vous allez apprendre
- Créer l'infrastructure du backend lui-même (bucket S3 + table DynamoDB de verrouillage)
- Comprendre pourquoi la clé de verrouillage DynamoDB s'appelle obligatoirement
LockID - Résoudre un lock bloqué anormalement avec
force-unlock, en toute connaissance des risques - Partager les outputs d'un projet Terraform avec un autre via
terraform_remote_state - Protéger le bucket de state avec versioning, chiffrement et permissions strictes
Dans quel contexte ?
L'équipe a compris depuis la leçon sur le state pourquoi un backend distant est indispensable en équipe. Il faut maintenant construire concrètement cette infrastructure de backend elle-même — un problème un peu particulier, puisque Terraform a besoin d'un state pour exister, mais le backend qui doit héberger ce state n'existe pas encore.
D'abord, il faut résoudre ce paradoxe de démarrage
La solution pratique est simple : la configuration qui CRÉE le bucket S3 et la table DynamoDB s'applique elle-même avec un state LOCAL, une seule fois, au tout début du projet. Une fois ce backend créé, tous les AUTRES projets Terraform de l'organisation peuvent s'y connecter comme backend distant.
Cette étape unique fondatrice explique pourquoi de nombreuses organisations gèrent leur "backend du backend" dans un dépôt à part, appliqué manuellement et rarement modifié ensuite.
| Composant AWS | Rôle |
|---|---|
| Bucket S3 | Stocke le fichier terraform.tfstate lui-même |
| Versioning S3 | Permet de restaurer une version antérieure en cas de corruption |
Table DynamoDB (LockID) | Empêche deux apply simultanés de s'exécuter en même temps |
| Chiffrement (SSE-KMS) | Protège le contenu du state au repos, notamment les secrets qu'il contient |
Prérequis
Il faut avoir bien compris pourquoi le state local pose problème en équipe (voir la leçon dédiée au state) pour saisir l'enjeu de chacun des composants mis en place dans cette leçon.
Une fois le bucket créé, pourquoi la table DynamoDB a-t-elle une contrainte de nommage précise ?
Terraform exige que la table de verrouillage possède une clé de hachage nommée EXACTEMENT LockID — ce n'est pas une convention arbitraire de cette leçon, mais une exigence technique du backend S3 lui-même. Sans ce nom exact, le mécanisme de verrouillage ne fonctionne tout simplement pas.
Maintenant que le backend est configuré, comment se comporte-t-il en usage réel ?
Le verrouillage devient automatique et transparent : un terraform apply en cours affiche "Acquiring state lock" et bloque toute exécution concurrente jusqu'à sa propre fin, garantissant qu'un seul changement s'applique à la fois sur le même state.
Piège fréquent
Si un processus Terraform est tué brutalement (Ctrl+C mal géré, crash de la CI), le lock peut rester bloqué indéfiniment alors qu'aucun apply n'est réellement en cours. terraform force-unlock <LOCK_ID> débloque cette situation, mais doit être utilisé avec une extrême précaution : forcer un déverrouillage alors qu'un apply est réellement toujours actif ailleurs peut corrompre le state.
Il reste un dernier cas d'usage puissant : partager des données entre projets Terraform séparés
Bonne pratique
Plutôt que de dupliquer manuellement un ID de sous-réseau d'un projet réseau vers un projet applicatif, data "terraform_remote_state" lit directement les outputs d'un AUTRE projet Terraform, à condition que ce projet expose bien les valeurs nécessaires via des output. Cela crée un couplage propre et explicite entre projets indépendants, sans copier-coller de valeurs qui finiraient par diverger.
Le backend distant maintenant solide, la prochaine leçon aborde l'automatisation complète de ce cycle plan/apply dans un pipeline CI/CD.
Commandes & code
Backend distant : S3 et verrouillage DynamoDB
# Étape 1 : créer l'infrastructure du backend elle-même (bucket S3 + table DynamoDB)
# Attention : cette config initiale est généralement appliquée avec un state LOCAL, une seule fois
resource "aws_s3_bucket" "terraform_state" {
bucket = "mon-org-terraform-state"
lifecycle {
prevent_destroy = true # protège le bucket de state contre une suppression accidentelle
}
}
resource "aws_s3_bucket_versioning" "state_versioning" {
bucket = aws_s3_bucket.terraform_state.id
versioning_configuration {
status = "Enabled" # permet de revenir à une version antérieure du state en cas de corruption
}
}
resource "aws_s3_bucket_server_side_encryption_configuration" "state_encryption" {
bucket = aws_s3_bucket.terraform_state.id
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "aws:kms"
}
}
}
resource "aws_dynamodb_table" "terraform_locks" {
name = "terraform-locks"
billing_mode = "PAY_PER_REQUEST"
hash_key = "LockID" # nom de clé EXIGÉ par Terraform pour le verrouillage
attribute {
name = "LockID"
type = "S"
}
}# Étape 2 : dans CHAQUE projet consommateur, configurer le backend
terraform {
backend "s3" {
bucket = "mon-org-terraform-state"
key = "projets/api/terraform.tfstate"
region = "eu-west-3"
dynamodb_table = "terraform-locks"
encrypt = true
}
}terraform init # bascule vers le backend distant, migre le state si demandé
# Le verrouillage est AUTOMATIQUE : un "apply" en cours empêche un autre "apply" concurrent
terraform apply
# -> "Acquiring state lock. This may take a few moments..."
# Si un lock est bloqué anormalement (process tué brutalement) :
terraform force-unlock <LOCK_ID> # à utiliser avec EXTRÊME précaution# --- Partager des sorties entre projets Terraform via un state distant (remote state data source) ---
data "terraform_remote_state" "reseau" {
backend = "s3"
config = {
bucket = "mon-org-terraform-state"
key = "projets/reseau/terraform.tfstate"
region = "eu-west-3"
}
}
resource "aws_instance" "app" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t3.micro"
subnet_id = data.terraform_remote_state.reseau.outputs.subnet_prive_id # output d'un AUTRE projet
}Résumé
- Un backend S3 + verrouillage DynamoDB (
LockIDen hash_key) est la référence pour le state distant en équipe sur AWS. - Le versioning S3 sur le bucket de state permet de restaurer une version antérieure en cas de corruption.
terraform_remote_statepermet à un projet de consommer les outputs d'un autre projet Terraform indépendant.
Exercices pratiques
Mission : sécuriser le backend fondateur de l'organisation
Objectif : Construire l'infrastructure du backend distant elle-même et raisonner sur le paradoxe de démarrage et les risques du verrouillage.
Contexte
L'équipe veut enfin construire son bucket S3 et sa table DynamoDB de verrouillage, la toute première brique dont dépendront ensuite tous les autres projets Terraform de l'organisation. Un pipeline CI plante en plein apply peu après, et le lock DynamoDB reste bloqué alors qu'aucun apply n'est réellement en cours.