Experiment: devops13 avril 2026

Terraform - AWS EC2 + RDS

Création d'une structure de base sur AWS avec Terraform (EC2 + RDS + VPC)

Terraform  - AWS EC2 + RDS

Terraform - AWS EC2 + RDS PostgreSQL

Cette experimentation consiste a deployer une instance EC2 et une base de donnees RDS PostgreSQL, puis a les integrer dans une architecture reseau AWS coherente. L'objectif est de construire une base d'infrastructure simple avec Terraform, en incluant le VPC, les subnets, le routage et les regles de securite.

Configuration et monitoring rapide

Dans un premier temps, on configure le provider AWS et un mecanisme d'alerte budgetaire. L'idee est de limiter les risques de depassement de cout pendant les tests.

On cree un fichier provider.tf avec les informations de base (pensez a executer aws configure au prealable) :

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 6.0"
    }
  }
}

provider "aws" {
  region = "eu-west-3"
}

resource "aws_budgets_budget" "example" {
  name         = "EC2_RDS_BUDGET"
  budget_type  = "COST"
  time_unit    = "MONTHLY"
  limit_amount = "1"
  limit_unit   = "USD"

  notification {
    comparison_operator        = "GREATER_THAN"
    threshold                  = 50
    threshold_type             = "PERCENTAGE"
    notification_type          = "ACTUAL"
    subscriber_email_addresses = ["contact@kernellab.fr"]
  }
}

La region choisie est eu-west-3 (Paris). La ressource aws_budgets_budget permet de definir un seuil de depense mensuel.

Ici, une notification email est envoyee quand 50% du budget defini (1 USD pour le test) est atteint.

Creation de l'instance EC2

Ensuite, on declare l'instance EC2 :

resource "aws_instance" "ec2_instance" {
  ami                         = "ami-007dcf089b8078f1a"
  instance_type               = "t3.micro"
  subnet_id                   = aws_subnet.subnet.id
  vpc_security_group_ids      = [aws_security_group.security_group.id]
  associate_public_ip_address = true
  key_name                    = "master-key"

  tags = {
    Name = "Ubuntu-terraform"
  }
}

Cette instance utilise une image Ubuntu (ami-007dcf089b8078f1a) et un type t3.micro. Elle est placee dans un subnet du VPC, associee a un security group dedie, et recoit une IP publique pour l'acces distant.

Creation du groupe de securite

On cree ensuite un security group rattache au VPC. Deux regles d'entree sont ajoutees : le port 22 (SSH) et le port 5432 (PostgreSQL). Le SSH est volontairement restreint à mon IP publique courante (recupérée dynamiquement), ce qui est une bonne pratique de securite. Le port PostgreSQL est ici ouvert sur 0.0.0.0/0 pour simplifier l'experimentation, mais en production il doit etre limite a des sources connues (par exemple un autre security group ou un CIDR prive).

# Groupe de sécurité
resource "aws_security_group" "security_group" {
  name        = "security_group"
  description = "Security group for EC2 instance"
  vpc_id      = aws_vpc.vpc.id

  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["${data.http.my_ip.response_body}/32"]
  }

  ingress {
    from_port   = 5432
    to_port     = 5432
    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"]
  }
}

Creation du VPC, des subnets et du routage

Cette section est le coeur reseau de l'infrastructure. On cree un VPC (10.0.0.0/16) avec le support DNS active, ce qui permet aux ressources de resoudre les noms internes et de beneficier d'hostnames AWS.

On ajoute ensuite deux subnets dans deux zones de disponibilite differentes (eu-west-3a et eu-west-3b). Ce choix ameliore la disponibilite et permet de preparer le terrain pour RDS, qui s'appuie sur un groupe de subnets.

La ressource aws_db_subnet_group indique explicitement à RDS quels subnets utiliser pour placer la base. Meme dans une architecture simple, c'est un élément important pour organiser proprement le plan d'adréssage.

On cree aussi une Internet Gateway, attachee au VPC, afin de donner un acces Internet aux subnets qui en ont besoin. La table de routage ajoute une route par defaut (0.0.0.0/0) vers cette gateway. Enfin, les associations lient cette table de routage aux deux subnets pour rendre la route effective.

En resume :

  • le VPC isole logiquement l'infrastructure ;
  • les subnets segmentent l'espace reseau ;
  • l'Internet Gateway ouvre l'acces sortant/entrant selon les regles ;
  • la route table definit le chemin du trafic ;
  • les associations appliquent ce routage a chaque subnet cible.
#Création du VPC
resource "aws_vpc" "vpc" {
  cidr_block           = "10.0.0.0/16"
  enable_dns_support   = true
  enable_dns_hostnames = true

  tags = {
    Name = "vpc-terraform"
  }
}

#Création du subnet
resource "aws_subnet" "subnet" {
  vpc_id                  = aws_vpc.vpc.id
  cidr_block              = "10.0.0.0/24"
  availability_zone       = "eu-west-3a"
  map_public_ip_on_launch = true

  tags = {
    Name = "subnet-ec2-db-1"
  }
}

resource "aws_subnet" "subnet_2" {
  vpc_id                  = aws_vpc.vpc.id
  cidr_block              = "10.0.1.0/24"
  availability_zone       = "eu-west-3b"
  map_public_ip_on_launch = true

  tags = {
    Name = "subnet-ec2-db-2"
  }
}

resource "aws_db_subnet_group" "db_subnet_group" {
  name       = "db-subnet-group"
  subnet_ids = [aws_subnet.subnet.id, aws_subnet.subnet_2.id]

  tags = {
    Name = "My DB subnet group"
  }
}

#Création de l'internet gateway
resource "aws_internet_gateway" "internet_gateway" {
  vpc_id = aws_vpc.vpc.id

  tags = {
    Name = "internet-gateway-terraform"
  }
}

#Création du route table
resource "aws_route_table" "route_table" {
  vpc_id = aws_vpc.vpc.id

  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = aws_internet_gateway.internet_gateway.id
  }

  tags = {
    Name = "route-table-terraform"
  }
}

#Association du route table au subnet
resource "aws_route_table_association" "route_table_association" {
  route_table_id = aws_route_table.route_table.id
  subnet_id      = aws_subnet.subnet.id
}

resource "aws_route_table_association" "route_table_association_2" {
  route_table_id = aws_route_table.route_table.id
  subnet_id      = aws_subnet.subnet_2.id
}

Sorties utiles (EC2 et BDD)

output "ec2_instance_public_ip" {
  value = aws_instance.ec2_instance.public_ip
}

output "db_instance_endpoint" {
  value = aws_db_instance.default.endpoint
}
Fin d'expérimentationKernelLab / 2026