ALB / ELB avec Terraform (provider 5.x)
À la fin de ce tutoriel, vous saurez distinguer CLB, ALB et NLB, déclarer
aws_lb,aws_lb_target_group,aws_lb_listeneret les security groups, comprendre l’exigence ≥ 2 AZ, configurer des health checks, et gérer un lab optionnel enca-central-1— Terraform ≥ 1.9, AWS provider ~> 5.0. Message clé : ALB facturé à l’heure — snippets + plan en priorité ; si apply, destroy immédiat.Niveau : Intermédiaire · Temps estimé : 35–45 min (lecture) / +15–30 min si apply · Versions testées : Terraform 1.16.2 (série ≥ 1.9), AWS provider ~> 5.0 · Dernière vérification : 2026-09-10
Slug proposé :
terraform-alb· Série : Terraform · Remplace / fusionne : #1674 (ELB ancien → ALB moderne)
Prérequis
- Avoir suivi EBS (
terraform-ebs) : lab minimal, tags, destroy obligatoire - Idéalement Workspaces (
terraform-workspaces) et Variables (terraform-variables) - Terraform ≥ 1.9, AWS CLI v2, profil de lab (
aws sts get-caller-identityOK) - Notions VPC / subnets multi-AZ (voir maillage VPC) ; Auto Scaling utile pour enregistrer des cibles saines en prod
Coût estimé : un ALB est facturé à l’heure (+ LCU) — pas Free Tier friendly. Recommandation P2 : validate / plan sans apply, ou apply très court puis destroy immédiat. Aucun secret dans le HCL / tfvars.
Auth sans secrets.
AWS_PROFILE/ SSO uniquement. Jamais d’access_key/secret_keydans le provider. Pas d’ARN ACM hardcodé : lab en HTTP:80 ; HTTPS = variable hors git.
Ce que nous allons construire
Lab terraform alb (ca-central-1) — optionnel / coût horaire
├── versions.tf / providers.tf → TF ≥ 1.9, aws ~> 5.0, region ca-central-1
├── Étapes 1–4 → CLB/ALB/NLB + aws_lb + TG + listener + HC
├── Snippets HCL → SG, subnets ≥ 2 AZ, health_check
├── apply OPTIONNEL → ALB facturé → destroy immédiat
└── Checklist + erreurs + quiz
(Alt : « Terraform ALB : aws_lb, target group, listener, health checks multi-AZ — ca-central-1 ».)
Étape 1 — CLB vs ALB vs NLB (pourquoi ALB en 2026)
Le vocabulaire « ELB » prête encore à confusion : historiquement il désignait le Classic Load Balancer ; aujourd’hui AWS regroupe ALB, NLB et (legacy) CLB sous Elastic Load Balancing. Pour un site ou une API HTTP en 2026, aws_lb de type application est le choix par défaut. Le CLB (aws_elb) ne doit plus apparaître dans un design neuf — le post #1674 est fusionné ici pour cette raison.
Cas réel : une équipe migre une API monolithique vers path-based routing (/api vs /admin). L’ALB route par listener rules vers des target groups distincts, sans multiplier les IP publiques. Un NLB serait surdimensionné (et moins expressif en HTTP) pour ce besoin. Réservez le NLB au TCP brut, aux IP statiques ou à la latence extrême.
Piège prod / lab : un ALB idle reste facturé à l’heure + LCU dès sa création. D’où la consigne P2 : plan d’abord, apply seulement si vous enchaînez un destroy dans la même session.
| Critère | CLB (Classic) | ALB (Application) | NLB (Network) |
|---|---|---|---|
| Couche | L4/L7 legacy | L7 HTTP/HTTPS | L4 TCP/UDP/TLS |
| Terraform | aws_elb (legacy) |
aws_lb type = "application" |
aws_lb type = "network" |
| Routage | Basique | Path / host / headers | IP / port, très haute perf |
| Cibles | Instances | Instance, IP, Lambda, ALB | Instance, IP, ALB |
| Cas 2026 | Éviter | APIs, sites, microservices | Gaming, IoT, TCP brut |
| Coût lab | Horaire | Horaire + LCU | Horaire + LCU |
Pourquoi ALB pour terraform alb en 2026 ?
- Le CLB (
aws_elb) est historique : les nouveaux designs ciblent ALB ou NLB. - La majorité des APIs et sites passent par HTTP/HTTPS → ALB (routage path/host).
- ASG, ECS et EKS documentent surtout
aws_lb+ target groups. - Remplacer #1674 = clarifier le vocabulaire « ELB » vers ALB ELBv2 explicite.
Le NLB reste pertinent (TCP pur, IP statiques, latence) — hors scope de ce lab P2 HTTP. Vous pouvez y revenir après le maillage Autoscaling.
Étape 2 — Ressources : aws_lb, target group, listener, SG
Mémorisez la chaîne plutôt que chaque argument isolé : le listener expose un port ; le target group définit comment sonder et répartir ; le SG ALB filtre l’entrée ; le SG app n’accepte que le SG ALB. Terraform déclare ces objets séparément : un oubli d’attachment ou de règle SG se traduit souvent par des 502/503 « mystérieux » alors que le apply est vert.
| Ressource | Rôle |
|---|---|
aws_security_group |
Ingress 80/443 vers l’ALB ; egress vers cibles |
aws_lb |
LB application, subnets ≥ 2 AZ |
aws_lb_target_group |
Pool de cibles + health_check |
aws_lb_listener |
Port public → forward vers le TG |
Chaîne : Client → Listener (SG ALB) → Target group → Cibles (SG app).
# versions.tf
terraform {
required_version = ">= 1.9.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
# providers.tf
provider "aws" {
region = "ca-central-1"
# Auth : AWS_PROFILE / SSO — jamais de clés ici
}
# variables.tf
variable "project" {
type = string
description = "Préfixe lab unique (sans secret)."
}
variable "vpc_id" {
type = string
description = "VPC existant (défaut ou lab)."
}
variable "public_subnet_ids" {
type = list(string)
description = "Au moins 2 subnets dans 2 AZ distinctes."
validation {
condition = length(var.public_subnet_ids) >= 2
error_message = "Un ALB exige au moins deux subnets (deux AZ)."
}
}
Étape 3 — Subnets ≥ 2 AZ + security groups
L’exigence multi-AZ n’est pas cosmétique : l’API AWS refuse un ALB sur une seule AZ. Deux subnets dans la même AZ échouent aussi. En ca-central-1, prenez explicitement 1a et 1b (ou les IDs renvoyés par votre VPC lab). enable_deletion_protection = false en lab évite un destroy bloqué ; en prod, activez-le pour les LB critiques.
Ouvrir 0.0.0.0/0 sur le port 80 est acceptable pour un lab HTTP court. En prod, restreignez (CloudFront, préfixes connus) et basculez HTTPS avec un certificat ACM dans la même Region que l’ALB.
Un ALB refuse un seul subnet ou deux subnets dans la même AZ. En ca-central-1 : ca-central-1a et ca-central-1b.
# main.tf — SG + ALB (apply optionnel — coût horaire)
resource "aws_security_group" "alb" {
name_prefix = "${var.project}-alb-"
description = "Lab ALB ingress HTTP"
vpc_id = var.vpc_id
ingress {
description = "HTTP from Internet (lab only)"
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "${var.project}-alb-sg"
ManagedBy = "terraform"
Lab = "terraform-alb"
}
}
resource "aws_lb" "app" {
name = "${var.project}-alb"
internal = false
load_balancer_type = "application"
security_groups = [aws_security_group.alb.id]
subnets = var.public_subnet_ids
enable_deletion_protection = false # lab : sinon destroy bloqué
tags = {
Name = "${var.project}-alb"
ManagedBy = "terraform"
Lab = "terraform-alb"
Region = "ca-central-1"
}
}
Points durs à retenir :
subnets: liste ≥ 2 IDs d’AZ différentes — sinon erreur API au plan/apply.load_balancer_type = "application": c’est l’ALB (pas le NLB).enable_deletion_protection = falseen lab : sinondestroybloqué.- SG ALB ≠ SG des instances : en prod, ouvrez le port applicatif depuis le SG ALB seulement.
nameALB : longueur et charset limités — gardez un préfixeprojectcourt.
Sans cibles attachées, l’ALB reste « idle » mais facturé dès la création. D’où le mode plan-only recommandé.
Étape 4 — Health checks + target group + listener
Un health check trop strict (path 404, matcher 200 alors que l’app renvoie 204, intervalle agressif) marque toutes les cibles unhealthy : l’ALB répond 503. Alignez path, port et code avec l’application avant d’accuser Terraform. Derrière un ASG, préférez l’enregistrement via target_group_arns / attachment ASG plutôt que des attachments d’instances figées.
Pour HTTPS, stockez certificate_arn en variable hors dépôt public. Ce lab reste en HTTP:80 pour limiter certificats, DNS et coûts annexes — ce n’est pas un modèle de prod final.
Le health check décide si une cible reçoit du trafic. Mauvaise config = 502/503.
resource "aws_lb_target_group" "http" {
name = "${var.project}-tg-http"
port = 80
protocol = "HTTP"
vpc_id = var.vpc_id
target_type = "instance" # ou "ip" / "lambda"
health_check {
enabled = true
path = "/health"
protocol = "HTTP"
matcher = "200"
interval = 30
timeout = 5
healthy_threshold = 2
unhealthy_threshold = 3
}
tags = { Lab = "terraform-alb" }
}
resource "aws_lb_listener" "http" {
load_balancer_arn = aws_lb.app.arn
port = 80
protocol = "HTTP"
default_action {
type = "forward"
target_group_arn = aws_lb_target_group.http.arn
}
}
# CONCEPTUEL — nécessite une EC2 / ASG
# resource "aws_lb_target_group_attachment" "demo" {
# target_group_arn = aws_lb_target_group.http.arn
# target_id = aws_instance.app.id
# port = 80
# }
output "alb_dns_name" {
description = "DNS public de l’ALB (si apply)."
value = aws_lb.app.dns_name
}
| Paramètre HC | Conseil |
|---|---|
path |
Léger (/health, /) |
matcher |
200 ou 200-399 |
| App | Doit répondre sur le port du TG |
| Prod ASG | target_group_arns / attachment ASG |
En prod, ajoutez un listener HTTPS:443 avec certificate_arn (ACM même Region ca-central-1) et une règle de redirection 80→443. Pour le lab P2 : restez en HTTP afin d’éviter certificat, DNS et coûts annexes. Stockez tout ARN sensible en variable / SSM Parameter Store — jamais en clair dans un dépôt public.
Étape 5 — Lab optionnel ca-central-1 + destroy
Le mode A (validate/plan) prouve que le graphe compile sans créer de LB facturé. Le mode B n’a de sens que si vous regardez réellement le DNS ALB puis détruisez. Gardez le filet CLI elbv2 describe-load-balancers : un LB orphelin hors state Terraform continue de facturer.
Mode A — Recommandé : validate / plan (sans coût ALB)
mkdir -p ~/terraform-alb-lab && cd ~/terraform-alb-lab
# Collez versions.tf, providers.tf, variables.tf, main.tf (étapes 2–4)
export AWS_PROFILE=lab
export AWS_REGION=ca-central-1
PROJECT="votreprenom20260910"
VPC_ID=$(aws ec2 describe-vpcs --filters Name=isDefault,Values=true
--query 'Vpcs[0].VpcId' --output text --region ca-central-1)
# Deux subnet IDs d’AZ distinctes → liste HCL ["subnet-aaa","subnet-bbb"]
terraform init && terraform fmt && terraform validate
terraform plan
-var="project=${PROJECT}"
-var="vpc_id=${VPC_ID}"
-var='public_subnet_ids=["subnet-AAA","subnet-BBB"]'
# STOP ici pour éviter le coût horaire ALB
Mode B — Apply minimal puis destroy immédiat
Uniquement si vous acceptez quelques minutes de facturation ALB :
terraform apply -auto-approve
-var="project=${PROJECT}"
-var="vpc_id=${VPC_ID}"
-var='public_subnet_ids=["subnet-AAA","subnet-BBB"]'
terraform output
# Destroy IMMÉDIAT — ne laissez pas l’ALB « pour plus tard »
terraform destroy -auto-approve
-var="project=${PROJECT}"
-var="vpc_id=${VPC_ID}"
-var='public_subnet_ids=["subnet-AAA","subnet-BBB"]'
cd ~ && rm -rf ~/terraform-alb-lab
aws elbv2 describe-load-balancers --region ca-central-1
--query "LoadBalancers[?contains(LoadBalancerName, '${PROJECT}')]"
# Attendu : []
Étape 6 — Checklist
Avant de passer au tuto IAM ou Autoscaling, confirmez mentalement : type application, ≥ 2 AZ, TG + listener + HC cohérents, SG séparés, aucun ARN sensible en clair, destroy prévu. Cette checklist évite les « ALB de démo » oubliés le week-end.
- Distinguer CLB / ALB / NLB — ALB pour HTTP 2026.
- Déclarer
aws_lbapplication + ≥ 2 subnets / AZ. - Coupler TG + health_check + listener.
- Séparer SG ALB / SG cibles ; tags
Lab=terraform-alb. - Region
ca-central-1, TF ≥ 1.9, provider~> 5.0. - Aucun secret / cert ARN en clair.
- Plan ou destroy immédiat — pas d’ALB idle.
Nettoyage
cd ~/terraform-alb-lab
terraform destroy -auto-approve
-var="project=${PROJECT}"
-var="vpc_id=${VPC_ID}"
-var='public_subnet_ids=["subnet-AAA","subnet-BBB"]'
cd ~ && rm -rf ~/terraform-alb-lab
# Filet : aws elbv2 describe-load-balancers --region ca-central-1
# + SG tagués Lab=terraform-alb
Erreurs fréquentes
| Symptôme | Cause | Correction |
|---|---|---|
| Need at least two subnets / AZ | 1 subnet ou 2 dans même AZ | 2 subnets AZ distinctes (1a+1b) |
| Destroy refusé | enable_deletion_protection = true |
false en lab, puis destroy |
Cibles unhealthy |
Path/port/SG HC incorrects | Aligner path ; SG ALB → cibles |
| 503 | Aucune cible / toutes unhealthy | Attachment EC2/ASG ou revoir HC |
| HTTPS sans certificat | certificate_arn manquant |
ACM ca-central-1 ; lab = HTTP:80 |
aws_elb vs aws_lb |
Docs #1674 / CLB | Migrer vers aws_lb application |
| Facture surprise | ALB laissé après lab | Destroy + vérif CLI |
| Name invalide / trop long | Préfixe excessif | ≤ 32 car., charset ALB |
| Listener rules conflict | Plusieurs default_action / priorités | Une default_action claire ; rules numérotées |
|---|---|---|
TG instance vs ip |
Mauvaise target_type pour Fargate/ECS | ip pour awsvpc ; instance pour EC2 classique |
| Cross-zone désactivé sans le savoir | Attribut LB / TG | Vérifier cross-zone selon besoin de répartition |
Quiz (3 questions)
1. Pour une API HTTP avec Terraform en 2026, quelle ressource ?
- A.
aws_elb(CLB) - B.
aws_lbload_balancer_type = "application" - C. NLB obligatoire pour tout HTTP
2. Combien de subnets / AZ minimum pour un ALB ?
- A. Un subnet suffit
- B. Au moins deux subnets dans deux AZ
- C. Quatre AZ obligatoires en ca-central-1
3. Après un lab terraform alb, action critique ?
- A. Laisser l’ALB jusqu’au lendemain
- B.
terraform destroyimmédiat + vérif CLI - C. Activer deletion protection et oublier le state
4. Pourquoi séparer SG ALB et SG des cibles ?
- A. Obligation de nommage
- B. Least privilege : l’app n’écoute que depuis l’ALB
- C. Réduit le prix LCU
5. Un ALB sans cibles saines renvoie souvent ?
- A. 200 systématique
- B. 5xx / 503 côté client
- C. Une redirection ACM automatique
Réponses : 1‑B · 2‑B · 3‑B · 4‑B · 5‑B
FAQ
Slug live terraform-elb vs fichier terraform-alb ? Le contenu canonique P2 parle ALB moderne (aws_lb). L’ancien libellé ELB est conservé pour le SEO/menu live, mais le HCL cible ELBv2 application — pas aws_elb.
Faut-il un ALB pour un seul conteneur de lab ? Souvent non. L’ALB brille dès que vous voulez HA multi-AZ, host/path routing ou un front unique devant un ASG. Pour un smoke test unique, une IP/DNS d’instance peut suffire (hors objectifs de ce tuto).
Quand passer au NLB ? TCP/UDP pur, perf extrême, IP statiques, ou intégration PrivateLink — pas pour remplacer un simple reverse proxy HTTP.
Pour aller plus loin
- Doc :
aws_lb,aws_lb_target_group,aws_lb_listener, ELB pricing - Sur ce site : série AWS ALB / équilibrage de charge, Auto Scaling + Launch Template ; suite immédiate Terraform IAM (
terraform-iam)
Maillage série Terraform (P2)
| ← Précédent | EBS (terraform-ebs) |
| → Suivant | IAM (terraform-iam) |
| Aussi | VPC (aws-vpc-sous-reseaux-igw) · Autoscaling (aws-auto-scaling-launch-template) · ALB AWS (aws-alb-equilibrage-charge) |
| Carte | Overview · Install · Workflow · Blocks · Providers · Variables · Locals · State · Modules · Workspaces · Labs AWS |
Retour parcours Terraform — hub de la série et leçons sœurs.



