
Créer une EC2 sans parler du réseau fonctionne pour un premier test, mais ce n’est pas encore une infrastructure exploitable. Très vite, vous devez répondre à trois questions concrètes : dans quel subnet l’instance doit vivre, quel security group filtre le trafic, et quels ports sont réellement ouverts. C’est cette transition entre “ça démarre” et “c’est joignable proprement” que ce guide traite.
Vous allez relire des ressources AWS déjà présentes, puis ajouter votre première couche réseau explicite. L’idée importante pour un débutant est la suivante : vous ne recréez pas tout. Vous branchez votre instance sur un réseau existant et vous lui attachez un pare-feu virtuel qui définit ses règles d’entrée.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Lire les ressources existantes avec les data sources (
aws_vpc,aws_subnet) - Créer un security group pour contrôler les règles réseau
- Autoriser SSH et HTTP via
aws_vpc_security_group_ingress_rule - Attacher une instance à un subnet spécifique avec des règles réseau précises
- Vérifier les sorties : subnet, security group, IP publique/privée
Pourquoi cette étape compte
Section intitulée « Pourquoi cette étape compte »Dans AWS, le réseau n’est pas un détail caché derrière l’instance. Une EC2 hérite d’un contexte réseau précis : VPC, subnet, security group. Si vous ne maîtrisez pas cet enchaînement, vous obtenez facilement une machine qui existe mais que vous ne pouvez ni joindre, ni sécuriser correctement.
Ce guide vous apprend donc une logique qui reviendra partout ensuite : lire ce qui existe, ajouter seulement la couche nécessaire, puis vérifier les identifiants réseau obtenus.
Prérequis
Section intitulée « Prérequis »- Terraform ≥ 1.11 installé
- AWS CLI configuré avec credentials valides
- Avoir lu Déployer une première EC2
Objectif
Section intitulée « Objectif »Vous allez construire une infrastructure qui :
- Récupère le VPC par défaut d’AWS
- Sélectionne un subnet existant
- Crée un security group avec règles d’ingress SSH et HTTP
- Lance une EC2 dans ce subnet protégée par le security group
Durée estimée : 15 minutes Coût : Gratuit ou ~$0.01 (tier gratuit AWS)
Préparation
Section intitulée « Préparation »Créez le répertoire du lab :
mkdir -p ~/terraform-aws-sg-subnetcd ~/terraform-aws-sg-subnetÉtape 1 — Déclarer le provider AWS
Section intitulée « Étape 1 — Déclarer le provider AWS »Créez versions.tf pour configurer le provider et les versions :
terraform { required_version = ">= 1.11.0" required_providers { aws = { source = "hashicorp/aws" version = "~> 5.0" } }}
provider "aws" { region = var.aws_region}Cela dit à Terraform :
- Utiliser Terraform ≥ 1.11.0
- Charger le provider AWS version ~5.0 (5.x stable)
- Se connecter à AWS dans la région définie par
var.aws_region
Étape 2 — Déclarer les variables
Section intitulée « Étape 2 — Déclarer les variables »Créez variables.tf :
variable "aws_region" { description = "AWS region" type = string default = "us-east-1"}
variable "instance_name" { description = "Name tag for the EC2 instance" type = string default = "lab02-instance-with-sg"}
variable "instance_type" { description = "EC2 instance type" type = string default = "t2.micro"}Ces variables vous permettront de changer de région ou de type d’instance sans modifier le code principal.
Étape 3 — Lire VPC, subnet et AMI existants
Section intitulée « Étape 3 — Lire VPC, subnet et AMI existants »Créez main.tf avec les data sources :
# Récupérer le VPC par défautdata "aws_vpc" "default" { default = true}
# Récupérer le premier subnet disponible du VPC par défautdata "aws_subnets" "default" { filter { name = "vpc-id" values = [data.aws_vpc.default.id] }}
# Lire l'AMI Ubuntu la plus récentedata "aws_ami" "ubuntu" { most_recent = true owners = ["099720109477"] # Canonical (Ubuntu)
filter { name = "name" values = ["ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*"] }
filter { name = "virtualization-type" values = ["hvm"] }}Ce bloc utilise les data sources Terraform pour lire l’infrastructure existante d’AWS sans la recréer :
data "aws_vpc" "default": récupère le VPC par défautdata "aws_subnets" "default": récupère tous les subnets du VPCdata "aws_ami" "ubuntu": récupère la dernière Ubuntu 22.04
Étape 4 — Créer le security group
Section intitulée « Étape 4 — Créer le security group »Toujours dans main.tf, ajoutez :
resource "aws_security_group" "lab02_sg" { name = "lab02-sg" description = "Security group for Lab 02 - SSH and HTTP access" vpc_id = data.aws_vpc.default.id
tags = { Name = "lab02-sg" }}Un security group est un firewall virtuel pour vos instances. Vous allez lui ajouter des règles ensuite.
Étape 5 — Autoriser SSH et HTTP
Section intitulée « Étape 5 — Autoriser SSH et HTTP »Toujours dans main.tf, ajoutez les règles d’ingress :
# Autoriser SSH (port 22)resource "aws_vpc_security_group_ingress_rule" "ssh" { security_group_id = aws_security_group.lab02_sg.id description = "Allow SSH from anywhere" from_port = 22 to_port = 22 ip_protocol = "tcp" cidr_ipv4 = "0.0.0.0/0"
tags = { Name = "allow-ssh" }}
# Autoriser HTTP (port 80)resource "aws_vpc_security_group_ingress_rule" "http" { security_group_id = aws_security_group.lab02_sg.id description = "Allow HTTP from anywhere" from_port = 80 to_port = 80 ip_protocol = "tcp" cidr_ipv4 = "0.0.0.0/0"
tags = { Name = "allow-http" }}Chaque rule dit : “Autoriser le trafic TCP entrant sur le port X depuis n’importe quel IP (0.0.0.0/0)”.
Étape 6 — Créer l’instance dans le subnet avec le security group
Section intitulée « Étape 6 — Créer l’instance dans le subnet avec le security group »Toujours dans main.tf, complétez :
resource "aws_instance" "lab02_vm" { ami = data.aws_ami.ubuntu.id instance_type = var.instance_type subnet_id = data.aws_subnets.default.ids[0] vpc_security_group_ids = [aws_security_group.lab02_sg.id]
tags = { Name = var.instance_name }}Points clés :
subnet_id: place l’instance dans le subnet sélectionnévpc_security_group_ids: associe le security group à l’instance[aws_security_group.lab02_sg.id]: c’est une liste → contrairement àsecurity_groups, qui s’utilise dans le VPC par défaut,vpc_security_group_idsest explicite et recommandé
Étape 7 — Déclarer les outputs
Section intitulée « Étape 7 — Déclarer les outputs »Créez outputs.tf :
output "vpc_id" { description = "VPC ID" value = data.aws_vpc.default.id}
output "subnet_id" { description = "Subnet ID where instance is running" value = aws_instance.lab02_vm.subnet_id}
output "security_group_id" { description = "Security Group ID" value = aws_security_group.lab02_sg.id}
output "instance_id" { description = "EC2 Instance ID" value = aws_instance.lab02_vm.id}
output "instance_public_ip" { description = "Public IP address of the instance" value = aws_instance.lab02_vm.public_ip}
output "instance_private_ip" { description = "Private IP address of the instance" value = aws_instance.lab02_vm.private_ip}
output "ubuntu_ami_id" { description = "Ubuntu AMI ID" value = data.aws_ami.ubuntu.id}Étape 8 — Créer le fichier tfvars
Section intitulée « Étape 8 — Créer le fichier tfvars »Créez terraform.tfvars :
aws_region = "us-east-1"instance_name = "lab02-instance-with-sg"instance_type = "t2.micro"Vérification
Section intitulée « Vérification »Maintenant exécutez le lab :
-
Initialiser Terraform :
Fenêtre de terminal terraform initSortie attendue :
Initializing the backend...Initializing provider plugins...- Finding hashicorp/aws versions matching "~> 5.0"...- Installing hashicorp/aws v5.100.0...Terraform has been successfully initialized! -
Valider la configuration :
Fenêtre de terminal terraform validateSortie attendue :
Success! The configuration is valid. -
Afficher le plan :
Fenêtre de terminal terraform planSortie attendue (résumé) :
Plan: 4 to add, 0 to change, 0 to destroy.Changes to Outputs:+ instance_id = (known after apply)+ instance_private_ip = (known after apply)+ instance_public_ip = (known after apply)+ security_group_id = (known after apply)+ subnet_id = "subnet-xxxxxxxxx"+ ubuntu_ami_id = "ami-xxxxxxxx"+ vpc_id = "vpc-xxxxxxxx" -
Appliquer la configuration :
Fenêtre de terminal terraform apply -auto-approveSortie attendue (fin) :
Apply complete! Resources: 4 added, 0 changed, 0 destroyed.Outputs:instance_id = "i-0e43f24bc8817d50d"instance_private_ip = "172.31.69.130"instance_public_ip = "32.195.205.231"security_group_id = "sg-07b0de0b4eca49e47"subnet_id = "subnet-ef519de1"ubuntu_ami_id = "ami-00de3875b03809ec5"vpc_id = "vpc-801432fa" -
Vérifier l’accès SSH (optionnel, la clé par défaut n’est pas disponible) :
Fenêtre de terminal aws ec2 describe-instances --instance-ids i-0e43f24bc8817d50d
Anatomie
Section intitulée « Anatomie »Data sources vs Resources
Section intitulée « Data sources vs Resources »| Type | Utilité | Exemple |
|---|---|---|
| Data source | Lire de l’infrastructure existante | data "aws_vpc", data "aws_ami" |
| Resource | Créer nouvelle infrastructure | resource "aws_security_group", resource "aws_instance" |
Les data sources ne créent rien — elles lisent uniquement. Cela vous permet de réutiliser ce qui existe déjà (VPC par défaut, AMI) sans duplication.
Security Group vs VPC Security Group Ingress Rule
Section intitulée « Security Group vs VPC Security Group Ingress Rule »Deux approches pour les règles :
# Approche 1 : Règles DANS la ressource (inline) — dépréciéresource "aws_security_group" "example" { ingress { from_port = 22 to_port = 22 protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] }}
# Approche 2 : Ressources SÉPARÉES (recommended) ✅resource "aws_security_group" "example" { name = "example"}
resource "aws_vpc_security_group_ingress_rule" "ssh" { security_group_id = aws_security_group.example.id from_port = 22 to_port = 22 ip_protocol = "tcp" cidr_ipv4 = "0.0.0.0/0"}Pourquoi séparer ?
- Plus granulaire : vous pouvez ajouter/modifier/supprimer une seule règle sans refactoriser tout le security group
- Plus lisible : chaque règle est explicite
- Meilleure gestion en équipe : moins de conflits lors de merges
Bonnes pratiques
Section intitulée « Bonnes pratiques »1. Nommer clairement les security groups
Section intitulée « 1. Nommer clairement les security groups »# ❌ Mauvaisresource "aws_security_group" "main" { name = "sg"}
# ✅ Bonresource "aws_security_group" "web_access" { name = "web-access-sg"}2. Restreindre 0.0.0.0/0 en production
Section intitulée « 2. Restreindre 0.0.0.0/0 en production »# ❌ Risquéecidr_ipv4 = "0.0.0.0/0"
# ✅ Produitcidr_ipv4 = "203.0.113.0/24" # Votre bureau/VPN3. Utiliser des tags pour tracer qui a créé quoi
Section intitulée « 3. Utiliser des tags pour tracer qui a créé quoi »tags = { Name = "lab02-sg" Environment = "lab" ManagedBy = "terraform"}4. Minimiser les ports ouverts
Section intitulée « 4. Minimiser les ports ouverts »# ❌ Trop permissiffrom_port = 0to_port = 65535ip_protocol = "-1" # Tous les protocoles
# ✅ Juste le nécessairefrom_port = 22to_port = 22ip_protocol = "tcp"Dépannage
Section intitulée « Dépannage »| Symptôme | Cause probable | Solution |
|---|---|---|
Error: No aws_subnet could be selected | Pas de subnet dans le VPC par défaut | Créer un VPC/subnet manuellement ou utiliser data "aws_availab availability_zones" |
Error: creating Security Group: ... InvalidParameterValue | Caractères spéciaux dans la description | Utiliser uniquement ASCII (pas d’accents, tirets longs) |
| Instance créée mais pas accessible SSH | La clé .pem n’est pas attachée | Ajouter key_name = aws_key_pair.xxx.key_name à la ressource |
| Port 22 ou 80 fermé | Security group non attachée ou règle manquante | Vérifier vpc_security_group_ids et les ingress rules |
Nettoyage
Section intitulée « Nettoyage »Après le lab, détruisez l’infrastructure pour ne pas être facturé :
terraform destroy -auto-approveSortie attendue :
Destroy complete! Resources: 4 destroyed.Nettoyez les fichiers Terraform générés :
rm -rf .terraform* terraform.tfstate*À retenir
Section intitulée « À retenir »- Les data sources permettent de lire l’infrastructure existante (VPC, subnet, AMI) sans la recréer
- aws_vpc_security_group_ingress_rule est l’approche recommandée pour les règles (séparation des préoccupations)
- Les security groups sont des firewalls virtuel — ils contrôlent qui peut accéder à vos instances
- vpc_security_group_ids (liste) est plus robuste que
security_groups(approche legacy) - Les outputs vous permettent de voir les IDs importants après l’apply
- Testez le plan avant l’apply pour voir exactement quoi Terraform créera