infra / terraform
Resources et attributs
Explication
Ce que vous allez apprendre
- Lire et écrire la syntaxe générale d'un bloc
resource - Référencer un attribut d'une ressource depuis une autre pour créer une dépendance
- Distinguer les arguments fournis par toi des attributs calculés par le cloud
- Créer plusieurs ressources similaires avec
countetfor_each - Protéger une ressource critique avec le bloc
lifecycle
Dans quel contexte ?
Une équipe backend a déjà créé un bucket S3 simple (leçon précédente) ; elle doit maintenant déployer une vraie instance de serveur EC2, lui attacher une adresse IP publique fixe, puis dupliquer ce schéma pour trois serveurs de traitement identiques (worker[0], worker[1], worker[2]).
D'abord, il faut maîtriser la syntaxe de base
Un bloc resource suit toujours la même forme : resource "<type>" "<nom_local>" { ... }. Le type (aws_instance) indique QUEL objet créer, défini par le provider ; le nom local (web) n'existe que dans ta configuration Terraform, pour pouvoir référencer cette ressource ailleurs dans le code.
À l'intérieur des accolades, on distingue deux catégories de valeurs bien différentes : les arguments qu'on fournit nous-mêmes (ami, instance_type) et les attributs calculés par le cloud, connus seulement APRÈS la création (public_ip, id).
| Élément | Qui le fournit | Connu quand |
|---|---|---|
Argument (ami, instance_type) | Toi, dans le code | Avant la création |
Attribut calculé (id, public_ip) | Le cloud, après création | Après apply |
Référence (aws_instance.web.id) | Terraform, via le graphe de dépendances | Résolu automatiquement dans l'ordre |
Prérequis
Il faut avoir déjà écrit et appliqué un premier fichier .tf avec un provider configuré (voir la leçon précédente) pour suivre les exemples de cette leçon.
Une fois une ressource créée, comment en référencer une autre ?
En écrivant aws_instance.web.id dans un autre bloc, Terraform comprend automatiquement qu'il doit créer web AVANT la ressource qui la référence. C'est ce qu'on appelle une dépendance implicite : aucune configuration supplémentaire n'est nécessaire, Terraform déduit l'ordre de création à partir des références présentes dans le code lui-même.
Il reste un problème quand il faut créer PLUSIEURS ressources similaires
Copier-coller trois fois le même bloc resource pour trois workers identiques fonctionne, mais devient vite ingérable dès qu'un paramètre commun doit changer. count résout ça en créant N instances numérotées (worker[0], worker[1], worker[2]), accessibles via count.index dans les attributs.
Piège fréquent
count numérote les ressources par position. Si tu supprimes l'élément du milieu d'une liste utilisée avec count, Terraform décale tous les index suivants et recrée inutilement des ressources qui n'avaient pourtant pas changé. for_each, indexé par CLÉ plutôt que par position, ne souffre pas de ce problème et doit être préféré dès que l'ordre des éléments peut varier.
Maintenant, une question de sécurité : comment protéger une ressource critique d'une suppression accidentelle ?
Le bloc lifecycle répond exactement à ce besoin, avec trois options principales : prevent_destroy bloque tout destroy sur cette ressource précise, create_before_destroy crée le remplaçant avant de supprimer l'ancien (zéro interruption de service), et ignore_changes ignore certains changements faits manuellement en dehors de Terraform.
Bonne pratique
Active systématiquement prevent_destroy = true sur toute ressource dont la perte serait catastrophique (base de données de production, bucket de state Terraform lui-même, vu dans une leçon ultérieure). Un simple terraform destroy lancé par erreur sur le mauvais dossier échoue alors proprement, plutôt que de tout supprimer.
Le piège à connaître avant de continuer
Écrire des valeurs en dur (comme l'ID d'AMI ami-0c55b159cbfafe1f0 utilisé dans cette leçon) fonctionne pour apprendre, mais devient vite fragile : un ID d'AMI change à chaque nouvelle version d'Ubuntu publiée. La prochaine leçon introduit les variables, la première étape pour rendre une configuration Terraform réellement réutilisable et paramétrable.
Commandes & code
Resources et attributs
# Syntaxe générale : resource "<type>" "<nom_local>" { ... }
resource "aws_instance" "web" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t3.micro"
tags = {
Name = "serveur-web"
Environment = "production"
}
}
# Référencer un attribut d'une autre ressource : <type>.<nom_local>.<attribut>
resource "aws_eip" "web_ip" {
instance = aws_instance.web.id # dépendance implicite : Terraform crée web AVANT web_ip
domain = "vpc"
}
# Attributs calculés (connus seulement APRÈS création) vs arguments (fournis par vous)
output "adresse_ip_publique" {
value = aws_instance.web.public_ip # attribut calculé par AWS, connu après apply
}
# meta-arguments disponibles sur TOUTE ressource
resource "aws_instance" "worker" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t3.small"
count = 3 # crée 3 instances : worker[0], worker[1], worker[2]
tags = {
Name = "worker-${count.index}" # index 0, 1, 2 dans le nom
}
}
# for_each : comme count, mais indexé par clé (plus stable si l'ordre change)
resource "aws_instance" "service" {
for_each = toset(["api", "worker", "scheduler"])
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t3.small"
tags = {
Name = "service-${each.key}" # each.key = "api", "worker" ou "scheduler"
}
}
lifecycle_config_example = null # (placeholder pédagogique, retiré ci-dessous)# Le bloc "lifecycle" contrôle le comportement de création/destruction
resource "aws_instance" "critique" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t3.medium"
lifecycle {
prevent_destroy = true # bloque tout "terraform destroy" sur cette ressource
create_before_destroy = true # crée le remplaçant AVANT de détruire l'ancien (zéro downtime)
ignore_changes = [tags] # ignore les changements manuels sur "tags" (faits hors Terraform)
}
}Résumé
countindexe les ressources par nombre entier (0, 1, 2...) ;for_eachles indexe par clé stable, plus robuste aux réordonnancements.- Les dépendances implicites s'expriment en référençant
type.nom.attributd'une autre ressource. lifecycle { prevent_destroy, create_before_destroy, ignore_changes }protège les ressources critiques.
Exercices pratiques
Mission : stabiliser un cluster de workers instable
Objectif : Diagnostiquer un recalcul en cascade causé par `count` et sécuriser une ressource critique contre la suppression accidentelle.
Contexte
Une liste de trois workers (aws_instance.worker avec count = 3) tourne en production. Un développeur supprime worker[1] au milieu de la liste source, puis relance terraform plan : celui-ci annonce que worker[1] doit être modifié ET que worker[2] doit être détruit puis recréé, alors qu'aucun des deux n'a réellement changé de configuration.