Dans le cours précédent, vous avez créé une base managée, un bucket et un service de conteneurs en cliquant dans une console ou en tapant des commandes. Cela fonctionne une fois. Mais comment recréer exactement la même chose pour la préproduction ? Comment savoir qui a modifié une règle de pare-feu, et quand ? L’infrastructure as code (IaC) répond à ces questions : l’infrastructure est décrite dans des fichiers texte, versionnés dans Git, relus en revue de code et appliqués par un outil.
Terraform (et son fork open source OpenTofu, compatible pour l’essentiel de ce cours) est l’outil d’IaC le plus répandu pour piloter plusieurs clouds avec un même langage, le HCL (HashiCorp Configuration Language).
Une approche déclarative
Vous ne décrivez pas les étapes (« crée un bucket, puis active le versionnage »), mais l’état voulu (« il existe un bucket versionné nommé ainsi »). Terraform compare cet état voulu à ce qui existe et calcule lui-même les actions. Relancer la même configuration ne crée pas de doublon : si tout est déjà conforme, il n’y a rien à faire.
Un premier fichier main.tf
terraform {
required_version = ">= 1.6"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = "eu-west-3" # Paris
}
resource "aws_s3_bucket" "exports" {
bucket = "atelier-nova-exports-prod"
tags = {
projet = "exports"
gere_par = "terraform"
}
}
- Le bloc
terraformfixe la version de Terraform et des providers. - Un provider est un plugin qui traduit vos ressources en appels d’API (AWS, Google Cloud, Azure, Scaleway, GitHub…). Il existe aussi des providers utilitaires comme
hashicorp/local(fichiers locaux) ethashicorp/random(valeurs aléatoires), parfaits pour s’entraîner sans compte cloud. - Un bloc
resource "TYPE" "NOM"déclare un objet. Son adresse estTYPE.NOM, iciaws_s3_bucket.exports. Le nom local sert à le référencer ailleurs :aws_s3_bucket.exports.arn.
Le cycle de travail
terraform init # télécharge les providers, crée .terraform/ et .terraform.lock.hcl
terraform plan # calcule ce qui va changer, sans rien modifier
terraform apply # affiche le plan, demande "yes", puis exécute
terraform destroy # supprime toutes les ressources gérées par cette configuration
Le plan est le moment clé. Lisez ses symboles :
| Symbole | Signification |
|---|---|
+ |
création |
~ |
modification sur place |
-/+ |
destruction puis recréation (remplacement) |
- |
destruction |
Il se termine par un résumé du type Plan: 1 to add, 0 to change, 0 to destroy. Un remplacement inattendu (-/+) sur une base de données signifie une perte de données : c’est exactement ce que la lecture du plan doit intercepter. La mention # forces replacement indique quel attribut provoque ce remplacement.
Le fichier .terraform.lock.hcl enregistre les versions exactes des providers : il se versionne dans Git, pour que toute l’équipe et la CI utilisent les mêmes. Le dossier .terraform/ ne se versionne pas.
Le fichier d’état
Après un apply, Terraform écrit terraform.tfstate, un fichier JSON qui associe chaque adresse (aws_s3_bucket.exports) à l’objet réel (son identifiant chez AWS) et à ses attributs. Sans lui, Terraform ne saurait pas que le bucket existe déjà et tenterait de le recréer.
terraform state list # adresses gérées
terraform state show aws_s3_bucket.exports # attributs connus d'une ressource
Trois règles :
- Ne jamais modifier l’état à la main : utilisez les commandes
terraform stateou les blocsmovedetimport(leçon 5). - Ne jamais le versionner dans Git : il contient souvent des valeurs sensibles (mots de passe générés, clés) en clair.
- Ne jamais le perdre : c’est la mémoire de votre infrastructure.
Un backend distant verrouillé
Sur un poste seul, l’état est un fichier local. En équipe, on le place dans un backend distant partagé, chiffré et versionné, avec un verrou : si Alice lance un apply, Bruno ne peut pas en lancer un second en même temps et corrompre l’état.
terraform {
backend "s3" {
bucket = "atelier-nova-tfstate"
key = "plateforme/prod/terraform.tfstate"
region = "eu-west-3"
encrypt = true
use_lockfile = true # verrou natif dans S3 (versions récentes de Terraform)
}
}
Les anciennes configurations utilisent une table DynamoDB pour le verrou (dynamodb_table) ; le backend gcs de Google Cloud verrouille nativement. Le bucket d’état lui-même est créé une fois, à part (souvent par une petite configuration dédiée), avec le versionnage activé pour pouvoir restaurer un état précédent. Après avoir ajouté ou changé un backend, relancez terraform init : Terraform propose de migrer l’état existant.
Exercices
Les solutions et les tests restent sur le serveur. Dans l'espace étudiant, ton code est exécuté et corrigé, et le tuteur donne des indices avant la solution.
Premier cycle complet avec le provider local
Dans un dossier vide
tf-intro, créezmain.tfavec le providerhashicorp/local(version~> 2.5) et une ressourcelocal_filenomméehello, de chemin${path.module}/hello.txtet de contenu"Bonjour Terraform\n". Lancezterraform init,terraform plan,terraform apply(répondezyes), puiscat hello.txtetterraform state list.- `terraform init` se termine par « Terraform has been successfully initialized! » et crée `.terraform.lock.hcl`
- Le plan affiche la ligne exacte `Plan: 1 to add, 0 to change, 0 to destroy.`
- `cat hello.txt` affiche `Bonjour Terraform`
- `terraform state list` affiche exactement `local_file.hello`
- Un fichier `terraform.tfstate` est apparu dans le dossier
Lire un remplacement puis tout détruire
Dans
tf-intro, remplacez le contenu delocal_file.hellopar"Bonjour Terraform, version 2\n". Lancezterraform planet repérez le symbole utilisé, puis appliquez. Enfin lancezterraform destroyet confirmez.- Le plan marque `local_file.hello` avec `-/+` et la mention `# forces replacement` sur `content`
- Le résumé du plan est exactement `Plan: 1 to add, 0 to change, 1 to destroy.`
- Après apply, `cat hello.txt` affiche `Bonjour Terraform, version 2`
- `terraform destroy` se termine par `Destroy complete! Resources: 1 destroyed.` et hello.txt n'existe plus
- `terraform state list` n'affiche plus rien
Que versionner dans Git ?
Parmi ces éléments d’un projet Terraform, lequel doit être versionné dans Git ?
- Le dossier `.terraform/`
- Le fichier `terraform.tfstate`
- Le fichier `.terraform.lock.hcl`
- Le fichier `terraform.tfstate.backup`
Quiz de fin de leçon
Que fait
terraform plan?- Il crée les ressources
- Il calcule et affiche les actions nécessaires sans rien modifier
- Il télécharge les providers
Que signifie le symbole
-/+dans un plan ?- Modification sur place
- Destruction puis recréation de la ressource
- Ressource ignorée
Pourquoi verrouiller l’état dans un backend distant ?
- Pour le rendre plus rapide
- Pour empêcher deux apply simultanés de corrompre l'état
- Pour le chiffrer automatiquement dans Git
La suite du cours
- Variables, outputs, locals et boucles18 min
- Modules : réutiliser et composer18 min
- Gérer plusieurs environnements16 min
- Revue de plan, CI et évolution de l'existant20 min