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
| Fonction | Description |
|---|---|
| Mapping | Lie les ressources config aux ressources réelles |
| Métadonnées | Stocke les dépendances entre ressources |
| Performance | Cache pour éviter les requêtes API |
| Synchronisation | Source 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
- Configurez un backend S3 avec DynamoDB
- Créez des workspaces pour dev et prod
- Importez une ressource existante
- Pratiquez les commandes state mv et rm