Auto Scaling Terraform : Launch Template
À la fin de ce tutoriel, vous saurez pourquoi un Auto Scaling Group (ASG) est indispensable en production, pourquoi
aws_launch_configurationest déprécié, et comment déclareraws_launch_template+aws_autoscaling_group(min / desired / max, health check ELB ou EC2) avec un aperçu du lien ALB target group. Regionca-central-1, Terraform ≥ 1.9, AWS provider ~> 5.0. Message clé : terraform autoscaling moderne = Launch Template uniquement ; lab plan-only ou destroy immédiat (EC2 facturé).Niveau : Intermédiaire · Temps estimé : 40–50 min (lecture) / +15–25 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-autoscaling· Série : Terraform · Remplace : #1719 — INTERDITaws_launch_configuration(déprécié) ; utiliseraws_launch_template+aws_autoscaling_group
Prérequis
- VPC (
terraform-vpc) : subnets ≥ 2 AZ, SG, outputs publics / privés - Idéalement ALB (
terraform-alb) : target group + health checks ; IAM (terraform-iam) : instance profile / rôle EC2 - Terraform ≥ 1.9, AWS CLI v2, profil lab (
aws sts get-caller-identityOK) - Notions EC2 / AMI / user-data (
aws-ec2-ami-user-data,aws-auto-scaling-launch-template)
Coût estimé : chaque instance ASG = EC2 à l’heure (+ EBS). Recommandation P2 : validate / plan sans apply, ou apply très court (desired=1, t3.micro) puis destroy immédiat. Aucun secret dans le HCL / tfvars.
Auth sans secrets.
AWS_PROFILE/ SSO uniquement — jamais de clés dans le provider. Pas de mot de passe, clé SSH privée ouuser_dataavec secrets en clair.
Ce que nous allons construire
Lab terraform autoscaling (ca-central-1) — plan-only ou destroy immédiat
├── versions.tf / providers.tf → TF ≥ 1.9, aws ~> 5.0, region ca-central-1
├── Étape LT vs LC → INTERDIT aws_launch_configuration
├── aws_launch_template → AMI data, instance_type, SG, user_data
├── aws_autoscaling_group → min/desired/max, VPC zone, health_check
├── Aperçu ALB TG → target_group_arns (lien terraform-alb)
└── Lab plan / destroy · checklist · quiz
(Alt : « Terraform autoscaling : aws_launch_template + aws_autoscaling_group, min/desired/max, health check ELB — ca-central-1 ».)
Ce guide remplace le post WordPress #1719. Focus : terraform autoscaling avec Launch Template (provider 5.x), discipline coûts EC2, et pont vers ALB / Route 53.
Étape 1 — Pourquoi un Auto Scaling Group
En production, une seule EC2 derrière un DNS est un point de défaillance : maintenance AZ, kernel panic, ou simple pic de trafic saturent le service. L’Auto Scaling Group ne « scale » pas seulement : il maintient une capacité et remplace les instances déclarées unhealthy. Terraform décrit cette intention (min / desired / max) au lieu de cliquer dans la console.
Cas réel : une API de facturation reçoit un pic le 1er du mois. Sans ASG, vous surdimensionnez 24×7. Avec ASG + politiques (hors scope de ce lab), vous montez desired puis redescendez. Même en lab sans politiques de scaling, le groupe prépare le terrain pour l’ALB : les cibles apparaissent et disparaissent sans réécrire le listener.
Piège prod : laisser desired_capacity élevé après un test de charge. Chaque instance facture compute + EBS jusqu’au destroy ou à la politique de scale-in. Taguez Lab / Owner et alarmez Billing.
Une instance EC2 seule est un SPOF (panne AZ, pic de charge). Un ASG maintient une flotte à capacité cible et remplace les instances unhealthy.
| Besoin | Sans ASG | Avec ASG |
|---|---|---|
| Haute dispo multi-AZ | Manuelle, fragile | Subnets ≥ 2 AZ, remplacement auto |
| Capacité | count figé |
min / desired / max |
| Health | Surveillance manuelle | EC2 ou ELB health check |
| Déploiement | Recréer l’instance | Nouveau Launch Template + refresh |
| Coût lab | 1 instance oubliée | Même risque × N — destroy obligatoire |
Règle P2 : l’ASG orchestre des instances saines derrière un TG. Chaîne : VPC multi-AZ → LT → ASG → (optionnel) ALB.
Étape 2 — Launch Template vs Launch Configuration (déprécié)
Les Launch Configurations appartiennent à l’ancienne génération Auto Scaling. AWS les a dépréciées : pas de versioning utile, support Spot/Mixed limité, et le provider Terraform 5.x oriente clairement vers aws_launch_template. Si vous ouvrez un vieux module ou le post #1719, migrez avant d’ajouter des features.
Le Launch Template versionné permet un déploiement progressif : vous publiez une nouvelle version AMI / user_data, puis un instance refresh de l’ASG. C’est le socle des rolling updates modernes — impossible proprement avec une LC immuable à recréer entièrement.
| Critère | Launch Configuration | Launch Template |
|---|---|---|
| Ressource TF | aws_launch_configuration |
aws_launch_template |
| Statut AWS | Déprécié | Recommandé / actuel |
| Versioning | Non (immuable, à recréer) | Versions LT ($Latest, $Default, numéro) |
| Spot / Mixed Instances | Limité | Oui (mixed_instances_policy) |
| Tags instance | Partiels | tag_specifications riches |
| Série P2 | INTERDIT | Obligatoire |
Pourquoi interdire aws_launch_configuration : dépréciation AWS, pas de versioning utile, provider 5.x pousse aws_launch_template + aws_autoscaling_group, et #1719 doit être remplacé sans LC.
Message clé SEO : terraform autoscaling 2026 = Launch Template uniquement.
Étape 3 — Provider + aws_launch_template
La data source AMI évite de copier un ami-… d’une Region à l’autre. En ca-central-1, un filtre Amazon Linux 2023 + most_recent suffit pour le lab. Le user_data reste minimal et sans secrets : mots de passe, jetons CI ou clés privées n’ont rien à faire en clair dans le state.
En prod, branchez un instance profile IAM (terraform-iam) pour SSM Session Manager : plus besoin d’ouvrir SSH 22 depuis Internet. Les tag_specifications propagent Lab sur les instances lancées — indispensable pour le filet CLI de nettoyage.
# versions.tf + providers.tf
terraform {
required_version = ">= 1.9.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = "ca-central-1" # AWS_PROFILE / SSO — jamais de clés
}
variable "project" { type = string }
variable "vpc_id" { type = string }
variable "private_subnet_ids" {
type = list(string) # ≥ 2 AZ — sorties terraform-vpc
}
variable "app_sg_id" { type = string }
variable "instance_type" {
type = string
default = "t3.micro" # lab : petit type
}
variable "desired_capacity" {
type = number
default = 1 # lab : 1 ; prod souvent ≥ 2
}
data "aws_ami" "amazon_linux" {
most_recent = true
owners = ["amazon"]
filter {
name = "name"
values = ["al2023-ami-*-x86_64"]
}
}
resource "aws_launch_template" "app" {
name_prefix = "${var.project}-app-"
image_id = data.aws_ami.amazon_linux.id
instance_type = var.instance_type
vpc_security_group_ids = [var.app_sg_id]
# Lab : user_data minimal (pas de secrets)
user_data = base64encode(<<-EOT
#!/bin/bash
echo "ok" > /usr/share/nginx/html/health.txt || true
EOT
)
tag_specifications {
resource_type = "instance"
tags = {
Name = "${var.project}-asg-instance"
Lab = "terraform-autoscaling"
}
}
tags = {
Name = "${var.project}-lt"
Lab = "terraform-autoscaling"
Region = "ca-central-1"
}
}
Points durs : data.aws_ami, name_prefix, user_data base64 sans secrets, tags Lab=terraform-autoscaling. Instance profile IAM : voir terraform-iam.
Étape 4 — aws_autoscaling_group : min / desired / max + health check
vpc_zone_identifier doit lister des subnets ≥ 2 AZ : sinon votre « HA » tient sur une seule salle. En lab, min_size = 0 permet de redescendre à zéro après test ; en prod, un min ≥ 2 (ou ≥ 1 multi-AZ selon le SLA) évite de servir à froid.
Le passage EC2 → ELB change la définition de « healthy » : l’ASG interroge le target group. Si votre application met 90 s à démarrer et que le grace period est à 30 s, vous obtiendrez une boucle de remplacements. Augmentez le grace period ou corrigez le chemin de health check avant de blâmer Terraform.
resource "aws_autoscaling_group" "app" {
name = "${var.project}-asg"
vpc_zone_identifier = var.private_subnet_ids # ≥ 2 AZ
min_size = 0
desired_capacity = var.desired_capacity
max_size = 2
health_check_type = "EC2" # lab ; prod derrière ALB → "ELB"
health_check_grace_period = 120
launch_template {
id = aws_launch_template.app.id
version = "$Latest"
}
tag {
key = "Name"
value = "${var.project}-asg"
propagate_at_launch = true
}
tag {
key = "Lab"
value = "terraform-autoscaling"
propagate_at_launch = true
}
lifecycle {
create_before_destroy = true
}
}
# INTERDIT en série P2 (déprécié) :
# resource "aws_launch_configuration" "legacy" { ... }
| Paramètre | Rôle lab P2 | Prod typique |
|---|---|---|
min_size |
0 (économie) |
≥ 2 (HA) |
desired_capacity |
1 |
Charge nominale |
max_size |
2 (plafond) |
Selon budget + alarmes |
health_check_type |
EC2 |
ELB si ALB + TG |
vpc_zone_identifier |
Subnets privés VPC | Multi-AZ obligatoires |
EC2 vs ELB : EC2 = status checks (lab sans ALB). ELB = santé du target group — requis derrière un ALB. Avec ELB, augmentez health_check_grace_period pour éviter les remplacements en boucle au boot.
Étape 5 — Lien ALB target group (aperçu)
Ne créez pas un second load balancer dans ce tuto : réutilisez le TG du guide ALB. L’attachement peut se faire via target_group_arns sur l’ASG ou aws_autoscaling_attachment. L’important est la cohérence SG : le port applicatif n’accepte que le SG de l’ALB, pas 0.0.0.0/0.
En prod, l’ALB (terraform-alb) reçoit le trafic ; le target group enregistre les instances de l’ASG.
# Aperçu — TG déjà créé dans terraform-alb (ne dupliquez pas le LB ici)
# variable "target_group_arn" { type = string }
# Dans aws_autoscaling_group.app, ajoutez :
# target_group_arns = [var.target_group_arn]
# health_check_type = "ELB"
#
# Alternative moderne (souvent préférée) :
# resource "aws_autoscaling_attachment" "app_tg" {
# autoscaling_group_name = aws_autoscaling_group.app.name
# lb_target_group_arn = var.target_group_arn
# }
Chaîne : Client → Listener → TG → ASG (LT). SG app ← SG ALB seulement. Route 53 pointera vers l’ALB, pas l’ASG.
Étape 6 — Lab : plan-only ou destroy immédiat
Le mode plan-only suffit à valider LT + ASG sans facturer d’EC2. Si vous appliquez, gardez t3.micro et desired=1, chronométrez le destroy, puis vérifiez qu’aucune instance Lab=terraform-autoscaling ne reste running. Un ASG « vide » avec desired=0 peut encore exister : détruisez le groupe lui-même pour éviter les surprises lors d’un prochain scale-out manuel.
Mode A — Recommandé : validate / plan (quasi 0 €)
mkdir -p ~/terraform-asg-lab && cd ~/terraform-asg-lab
# Collez versions.tf, providers.tf, le LT + ASG (étapes 3–4)
# Récupérez vpc_id / private_subnet_ids / app_sg_id depuis terraform-vpc
export AWS_PROFILE=lab AWS_REGION=ca-central-1
PROJECT="votreprenom20260910"
terraform init && terraform fmt && terraform validate
terraform plan
-var="project=${PROJECT}"
-var="vpc_id=${VPC_ID}"
-var='private_subnet_ids=["subnet-AAA","subnet-BBB"]'
-var="app_sg_id=${APP_SG_ID}"
-var="desired_capacity=1"
# Attendu : 1 LT + 1 ASG — STOP ici en mode plan-only
Mode B — Apply minimal puis destroy immédiat
terraform apply -auto-approve
-var="project=${PROJECT}"
-var="vpc_id=${VPC_ID}"
-var='private_subnet_ids=["subnet-AAA","subnet-BBB"]'
-var="app_sg_id=${APP_SG_ID}"
-var="desired_capacity=1"
aws autoscaling describe-auto-scaling-groups --region ca-central-1
--query "AutoScalingGroups[?Tags[?Key=='Lab' && Value=='terraform-autoscaling']].AutoScalingGroupName"
terraform destroy -auto-approve
-var="project=${PROJECT}"
-var="vpc_id=${VPC_ID}"
-var='private_subnet_ids=["subnet-AAA","subnet-BBB"]'
-var="app_sg_id=${APP_SG_ID}"
-var="desired_capacity=1"
cd ~ && rm -rf ~/terraform-asg-lab
Discipline : desired=1 + t3.micro + destroy immédiat. Un ASG oublié facture chaque EC2 jusqu’au destroy.
Étape 7 — Checklist
- Comprendre pourquoi ASG (HA, capacité, remplacement unhealthy).
- INTERDIT
aws_launch_configuration— uniquementaws_launch_template. - Déclarer LT (AMI data, SG, tags) + ASG (
min/desired/max). - Choisir health_check_type
EC2(lab) ouELB(derrière ALB). - Subnets ≥ 2 AZ (
terraform-vpc) ; aperçutarget_group_arns. - Region
ca-central-1, TF ≥ 1.9, provider~> 5.0, aucun secret. - Plan-only ou destroy immédiat — pas d’EC2 / ASG idle.
Nettoyage
cd ~/terraform-asg-lab
terraform destroy -auto-approve
-var="project=${PROJECT}"
-var="vpc_id=${VPC_ID}"
-var='private_subnet_ids=["subnet-AAA","subnet-BBB"]'
-var="app_sg_id=${APP_SG_ID}"
-var="desired_capacity=1"
cd ~ && rm -rf ~/terraform-asg-lab
# Filet CLI
aws autoscaling describe-auto-scaling-groups --region ca-central-1
--query "AutoScalingGroups[?Tags[?Key=='Lab' && Value=='terraform-autoscaling']].AutoScalingGroupName"
aws ec2 describe-instances --region ca-central-1
--filters Name=tag:Lab,Values=terraform-autoscaling Name=instance-state-name,Values=running
--query 'Reservations[].Instances[].InstanceId'
# Attendu : []
Erreurs fréquentes
| Symptôme | Cause | Correction |
|---|---|---|
aws_launch_configuration dans le plan |
Contenu / module legacy #1719 | Migrer vers aws_launch_template |
| ASG 0 instance / stuck | Subnets 1 AZ, SG, AMI invalide | ≥ 2 AZ ; AMI data ; SG OK |
| Remplacements en boucle | health_check_type=ELB trop tôt |
Grace period ↑ ou lab en EC2 |
Cibles ALB unhealthy |
Path HC / port / SG ALB→app | Aligner TG + SG (terraform-alb) |
InvalidAMIID |
AMI hardcodée autre Region | data.aws_ami en ca-central-1 |
| Facture surprise | ASG desired > 0 oublié |
Destroy + vérif CLI |
CreateBeforeDestroy conflict |
Nom LT / ASG figé | name_prefix sur le LT |
| IAM / SSM impossible | Pas d’instance profile | Brancher rôle (terraform-iam) |
| Mixed Instances / Spot KO | Tentative via Launch Configuration | Migrer LT + mixed_instances_policy |
|---|---|---|
| Instance refresh bloqué | Mauvaise version LT / capacity | Vérifier version LT et max ASG |
| Subnets publics par erreur | Copie des outputs VPC | Utiliser private_subnet_ids pour l’app |
Quiz (3 questions)
1. Quelle ressource Launch est interdite en série P2 terraform autoscaling ?
- A.
aws_launch_template - B.
aws_launch_configuration(déprécié) - C.
aws_autoscaling_group
2. Pour un ASG derrière un ALB, quel health_check_type privilégier ?
- A. Toujours
EC2uniquement - B.
ELB(santé via target group) - C. Aucun health check en prod
3. Après un lab ASG avec desired=1, action critique ?
- A. Laisser tourner jusqu’au lendemain
- B.
terraform destroyimmédiat + vérif CLI - C. Monter
max_sizeà 20 « au cas où »
4. Pourquoi name_prefix sur le Launch Template plutôt qu’un nom figé ?
- A. Obligation AWS
- B. Facilite create_before_destroy / rotations
- C. Réduit le prix EC2
5. Que vérifie le health check ELB ?
- A. Uniquement le status check EC2
- B. La santé déclarée par le target group ALB
- C. La facture Billing
Réponses : 1‑B · 2‑B · 3‑B · 4‑B · 5‑B
FAQ
Faut-il encore apprendre aws_launch_configuration ? Non pour les nouveaux designs. Sachez le reconnaître dans du code legacy afin de le migrer, mais n’en créez plus.
desired_capacity vs politiques de scaling ? desired fixe la capacité courante. Les politiques (CPU, ALBRequestCount, schedules) modifient desired dans la fourchette min/max. Ce lab pose le socle ; les policies viennent ensuite.
Puis-je mettre l’ASG en subnets publics ? Techniquement oui, rarement souhaitable. Préférez privé + ALB public ; egress via NAT ou endpoints selon le budget.
Pour aller plus loin
- Doc :
aws_launch_template,aws_autoscaling_group,aws_autoscaling_attachment, EC2 Auto Scaling - Site :
aws-auto-scaling-launch-template·terraform-alb·terraform-vpc·terraform-iam
Maillage série Terraform (P2)
| ← Précédent | VPC (terraform-vpc) |
| → Suivant | Route 53 (terraform-route53) |
| Aussi | ALB (terraform-alb) · IAM (terraform-iam) · ASG AWS (aws-auto-scaling-launch-template) |
| Carte | Overview · … · IAM · RDS · VPC · Autoscaling · Route 53 · … |
Retour parcours Terraform — hub de la série et leçons sœurs.



