Exercice 07 : Projet Capstone - Infrastructure Modulaire avec Variables, Modules et State Distant
🎯 Objectifs
À la fin de cet exercice, vous serez capable de :
- ✅ Paramétrer votre configuration avec
variable,local, etoutput - ✅ Utiliser un
data sourcepour récupérer des informations existantes - ✅ Créer un module Terraform réutilisable et l'appeler
- ✅ Configurer un backend S3 (ou local avec migration) pour le state distant
- ✅ Utiliser
terraform.tfvarspour plusieurs environnements
Durée estimée : 45 minutes
Difficulté : ⭐⭐⭐⭐☆ (Avancé)
Prérequis :
- Exercice 06 Terraform complété
- Module Terraform Intermédiaire complété
- (Optionnel) Accès AWS pour le backend S3
📖 Contexte
Votre infrastructure Docker gérée par Terraform s'étend. Vous devez maintenant la rendre modulaire pour la réutiliser sur plusieurs environnements (dev, staging, prod), externaliser le state pour le travail en équipe, et créer un module Docker réutilisable.
📋 Énoncé
Refactorisez l'infrastructure Terraform de l'exercice précédent en utilisant un module, des variables avancées, des locals, des data sources, et un backend distant.
🧭 Déroulement de l'exercice
Tâche 1 : Créer un module Docker réutilisable
Créez un dossier modules/docker-container/ contenant :
main.tf: ressources Docker (image, réseau, conteneur)variables.tf: variables du module (app_name,image_name,http_port,env_vars)outputs.tf: outputs du module (container_id, container_name, app_url)
Indice : Un module est un dossier Terraform avec ses propres fichiers HCL. Il reçoit des inputs via
variableet expose des outputs. On l'appelle avecmodule "nom" { source = "./modules/docker-container" ... }.
Vérification : Le dossier modules/docker-container/ contient main.tf, variables.tf, outputs.tf.
Tâche 2 : Utiliser des locals pour les valeurs calculées
Dans main.tf racine, utilisez locals pour définir :
environment: valeur calculée basée survar.environmentcommon_tags: map avecenvironment,managed_by = "terraform",project = var.app_nameimage_tag: concaténation devar.image_nameetvar.image_version
Indice :
`hcllocals {
environment = lower(var.environment)
image_tag = "${var.image_name}:${var.image_version}"
common_labels = {
environment = local.environment
managed_by = "terraform"
project = var.app_name
}
}
`Les
localsne peuvent pas être surchargés depuis l'extérieur (contrairement aux variables).
Vérification : terraform console → local.image_tag retourne la valeur calculée.
Tâche 3 : Appeler le module pour deux services
Dans main.tf, appelez le module deux fois : une fois pour un service nginx (port 8080) et une fois pour un service httpd (port 8081). Passez des variables différentes à chaque instance.
Indice :
`hclmodule "nginx" {
source = "./modules/docker-container"
app_name = "${var.app_name}-nginx"
image_name = local.image_tag
http_port = 8080
}
>
module "httpd" {
source = "./modules/docker-container"
app_name = "${var.app_name}-httpd"
image_name = "httpd:2.4-alpine"
http_port = 8081
}
`
terraform plandoit afficher les ressources de chaque module.
Vérification : terraform plan affiche 6 to add (2 modules × 3 ressources chacun).
Tâche 4 : Utiliser un data source
Ajoutez un data source pour récupérer l'image Docker alpine:latest existante sur votre machine (si elle est déjà téléchargée), et affichez son ID dans un output.
Indice :
`hcldata "docker_image" "alpine" {
name = "alpine:latest"
}
>
output "alpine_image_id" {
value = data.docker_image.alpine.id
}
`Contrairement à
resource, undata sourcelit une ressource existante sans la créer ni la gérer.
Vérification : Si alpine:latest existe localement (docker pull alpine:latest), terraform refresh puis terraform output alpine_image_id retourne l'ID de l'image.
Tâche 5 : Créer des fichiers tfvars pour deux environnements
Créez dev.tfvars et staging.tfvars avec des valeurs différentes pour app_name, image_version, et http_port. Testez le plan avec chaque fichier.
Indice :
terraform plan -var-file=dev.tfvarsutilise les valeurs du fichier. Cela permet de gérer plusieurs environnements avec la même configuration HCL.
Vérification : terraform plan -var-file=dev.tfvars et terraform plan -var-file=staging.tfvars produisent des plans différents (noms et ports différents).
Tâche 6 : Configurer un backend (local ou S3)
Option A (sans AWS) : Configurez un backend local avec un chemin personnalisé pour le state file. Simulez une migration de state avec terraform init -migrate-state.
Option B (avec AWS) : Configurez un backend s3 pointant vers un bucket S3 existant, avec DynamoDB pour le state locking.
Indice - Option A :
`hclterraform {
backend "local" {
path = "./state/terraform.tfstate"
}
}
`
>
Indice - Option B :
`hclterraform {
backend "s3" {
bucket = "mon-bucket-tf-state"
key = "docker-infra/terraform.tfstate"
region = "eu-west-3"
dynamodb_table = "terraform-locks"
}
}
`
terraform initavec un backend S3 configure automatiquement le locking DynamoDB.
Vérification (Option A) : Après terraform init -migrate-state, le fichier ./state/terraform.tfstate contient l'état de l'infrastructure.
🗂️ Mini-Projet : Infrastructure modulaire multi-environnements
Arborescence finale :
terraform-intermediaire/
├── main.tf
├── variables.tf
├── outputs.tf
├── dev.tfvars
├── staging.tfvars
└── modules/
└── docker-container/
├── main.tf
├── variables.tf
└── outputs.tfWorkflow multi-environnements :
# Développement
terraform apply -var-file=dev.tfvars
# Staging
terraform apply -var-file=staging.tfvars
# Voir les outputs du module
terraform output
terraform output -json | python3 -m json.tool
# Explorer le state
terraform state list
terraform state show module.nginx.docker_container.webCheckpoints de validation :
- Le module
modules/docker-container/a ses 3 fichiers HCL terraform planaffiche les ressources de deux modulesterraform applycrée 2 conteneurs sur des ports différentsterraform plan -var-file=dev.tfvarset-var-file=staging.tfvarsdonnent des plans différents- Le data source Docker fonctionne
terraform state listliste les ressources avec le préfixemodule.nginx.etmodule.httpd.