TP 22 : Gérer un state distant et son verrouillage
TP 22 : Gérer un state distant et son verrouillage
Section intitulée « TP 22 : Gérer un state distant et son verrouillage »Objectifs
Section intitulée « Objectifs »À l’issue de ce TP, vous serez capable de :
- expliquer pourquoi le state local est inadapté au travail en équipe ;
- provisionner un bucket S3 dédié au stockage du state (chiffrement, versioning, blocage public) ;
- migrer un state local existant vers un backend distant sans perte ;
- activer le verrouillage natif S3 (
use_lockfile) et observer un conflit de verrou ; - lever un verrou bloqué avec
terraform force-unlock.
Prérequis
Section intitulée « Prérequis »- Terraform
>= 1.11(le verrouillage natif S3 est GA depuis la 1.11 ; il était expérimental en 1.10). - Un compte AWS et la CLI
awsconfigurée (aws sts get-caller-identitydoit répondre). - Deux terminaux ouverts pour simuler la concurrence.
Vérifiez votre version :
terraform versionContexte
Section intitulée « Contexte »L’équipe plateforme d’InfraBank gère jusqu’ici son infrastructure avec un terraform.tfstate posé sur le poste d’un ingénieur. Deux incidents récents (un state écrasé, un fichier perdu au reformatage d’un laptop) imposent de passer à un state distant partagé, chiffré et verrouillé.
Étape 1 : Point de départ en state local
Section intitulée « Étape 1 : Point de départ en state local »Créez un dossier de travail et une configuration minimale qui génère du state sans facturer de ressource réelle.
terraform { required_version = ">= 1.11"
required_providers { random = { source = "hashicorp/random" version = "~> 3.6" } time = { source = "hashicorp/time" version = "~> 0.12" } }}resource "random_pet" "server" { length = 2}
output "server_name" { value = random_pet.server.id}terraform initterraform apply -auto-approvels -l terraform.tfstateLe state est bien un fichier local. C’est ce que nous allons déplacer.
Étape 2 : Bootstrap du bucket de state
Section intitulée « Étape 2 : Bootstrap du bucket de state »Le bucket qui héberge le state ne doit pas se gérer lui-même. On le crée donc dans un dossier séparé (bootstrap/) avec son propre state local.
terraform { required_version = ">= 1.11" required_providers { aws = { source = "hashicorp/aws" version = "~> 5.60" } }}
provider "aws" { region = "eu-west-3"}
resource "aws_s3_bucket" "state" { bucket = "infrabank-tfstate-${random_id.suffix.hex}"}
resource "random_id" "suffix" { byte_length = 4}
resource "aws_s3_bucket_versioning" "state" { bucket = aws_s3_bucket.state.id versioning_configuration { status = "Enabled" }}
resource "aws_s3_bucket_server_side_encryption_configuration" "state" { bucket = aws_s3_bucket.state.id rule { apply_server_side_encryption_by_default { sse_algorithm = "aws:kms" } }}
resource "aws_s3_bucket_public_access_block" "state" { bucket = aws_s3_bucket.state.id block_public_acls = true block_public_policy = true ignore_public_acls = true restrict_public_buckets = true}
output "bucket_name" { value = aws_s3_bucket.state.bucket}cd bootstrapterraform initterraform apply -auto-approveterraform output bucket_name # notez ce nomcd ..Le versioning est indispensable : il permet de récupérer une version antérieure du state en cas de corruption, et il est requis pour un usage sûr du verrou natif.
Étape 3 : Déclarer le backend distant
Section intitulée « Étape 3 : Déclarer le backend distant »Ajoutez le bloc backend dans la configuration principale. Remplacez le nom du bucket par celui obtenu à l’étape 2.
terraform { backend "s3" { bucket = "infrabank-tfstate-XXXXXXXX" key = "plateforme/terraform.tfstate" region = "eu-west-3" encrypt = true use_lockfile = true }}Points importants :
- le bloc
backendn’accepte ni variable ni interpolation : il est lu très tôt, avant l’évaluation des variables. Toutes les valeurs sont littérales. use_lockfile = trueactive le verrouillage natif S3. Terraform crée un objetplateforme/terraform.tfstate.tflockpar écriture conditionnelle (If-None-Match). Plus besoin de table DynamoDB.encrypt = truedemande le chiffrement de l’objet state écrit par Terraform.
Étape 4 : Migrer le state
Section intitulée « Étape 4 : Migrer le state »terraform init -migrate-stateTerraform détecte le changement de backend et propose de copier le state local vers S3. Répondez yes. Vérifiez :
aws s3 ls s3://infrabank-tfstate-XXXXXXXX/plateforme/terraform state listLe terraform.tfstate local est désormais vide (ou remplacé par un pointeur). La source de vérité est dans S3.
Étape 5 : Simuler deux exécutions concurrentes
Section intitulée « Étape 5 : Simuler deux exécutions concurrentes »Pour observer le verrou, il faut une opération qui dure. Ajoutez une temporisation :
resource "time_sleep" "hold_lock" { create_duration = "90s"}Terminal A :
terraform apply -auto-approve# reste 90 s à créer time_sleep.hold_lock ; le verrou est détenuTerminal B (pendant que A tourne) :
terraform planTerminal B échoue avec une erreur de type :
Error: Error acquiring the state lockStatusCode: 412 ... PreconditionFailedLock Info: ID: ... Operation: OperationTypeApply Who: ...@poste-bLe code HTTP 412 PreconditionFailed est l’écriture conditionnelle refusée : l’objet .tflock existe déjà. Ce n’est pas un bug, c’est le verrou qui fait son travail. Quand A termine, l’objet .tflock est supprimé et B peut s’exécuter.
Étape 6 : Lever un verrou bloqué
Section intitulée « Étape 6 : Lever un verrou bloqué »Si un processus meurt en cours de route (Ctrl-C brutal, coupure réseau), le verrou peut rester. Récupérez l’ID affiché dans l’erreur, puis :
terraform force-unlock <LOCK_ID>N’utilisez force-unlock que si vous êtes certain qu’aucune autre exécution n’est en cours : forcer le mauvais verrou ouvre la porte à un écrasement de state.
Vérification
Section intitulée « Vérification »terraform state listrenvoie les ressources depuis S3.- Un objet
.tflockapparaît puis disparaît pendant unapply. - Le terminal B est bien bloqué tant que A détient le verrou.
Nettoyage
Section intitulée « Nettoyage »# Détruire l'infra de démonstrationterraform destroy -auto-approve
# Vider puis détruire le bucket (dans bootstrap/)aws s3 rm s3://infrabank-tfstate-XXXXXXXX --recursivecd bootstrapterraform destroy -auto-approve