Passer au contenu principal

Organisation (Terraform)

Structurer un projet Terraform

La structure d'un projet Terraform conditionne sa maintenabilité sur le long terme. Un projet flat avec tout dans un seul répertoire fonctionne pour un POC. Pour une infrastructure production avec plusieurs environnements et plusieurs équipes, une structure réfléchie évite les catastrophes.

Structure flat : pour les projets simples

projet-simple/
├── main.tf
├── variables.tf
├── outputs.tf
├── providers.tf
├── versions.tf
├── terraform.tfvars
└── .terraform.lock.hcl

Convient pour : un seul environnement, une petite infrastructure, un POC.

Structure par environnement : la plus courante

infrastructure/
├── modules/
│   ├── vpc/
│   ├── ec2/
│   └── rds/
├── environments/
│   ├── prod/
│   │   ├── main.tf          # appelle les modules
│   │   ├── variables.tf
│   │   ├── outputs.tf
│   │   ├── backend.tf       # config backend S3 prod
│   │   └── terraform.tfvars
│   ├── staging/
│   │   ├── main.tf
│   │   └── terraform.tfvars
│   └── dev/
│       └── ...
└── README.md

Chaque environnement a son propre state, son propre backend, et ses propres accès. C'est la structure recommandée pour les équipes.

backend.tf par environnement

# environments/prod/backend.tf
terraform {
  backend "s3" {
    bucket         = "mon-bucket-tfstate"
    key            = "prod/terraform.tfstate"
    region         = "eu-west-1"
    dynamodb_table = "terraform-locks"
    encrypt        = true
  }
}

.gitignore

# State files — jamais dans Git
*.tfstate
*.tfstate.backup
.terraform/

# Variables avec secrets
*.tfvars
!example.tfvars   # conserver un exemple sans secrets

# Plans binaires
*.tfplan

# Overrides locaux
override.tf
override.tf.json
*_override.tf

example.tfvars : documentation des variables requises

# terraform.tfvars.example — versionné dans Git
# Copier en terraform.tfvars et remplir les valeurs

aws_region    = "eu-west-1"
environment   = "prod"
project_name  = "monprojet"

# Secrets — récupérer depuis le gestionnaire de secrets
db_password   = "CHANGER_MOI"
api_key       = "CHANGER_MOI"

Conventions de nommage

Un naming cohérent simplifie la lecture des plans et des logs :

  • Ressources : snake_case, nom local descriptif (web_server plutôt que ec2)
  • Variables : snake_case, préfixées par le domaine si nécessaire (db_password, vpc_cidr)
  • Modules : snake_case, nom fonctionnel (module "app_vpc")
  • Resources AWS : kebab-case dans les tags Name, préfixé par l'environnement (prod-web-01)