Introduction
Le load balancing cloud est un pilier de l'architecture moderne pour garantir la haute disponibilité (HA), la scalabilité horizontale et la résilience des applications. Sur AWS, l'Application Load Balancer (ALB) excelle pour le routage L7 intelligent, les health checks avancés et l'intégration native avec Auto Scaling Groups (ASG).
Ce tutoriel advanced vous guide pas à pas pour implémenter une stack complète avec Terraform : création d'une VPC multi-AZ, subnets publics, ALB avec target groups HTTP/HTTPS, launch template EC2 pour une app Nginx simple, et ASG pour l'auto-scaling. Imaginez comme un orchestre : l'ALB est le chef qui répartit les requêtes vers les musiciens (instances EC2) en temps réel, en évitant les 'mauvais' via health checks.
Pourquoi ce setup ? Il est production-ready, gère >10k req/s, supporte SSL termination et est 100% IaC pour CI/CD. Durée estimée : 30 min. À la fin, vous aurez un LB accessible publiquement, scalable à l'infini. Préparez votre compte AWS ! (142 mots)
Prérequis
- Compte AWS actif avec permissions IAM :
AmazonEC2FullAccess,AmazonVPCFullAccess,AWSElasticLoadBalancingFullAccess,AutoScalingFullAccess. - Terraform CLI v1.5+ installé (télécharger).
- AWS CLI v2 configuré (
aws configure) avec clés IAM admin. - Éditeur de code (VS Code avec extension Terraform recommandée).
- Connaissances avancées en networking AWS (VPC, SG, AZ) et IaC.
Initialiser le projet Terraform
mkdir aws-load-balancer-terraform
cd aws-load-balancer-terraform
git init
echo 'terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.40"
}
}
required_version = ">= 1.5"
}' > versions.tf
terraform initCe script crée le répertoire projet, initialise Git pour versionning, définit les versions Terraform/AWS provider dans versions.tf, et lance terraform init pour télécharger les providers. Cela pose les fondations IaC sans erreurs de compatibilité. Évitez les versions wildcards pour la stabilité en prod.
Configurer les providers et variables
Créez maintenant providers.tf et variables.tf. Le provider AWS cible eu-west-1 pour la compliance EU RGPD. Les variables permettent la personnalisation (CIDR, instance type). Utilisez terraform plan après chaque fichier pour valider.
Providers et variables Terraform
terraform {
backend "s3" {
bucket = "your-terraform-state-bucket"
key = "aws-alb/terraform.tfstate"
region = "eu-west-1"
dynamodb_table = "terraform-locks"
}
}
provider "aws" {
region = var.aws_region
}
data "aws_availability_zones" "available" {
state = "available"
}
variable "aws_region" {
description = "Région AWS"
type = string
default = "eu-west-1"
}
variable "vpc_cidr" {
description = "CIDR du VPC"
type = string
default = "10.0.0.0/16"
}
variable "instance_type" {
description = "Type d'instance EC2"
type = string
default = "t3.micro"
}Ce fichier configure le provider AWS avec backend S3 pour état distant (essentiel en équipe), data source AZ pour multi-zone, et variables par défaut. Le backend DynamoDB gère les locks concurrents. Piège : oubliez le backend local en prod, risque de corruption d'état.
Provisionner la VPC et networking
VPC multi-AZ : 2 subnets publics pour l'ALB (HA). Internet Gateway (IGW) + route table publique. Security Groups : ALB (HTTP/HTTPS inbound), EC2 (ALB + SSH). Exécutez terraform plan pour preview.
Ressources VPC et Security Groups
resource "aws_vpc" "main" {
cidr_block = var.vpc_cidr
tags = {
Name = "alb-vpc"
}
}
resource "aws_subnet" "public" {
count = 2
vpc_id = aws_vpc.main.id
cidr_block = "10.0.${50 + count.index}.0/24"
availability_zone = data.aws_availability_zones.available.names[count.index]
map_public_ip_on_launch = true
tags = {
Name = "public-subnet-${count.index + 1}"
}
}
resource "aws_internet_gateway" "igw" {
vpc_id = aws_vpc.main.id
tags = {
Name = "alb-igw"
}
}
resource "aws_default_route_table" "public" {
default_route_table_id = aws_vpc.main.default_route_table_id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.igw.id
}
}
resource "aws_security_group" "alb_sg" {
name_prefix = "alb-sg-"
vpc_id = aws_vpc.main.id
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 443
to_port = 443
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 = "alb-sg"
}
}
resource "aws_security_group" "ec2_sg" {
name_prefix = "ec2-sg-"
vpc_id = aws_vpc.main.id
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
security_groups = [aws_security_group.alb_sg.id]
}
ingress {
from_port = 22
to_port = 22
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 = "ec2-sg"
}
}Provisionne VPC, 2 subnets publics AZ-isolés, IGW pour accès internet, et SGs restrictifs (least privilege). L'EC2 SG autorise uniquement trafic depuis ALB sur port 80. Piège : sans map_public_ip_on_launch, pas d'IP publique pour targets ; testez avec plan.
Application Load Balancer et Target Group
resource "aws_lb" "main" {
name = "alb-loadbalancer"
internal = false
load_balancer_type = "application"
security_groups = [aws_security_group.alb_sg.id]
subnets = aws_subnet.public[*].id
tags = {
Environment = "prod"
}
}
resource "aws_lb_target_group" "app" {
name = "app-tg"
port = 80
protocol = "HTTP"
vpc_id = aws_vpc.main.id
health_check {
enabled = true
healthy_threshold = 2
interval = 30
matcher = "200"
path = "/"
port = "traffic-port"
protocol = "HTTP"
timeout = 5
unhealthy_threshold = 2
}
}
resource "aws_lb_listener" "http" {
load_balancer_arn = aws_lb.main.arn
port = "80"
protocol = "HTTP"
default_action {
type = "forward"
target_group_arn = aws_lb_target_group.app.arn
}
}
resource "aws_lb_listener" "https" {
load_balancer_arn = aws_lb.main.arn
port = "443"
protocol = "HTTPS"
ssl_policy = "ELBSecurityPolicy-2016-08"
certificate_arn = data.aws_acm_certificate.cert.arn
default_action {
type = "forward"
target_group_arn = aws_lb_target_group.app.arn
}
}Crée ALB internet-facing en subnets publics, target group avec health check strict (/ sur HTTP 200), listeners HTTP/HTTPS (ajustez cert ACM). Forward tout trafic au TG. Piège : health check path doit matcher votre app (Nginx root ok) ; sinon, instances marked unhealthy.
Déployer EC2 via Launch Template et ASG
Launch Template : AMI Amazon Linux 2023, user-data installe Nginx + health endpoint. ASG : 2 instances min, scale sur CPU >70%, attache au TG. terraform apply pour déployer ! Accédez à l'ALB DNS après.
Launch Template, ASG et Outputs
data "aws_ami" "amazon_linux" {
most_recent = true
owners = ["amazon"]
filter {
name = "name"
values = ["al2023-ami-*-x86_64-kernel-*"]
}
}
resource "aws_launch_template" "app" {
name_prefix = "app-lt-"
image_id = data.aws_ami.amazon_linux.id
instance_type = var.instance_type
vpc_security_group_ids = [aws_security_group.ec2_sg.id]
user_data = base64encode(
templatefile("${path.module}/user-data.sh", {
health_path = "/"
})
)
tag_specifications {
resource_type = "instance"
tags = {
Name = "alb-app"
}
}
}
resource "aws_autoscaling_group" "app" {
desired_capacity = 2
max_size = 4
min_size = 2
vpc_zone_identifier = aws_subnet.public[*].id
target_group_arns = [aws_lb_target_group.app.arn]
health_check_grace_period = 300
health_check_type = "ELB"
launch_template {
id = aws_launch_template.app.id
version = "$Latest"
}
tag {
key = "Name"
value = "alb-asg"
propagate_at_launch = true
}
}
resource "aws_autoscaling_policy" "scale_up" {
name = "scale-up"
scaling_adjustment = 2
adjustment_type = "ChangeInCapacity"
cooldown = 300
autoscaling_group_name = aws_autoscaling_group.app.name
}
resource "aws_autoscaling_policy" "scale_down" {
name = "scale-down"
scaling_adjustment = -1
adjustment_type = "ChangeInCapacity"
cooldown = 300
autoscaling_group_name = aws_autoscaling_group.app.name
}
output "alb_dns_name" {
description = "DNS de l'ALB"
value = aws_lb.main.dns_name
}
output "target_group_arn" {
value = aws_lb_target_group.app.arn
}Launch template avec AMI auto-résolue, user-data Nginx (fichier séparé ci-après), ASG multi-AZ avec ELB health, policies scale CPU-based. Outputs pour intégration CI/CD. Piège : grace_period trop court = faux unhealthy ; user-data doit exposer health path.
User-data script pour Nginx
#!/bin/bash
yum update -y
yum install -y nginx
systemctl enable nginx
systemctl start nginx
cat > /usr/share/nginx/html/index.html <<EOF
<!DOCTYPE html>
<html>
<head><title>AWS ALB Test</title></head>
<body>
<h1>Load Balanced by AWS ALB! ✅</h1>
<p>Instance ID: $(curl -s http://169.254.169.254/latest/meta-data/instance-id)</p>
</body>
</html>
EOF
systemctl reload nginxScript user-data bootstrap : update, install Nginx, page custom avec Instance ID pour vérifier routing. Health check sur / renvoie 200. Piège : sans reload, changements non appliqués ; testez localement avec bash user-data.sh.
Appliquer et tester le déploiement
terraform validate
tfenv vars set aws_region eu-west-1 # si tfenv
terraform plan -var="vpc_cidr=10.1.0.0/16"
terraform apply -auto-approve
terraform output alb_dns_name
curl $(terraform output -raw alb_dns_name)
echo 'DNS ALB: $(terraform output -raw alb_dns_name)' > alb-url.txt
# Cleanup
t# erraform destroy -auto-approveValide, planifie (optionnel override vars), applique, output DNS, teste curl (doit montrer HTML Nginx). Cleanup destroy. Piège : sans -var-file, defaults utilisés ; surveillez coûts (~0.025$/h ALB + EC2).
Bonnes pratiques
- Multi-AZ obligatoire : au moins 2 subnets AZ-différents pour 99.99% SLA.
- Health checks stricts : path app-spécifique, threshold 2-3, interval 30s.
- SSL termination ALB : offload HTTPS, cert ACM gratuit/auto-renew.
- Monitoring CloudWatch : alarmes CPU>70%, connexions, latency ; intégrez à Slack.
- IaC avancé : modules Terraform réutilisables, remote state S3 + locks.
Erreurs courantes à éviter
- SG trop permissifs : toujours spécifiez source (ALB ID pour EC2) ; audit avec GuardDuty.
- Pas de grace_period ASG : instances tuées prématurément ; mettez 300s min.
- Health check fail : vérifiez logs Nginx (
/var/log/nginx/error.log) et path matcher (200 seulement). - État Terraform perdu : utilisez backend S3 dès le début, jamais local en prod.
Pour aller plus loin
- Docs officielles : AWS ALB, Terraform AWS.
- Avancé : WAF integration, Lambda targets, EKS Ingress.
- Formations : DevOps AWS & Terraform chez Learni.
- Repo GitHub exemple : fork & contribuez !