Skip to content

Module 1 — Terraform : premiers pas réellement exécutés

Bonne lecture et bon apprentissage ! Junior TSAFACK – 12/09/2026 Temps de lecture estimé : 10 minutes


Provisionner une ressource cloud à la main (console web, ou script d’appels API) fonctionne pour une ressource, mais devient vite ingérable pour une infrastructure entière : impossible de savoir si l’état actuel correspond encore à ce qui a été prévu, impossible de reproduire l’environnement à l’identique ailleurs. Terraform décrit l’infrastructure voulue dans des fichiers déclaratifs (.tf), calcule la différence avec l’état réel, et applique uniquement cette différence.

Comment ce module a été démontré sans compte cloud

Section titled “Comment ce module a été démontré sans compte cloud”

Provisionner un vrai serveur AWS/Azure/GCP nécessiterait des identifiants cloud actifs — indisponibles dans cet environnement d’exécution. Plutôt que de décrire Terraform en pure théorie, ce module utilise les fournisseurs officiels local et random (aucune API cloud, tout se passe sur le système de fichiers local) pour dérouler un vrai cycle de vie Terraform complet, avec Terraform lui-même exécuté via son image Docker officielle (hashicorp/terraform) — donc sans installation locale du binaire.

main.tf
terraform {
required_providers {
local = { source = "hashicorp/local", version = "~> 2.5" }
random = { source = "hashicorp/random", version = "~> 3.6" }
}
}
variable "environment" {
type = string
default = "staging"
}
variable "replica_count" {
type = number
default = 2
}
resource "random_id" "suffix" {
byte_length = 4
}
resource "local_file" "service_config" {
filename = "${path.module}/generated/service-${var.environment}.conf"
content = <<-EOT
environment = ${var.environment}
replicas = ${var.replica_count}
instance_id = app-${random_id.suffix.hex}
EOT
}
output "instance_id" {
value = "app-${random_id.suffix.hex}"
}

terraform init : télécharger les fournisseurs

Section titled “terraform init : télécharger les fournisseurs”
$ terraform init
Initializing provider plugins...
- Finding hashicorp/random versions matching "~> 3.6"...
- Finding hashicorp/local versions matching "~> 2.5"...
- Installing hashicorp/random v3.9.1...
- Installing hashicorp/local v2.9.1...
Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository...
Terraform has been successfully initialized!

Le fichier .terraform.lock.hcl fige les versions exactes des fournisseurs utilisés — à committer dans le dépôt Git, pour garantir que toute l’équipe (et la CI) utilise les mêmes versions.

terraform plan : prévisualiser avant d’agir

Section titled “terraform plan : prévisualiser avant d’agir”
$ terraform plan
# random_id.suffix will be created
+ resource "random_id" "suffix" {
+ byte_length = 4
+ hex = (known after apply)
}
# local_file.service_config will be created
+ resource "local_file" "service_config" {
+ filename = "./generated/service-staging.conf"
+ content = (known after apply)
}
Plan: 3 to add, 0 to change, 0 to destroy.

plan ne modifie rien — c’est une simulation. C’est la commande à lancer systématiquement en CI sur chaque pull request, pour que la revue humaine voie exactement ce qui va changer avant de fusionner.

$ terraform apply -auto-approve
random_id.suffix: Creating...
random_id.suffix: Creation complete after 0s [id=5J3mIg]
local_file.service_config: Creating...
local_file.service_config: Creation complete after 0s
Apply complete! Resources: 3 added, 0 changed, 0 destroyed.
Outputs:
config_path = "./generated/service-staging.conf"
instance_id = "app-e49de622"

Vérification du fichier réellement généré sur le disque :

$ cat generated/service-staging.conf
environment = staging
replicas = 2
instance_id = app-e49de622

Le concept le plus important : replace vs update in-place

Section titled “Le concept le plus important : replace vs update in-place”

En relançant plan avec des variables différentes (environment = production, replica_count = 5) :

$ terraform plan -var-file=variables-prod.tfvars
# local_file.service_config must be replaced
-/+ resource "local_file" "service_config" {
~ content = <<-EOT
- environment = staging
+ environment = production
- replicas = 2
+ replicas = 5
EOT
~ filename = "./generated/service-staging.conf" -> "./generated/service-production.conf" # forces replacement
}
Plan: 2 to add, 0 to change, 2 to destroy.

Terraform indique must be replaced, pas modifié : parce que le nom de fichier change, la ressource doit être détruite puis recréée (elle ne peut pas être renommée en place). C’est une distinction essentielle en infrastructure réelle : certains changements s’appliquent sans interruption (~ update in-place — par exemple changer une étiquette), d’autres forcent un remplacement (-/+ replace — par exemple changer le type d’une instance sur certains fournisseurs cloud), ce qui peut impliquer une coupure de service. Un ingénieur DevOps doit lire cette ligne dans le plan avant d’appliquer, pas après.

$ terraform destroy -auto-approve
local_file.service_config: Destroying...
local_file.readme: Destroying...
random_id.suffix: Destroying...
Destroy complete! Resources: 3 destroyed.

Vérifié : après destroy, le dossier generated/ est réellement vide. C’est le principe même de l’Infrastructure as Code : l’état voulu est entièrement décrit dans le code, donc rien ne dépend d’une configuration manuelle qu’on oublierait de nettoyer.

Module 2 : AWS CloudFormation — concepts et anatomie d’un template