Aller au contenu principal

State Management


Objectifs du chapitre

  • Comprendre le rôle du state
  • Configurer un backend distant
  • Manipuler le state
  • Gérer le state en équipe

1 - Qu'est-ce que le State ?

Définition

Le state est un fichier JSON qui stocke l'état actuel de votre infrastructure.

Rôle du state

FonctionDescription
MappingLie les ressources config aux ressources réelles
MétadonnéesStocke les dépendances entre ressources
PerformanceCache pour éviter les requêtes API
SynchronisationSource de vérité pour l'équipe

Contenu du state

{
"version": 4,
"terraform_version": "1.6.0",
"resources": [
{
"mode": "managed",
"type": "aws_instance",
"name": "web",
"provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
"instances": [
{
"schema_version": 1,
"attributes": {
"id": "i-0123456789abcdef0",
"ami": "ami-12345678",
"instance_type": "t2.micro",
"public_ip": "54.123.45.67"
}
}
]
}
]
}

2 - State local vs distant

State local

Problèmes :

  • Pas de partage en équipe
  • Risque de perte
  • Pas de verrouillage
  • Secrets en clair sur disque

State distant (Remote Backend)

Avantages :

  • Partage en équipe
  • Verrouillage (locking)
  • Chiffrement
  • Versioning
  • Backup

3 - Configuration des backends

S3 Backend (AWS)

terraform {
backend "s3" {
bucket = "my-terraform-state"
key = "prod/terraform.tfstate"
region = "eu-west-1"
encrypt = true
dynamodb_table = "terraform-locks"
}
}

Créer les ressources du backend

# backend-setup/main.tf

# Bucket S3 pour le state
resource "aws_s3_bucket" "terraform_state" {
bucket = "my-terraform-state"
}

resource "aws_s3_bucket_versioning" "terraform_state" {
bucket = aws_s3_bucket.terraform_state.id
versioning_configuration {
status = "Enabled"
}
}

resource "aws_s3_bucket_server_side_encryption_configuration" "terraform_state" {
bucket = aws_s3_bucket.terraform_state.id
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "AES256"
}
}
}

resource "aws_s3_bucket_public_access_block" "terraform_state" {
bucket = aws_s3_bucket.terraform_state.id

block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}

# DynamoDB pour le locking
resource "aws_dynamodb_table" "terraform_locks" {
name = "terraform-locks"
billing_mode = "PAY_PER_REQUEST"
hash_key = "LockID"

attribute {
name = "LockID"
type = "S"
}
}

Azure Backend

terraform {
backend "azurerm" {
resource_group_name = "terraform-state-rg"
storage_account_name = "tfstate12345"
container_name = "tfstate"
key = "prod.terraform.tfstate"
}
}

GCS Backend (Google Cloud)

terraform {
backend "gcs" {
bucket = "my-terraform-state"
prefix = "prod"
}
}

Terraform Cloud Backend

terraform {
cloud {
organization = "my-org"

workspaces {
name = "my-workspace"
}
}
}

4 - Verrouillage du State

Concept

Forcer le déverrouillage

# En cas de crash, le lock peut rester
terraform force-unlock LOCK_ID

# Le LOCK_ID est affiché dans le message d'erreur

5 - Commandes State

Lister les ressources

# Lister toutes les ressources
terraform state list

# Filtrer par type
terraform state list aws_instance.web
terraform state list 'module.vpc.*'

Voir les détails

# Détails d'une ressource
terraform state show aws_instance.web

# Tout le state
terraform show
terraform show -json

Déplacer des ressources

# Renommer une ressource
terraform state mv aws_instance.web aws_instance.web_server

# Déplacer dans un module
terraform state mv aws_instance.web module.compute.aws_instance.web

# Déplacer depuis un module
terraform state mv module.compute.aws_instance.web aws_instance.web

Supprimer du state

# Retirer une ressource du state (sans la détruire dans le cloud)
terraform state rm aws_instance.web

# La ressource existe toujours dans AWS mais Terraform ne la gère plus

Importer des ressources

# Importer une ressource existante
terraform import aws_instance.web i-0123456789abcdef0

# Importer avec module
terraform import module.vpc.aws_vpc.main vpc-12345678

6 - Workspaces

Concept

Les workspaces permettent de gérer plusieurs états avec la même configuration.

Commandes

# Lister les workspaces
terraform workspace list

# Créer un workspace
terraform workspace new staging
terraform workspace new production

# Sélectionner un workspace
terraform workspace select staging

# Afficher le workspace actuel
terraform workspace show

# Supprimer un workspace
terraform workspace delete staging

Utilisation dans la config

# Utiliser le nom du workspace
resource "aws_instance" "web" {
count = terraform.workspace == "production" ? 3 : 1

ami = data.aws_ami.ubuntu.id
instance_type = terraform.workspace == "production" ? "t3.large" : "t3.micro"

tags = {
Name = "web-${terraform.workspace}"
Environment = terraform.workspace
}
}

# Variables par workspace
locals {
env_config = {
default = {
instance_type = "t2.micro"
count = 1
}
staging = {
instance_type = "t2.small"
count = 2
}
production = {
instance_type = "t2.large"
count = 3
}
}

config = local.env_config[terraform.workspace]
}

Backend avec workspaces

# Le workspace est ajouté au chemin du state
terraform {
backend "s3" {
bucket = "my-terraform-state"
key = "myproject/terraform.tfstate"
region = "eu-west-1"

# State path: myproject/env:/staging/terraform.tfstate
workspace_key_prefix = "env:"
}
}

7 - State Refresh

Synchroniser le state

# Refresh le state avec l'état réel
terraform refresh

# Ou via plan
terraform plan -refresh-only

# Appliquer le refresh
terraform apply -refresh-only

Cas d'usage


8 - State et sécurité

Données sensibles

Le state contient des données sensibles :

  • Mots de passe
  • Clés API
  • Adresses IP privées

Bonnes pratiques

# ✅ Chiffrer le state
terraform {
backend "s3" {
bucket = "my-terraform-state"
encrypt = true
}
}

# ✅ Limiter les accès
# Utiliser IAM policies strictes pour le bucket S3

# ✅ Activer le versioning
# Permet de récupérer un state corrompu

# ✅ Ne jamais commiter le state
# .gitignore
*.tfstate
*.tfstate.*

Masquer les outputs sensibles

output "db_password" {
value = random_password.db.result
sensitive = true
}

9 - Récupération et backup

Versioning S3

resource "aws_s3_bucket_versioning" "state" {
bucket = aws_s3_bucket.terraform_state.id
versioning_configuration {
status = "Enabled"
}
}

Récupérer une version précédente

# Lister les versions
aws s3api list-object-versions \
--bucket my-terraform-state \
--prefix prod/terraform.tfstate

# Télécharger une version
aws s3api get-object \
--bucket my-terraform-state \
--key prod/terraform.tfstate \
--version-id XXXXX \
terraform.tfstate.backup

Pull et push du state

# Télécharger le state
terraform state pull > terraform.tfstate.backup

# Pousser un state (DANGER)
terraform state push terraform.tfstate.fixed

10 - Bonnes pratiques

Organisation du state

State par environnement

terraform-state-bucket/
├── networking/
│ ├── dev/terraform.tfstate
│ ├── staging/terraform.tfstate
│ └── prod/terraform.tfstate
├── compute/
│ ├── dev/terraform.tfstate
│ ├── staging/terraform.tfstate
│ └── prod/terraform.tfstate
└── database/
├── dev/terraform.tfstate
├── staging/terraform.tfstate
└── prod/terraform.tfstate

Checklist sécurité

☐ Backend distant configuré
☐ Chiffrement activé
☐ Versioning activé
☐ Locking configuré (DynamoDB)
☐ Accès restreint (IAM)
☐ State jamais dans Git
☐ Outputs sensibles marqués

Résumé

Points clés
  • Le state est la source de vérité
  • Utilisez toujours un backend distant en production
  • Le locking évite les corruptions
  • Chiffrez et versionnez le state
  • Divisez le state pour les gros projets

Exercices pratiques

  1. Configurez un backend S3 avec DynamoDB
  2. Créez des workspaces pour dev et prod
  3. Importez une ressource existante
  4. Pratiquez les commandes state mv et rm

← Variables et Outputs | Modules →