Maîtriser l'Infrastructure as Code (IaC) : Déployez et Gérez Vos Applications Cloud avec Confiance
Maîtriser l'Infrastructure as Code (IaC) : Déployez et Gérez Vos Applications Cloud avec Confiance

Terraform en Action : Provisionner Votre Première Infrastructure Cloud (VPC, Instances)

Bienvenue dans cette leçon fondamentale de notre parcours "Maîtriser l'Infrastructure as Code (IaC) : Déployez et Gérez Vos Applications Cloud avec Confiance". Aujourd'hui, nous allons passer de la théorie à la pratique en provisionnant les briques de base de toute infrastructure cloud : un Virtual Private Cloud (VPC) et des instances de calcul (EC2), le tout avec Terraform.


1. Introduction : Construire nos Fondations Cloud avec Terraform

Dans les leçons précédentes, nous avons exploré les principes de l'Infrastructure as Code et découvert Terraform comme un outil puissant pour les mettre en œuvre. Rappelez-vous, Terraform nous permet de définir notre infrastructure à l'aide d'un langage déclaratif (HCL) et de la provisionner sur n'importe quel fournisseur cloud compatible.

Aujourd'hui, notre objectif est double :

  1. Comprendre les composants fondamentaux d'une infrastructure cloud : le réseau isolé (VPC) et les machines virtuelles (Instances).
  2. Appliquer nos connaissances de Terraform pour définir, planifier et déployer ces ressources sur le fournisseur AWS.

Nous allons construire une infrastructure simple mais fonctionnelle, composée de :

  • Un VPC personnalisé pour isoler notre réseau.
  • Un sous-réseau au sein de ce VPC.
  • Une passerelle Internet pour la connectivité externe.
  • Une table de routage pour diriger le trafic.
  • Un groupe de sécurité pour contrôler le trafic entrant et sortant de nos instances.
  • Une instance EC2 (notre serveur virtuel) déployée dans notre sous-réseau.

C'est une étape cruciale pour maîtriser IaC et déployer des applications robustes et sécurisées.


2. Prérequis Indispensables

Avant de plonger dans le code, assurez-vous d'avoir les éléments suivants :

  • Terraform installé sur votre machine. Si ce n'est pas le cas, suivez la documentation officielle : install.terraform.io.
  • Un compte Amazon Web Services (AWS) actif avec les permissions nécessaires pour créer des ressources (VPC, EC2, etc.).
  • Le CLI AWS configuré sur votre machine. Cela inclut la configuration de vos identifiants d'accès (AWS Access Key ID et Secret Access Key) et d'une région par défaut. Terraform utilisera ces identifiants pour s'authentifier auprès d'AWS.
  • Optionnellement, une paire de clés SSH (key pair) existante dans votre compte AWS si vous souhaitez vous connecter à l'instance EC2 par SSH. Nous n'allons pas la créer via Terraform dans cette leçon pour nous concentrer sur les aspects réseau et instance, mais vous pouvez facilement l'ajouter si vous le souhaitez.

3. Structure de notre Projet Terraform

Pour maintenir notre code organisé, nous allons créer un répertoire de projet et y placer nos fichiers Terraform :

mkdir my-first-infra
cd my-first-infra
touch main.tf variables.tf outputs.tf
  • main.tf : Contient la définition de toutes nos ressources AWS.
  • variables.tf : Définit les variables personnalisables de notre infrastructure.
  • outputs.tf : Spécifie les informations importantes que Terraform devrait nous retourner après le déploiement.

4. Concepts Clés de Terraform (Rappel Rapide)

Avant de coder, récapitulons rapidement les éléments fondamentaux de Terraform que nous allons utiliser :

  • Providers : Le bloc provider indique à Terraform quel cloud ou service nous voulons gérer (ex: aws, azurerm, google).
  • Resources : Le bloc resource est l'unité de base de l'infrastructure. Il déclare un composant spécifique (ex: aws_vpc, aws_instance). Chaque ressource a un type (ex: aws_vpc) et un nom local unique (ex: main).
  • Data Sources : Le bloc data permet à Terraform de récupérer des informations sur des ressources existantes ou des données externes (ex: récupérer le dernier AMI Ubuntu).
  • Variables : Le bloc variable permet de paramétrer notre configuration, la rendant plus flexible et réutilisable.
  • Outputs : Le bloc output permet d'exposer des valeurs importantes de notre infrastructure une fois déployée (ex: l'adresse IP publique d'une instance).
  • Référencement : Terraform permet de référencer les attributs d'autres ressources (ex: aws_vpc.main.id). Cela crée des dépendances implicites.

5. Définition de l'Infrastructure

C'est le cœur de notre leçon ! Nous allons maintenant remplir nos fichiers Terraform.

5.1. variables.tf : Paramétrer notre Infrastructure

Commençons par définir les paramètres que nous pourrons facilement modifier.

# variables.tf

variable "aws_region" {
  description = "Région AWS où déployer l'infrastructure."
  type        = string
  default     = "eu-west-1" # Vous pouvez changer cette région
}

variable "project_name" {
  description = "Nom du projet utilisé pour le tag des ressources."
  type        = string
  default     = "MyFirstTerraformInfra"
}

variable "vpc_cidr_block" {
  description = "Bloc CIDR pour le VPC."
  type        = string
  default     = "10.0.0.0/16"
}

variable "subnet_cidr_block" {
  description = "Bloc CIDR pour le sous-réseau public."
  type        = string
  default     = "10.0.1.0/24"
}

variable "instance_type" {
  description = "Type d'instance EC2 à déployer."
  type        = string
  default     = "t2.micro" # Type d'instance éligible au niveau gratuit d'AWS
}

variable "instance_key_pair" {
  description = "Nom de la paire de clés SSH AWS pour l'accès à l'instance EC2."
  type        = string
  default     = "my-ssh-key" # REMPLACEZ PAR LE NOM DE VOTRE PAIRE DE CLÉS EXISTANTE
}

Explication : Nous définissons des variables pour la région AWS, le nom du projet (utile pour les tags), les plages d'adresses IP (CIDR) de notre VPC et sous-réseau, le type d'instance EC2, et le nom de la paire de clés SSH. L'utilisation de default rend ces variables optionnelles lors de l'exécution, mais vous pouvez les surcharger.

5.2. main.tf : Le Cœur de notre Déploiement

Ce fichier va contenir la définition de toutes nos ressources AWS.

# main.tf

# 1. Configuration du Fournisseur AWS
provider "aws" {
  region = var.aws_region
}

# 2. Récupération de l'AMI (Amazon Machine Image) pour notre instance
# Nous utilisons une data source pour récupérer la dernière AMI Ubuntu 22.04 LTS
data "aws_ami" "ubuntu_latest" {
  most_recent = true
  filter {
    name   = "name"
    values = ["ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*"]
  }
  filter {
    name   = "virtualization-type"
    values = ["hvm"]
  }
  owners = ["099720109477"] # Canonical
}

# 3. Création du VPC (Virtual Private Cloud)
resource "aws_vpc" "main" {
  cidr_block = var.vpc_cidr_block
  tags = {
    Name    = "${var.project_name}-VPC"
    Project = var.project_name
  }
}

# Explication du VPC :
# Un VPC est un réseau virtuel privé et isolé dans le cloud AWS.
# `cidr_block` définit la plage d'adresses IP privées du VPC (ex: 10.0.0.0/16).
# Les `tags` sont des métadonnées pour organiser et identifier vos ressources.

# 4. Création du Sous-Réseau Public
resource "aws_subnet" "public" {
  vpc_id            = aws_vpc.main.id
  cidr_block        = var.subnet_cidr_block
  availability_zone = "${var.aws_region}a" # Choisir une zone de disponibilité (ex: eu-west-1a)
  map_public_ip_on_launch = true # Les instances lancées dans ce subnet recevront une IP publique

  tags = {
    Name    = "${var.project_name}-PublicSubnet"
    Project = var.project_name
  }
}

# Explication du Sous-Réseau :
# Un sous-réseau est une subdivision du VPC. Ici, il est "public" car il a un accès Internet.
# `vpc_id` le relie à notre VPC précédemment créé.
# `cidr_block` définit sa plage IP, qui doit être contenue dans le CIDR du VPC.
# `availability_zone` est une localisation physique isolée au sein d'une région AWS.
# `map_public_ip_on_launch = true` est crucial pour que notre instance ait une adresse IP publique.

# 5. Création de la Passerelle Internet (Internet Gateway)
resource "aws_internet_gateway" "main" {
  vpc_id = aws_vpc.main.id

  tags = {
    Name    = "${var.project_name}-IGW"
    Project = var.project_name
  }
}

# Explication de la Passerelle Internet :
# L'Internet Gateway est un composant du VPC qui permet la communication entre les instances du VPC
# et l'Internet. Elle doit être attachée à un VPC.

# 6. Création de la Table de Routage
resource "aws_route_table" "public" {
  vpc_id = aws_vpc.main.id

  # Règle de routage par défaut pour l'Internet
  route {
    cidr_block = "0.0.0.0/0"        # Toutes les destinations
    gateway_id = aws_internet_gateway.main.id # Vers notre Internet Gateway
  }

  tags = {
    Name    = "${var.project_name}-PublicRouteTable"
    Project = var.project_name
  }
}

# Explication de la Table de Routage :
# Une table de routage contient un ensemble de règles (routes) qui déterminent
# où le trafic réseau du sous-réseau est dirigé.
# La route "0.0.0.0/0" signifie "tout le trafic qui ne correspond à aucune autre règle".
# Ici, nous le dirigeons vers notre Internet Gateway pour qu'il puisse atteindre Internet.

# 7. Association de la Table de Routage au Sous-Réseau
resource "aws_route_table_association" "public" {
  subnet_id      = aws_subnet.public.id
  route_table_id = aws_route_table.public.id
}

# Explication de l'Association :
# C'est l'étape qui lie concrètement notre table de routage à notre sous-réseau.
# Sans cette association, le sous-réseau n'aurait pas de route vers l'Internet.

# 8. Création du Groupe de Sécurité (Security Group)
resource "aws_security_group" "web_sg" {
  name        = "${var.project_name}-WebSecurityGroup"
  description = "Autorise le trafic HTTP et SSH vers l'instance web"
  vpc_id      = aws_vpc.main.id

  # Règle pour autoriser le trafic entrant (ingress) HTTP (port 80)
  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"] # Autoriser de n'importe où
  }

  # Règle pour autoriser le trafic entrant (ingress) SSH (port 22)
  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"] # Autoriser de n'importe où (à des fins de démonstration, soyez plus restrictif en production !)
  }

  # Règle pour autoriser tout le trafic sortant (egress)
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1" # -1 signifie tous les protocoles
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = {
    Name    = "${var.project_name}-WebSG"
    Project = var.project_name
  }
}

# Explication du Groupe de Sécurité :
# Un Security Group agit comme un pare-feu virtuel pour votre instance.
# Il contrôle le trafic entrant (`ingress`) et sortant (`egress`).
# Ici, nous autorisons le trafic HTTP (port 80) et SSH (port 22) de n'importe où.
# Pour la production, vous devriez restreindre le CIDR_BLOCK pour SSH à votre adresse IP spécifique.

# 9. Création de l'Instance EC2
resource "aws_instance" "web_server" {
  ami           = data.aws_ami.ubuntu_latest.id # Utilisation de l'AMI récupérée
  instance_type = var.instance_type
  subnet_id     = aws_subnet.public.id
  vpc_security_group_ids = [aws_security_group.web_sg.id]
  key_name      = var.instance_key_pair # Nom de la paire de clés SSH

  # Script de démarrage pour installer Nginx
  user_data = <<-EOF
              #!/bin/bash
              sudo apt update -y
              sudo apt install -y nginx
              sudo systemctl start nginx
              sudo systemctl enable nginx
              echo "<h1>Hello from Terraform!</h1>" | sudo tee /var/www/html/index.nginx-debian.html
              EOF

  tags = {
    Name    = "${var.project_name}-WebServer"
    Project = var.project_name
  }
}

# Explication de l'Instance EC2 :
# C'est notre machine virtuelle !
# `ami` spécifie l'image disque à utiliser (ici, notre AMI Ubuntu).
# `instance_type` définit les ressources CPU, RAM, etc. (ex: t2.micro).
# `subnet_id` place l'instance dans notre sous-réseau public.
# `vpc_security_group_ids` attache notre groupe de sécurité à l'instance.
# `key_name` est essentiel pour se connecter à l'instance via SSH.
# `user_data` est un script shell qui s'exécute au premier démarrage de l'instance.
# Ici, il installe et configure Nginx, et crée un fichier `index.nginx-debian.html` simple.

5.3. outputs.tf : Récupérer des Informations Utiles

Après le déploiement, nous voudrons connaître certaines informations sur notre infrastructure.

# outputs.tf

output "vpc_id" {
  description = "ID du VPC créé."
  value       = aws_vpc.main.id
}

output "public_subnet_id" {
  description = "ID du sous-réseau public créé."
  value       = aws_subnet.public.id
}

output "web_server_public_ip" {
  description = "Adresse IP publique de l'instance du serveur web."
  value       = aws_instance.web_server.public_ip
}

output "web_server_public_dns" {
  description = "Nom DNS public de l'instance du serveur web."
  value       = aws_instance.web_server.public_dns
}

Explication : Nous définissons des outputs pour l'ID du VPC, l'ID du sous-réseau, l'adresse IP publique et le nom DNS public de notre instance EC2. Ces valeurs seront affichées après un terraform apply et sont facilement utilisables par d'autres configurations Terraform ou des scripts.


6. Le Workflow Terraform : Déployer et Gérer

Maintenant que notre infrastructure est définie dans le code, il est temps de la déployer ! Suivez ces étapes dans votre terminal, à la racine du dossier my-first-infra.

6.1. Initialisation du Répertoire Terraform

terraform init

Explication : Cette commande initialise le répertoire de travail. Terraform télécharge les plugins nécessaires pour le fournisseur AWS et configure le backend. Vous devriez voir un message indiquant que Terraform a été initialisé avec succès.

6.2. Planification du Déploiement

terraform plan

Explication : Le terraform plan est une étape cruciale. Il analyse vos fichiers de configuration, compare l'état actuel de votre infrastructure (s'il en existe une) avec l'état souhaité défini dans votre code, et vous montre précisément ce que Terraform va faire (créer, modifier ou supprimer des ressources). C'est votre chance de revoir les changements avant de les appliquer.

Vous devriez voir un long rapport détaillant toutes les ressources qui seront ajoutées, avec des + à côté de chaque ressource.

6.3. Application de l'Infrastructure

terraform apply

Explication : C'est la commande qui déploie réellement votre infrastructure. Terraform vous demandera une confirmation (tapez yes) avant de procéder. Il va ensuite créer toutes les ressources définies dans main.tf sur AWS dans l'ordre approprié, en gérant les dépendances.

Le processus peut prendre quelques minutes. Une fois terminé, Terraform affichera les outputs que nous avons définis dans outputs.tf, y compris l'adresse IP publique de votre serveur web.

6.4. Vérification de l'Infrastructure

Après un terraform apply réussi, vous pouvez :

  1. Consulter la console AWS : Allez dans les services VPC et EC2 de votre région sélectionnée (eu-west-1 par défaut). Vous devriez y voir votre nouveau VPC, sous-réseau, Internet Gateway, route table, security group, et votre instance EC2 en cours d'exécution.
  2. Accéder à votre serveur web : Prenez l'adresse IP publique de votre instance EC2 affichée dans les outputs de Terraform (ex: web_server_public_ip). Ouvrez un navigateur web et entrez cette adresse IP. Vous devriez voir la page "Hello from Terraform!" servie par Nginx.
  3. Se connecter en SSH (optionnel) : Si vous avez spécifié une paire de clés SSH valide, vous pouvez vous connecter à votre instance :
    ssh -i /chemin/vers/votre/cle.pem ubuntu@<adresse_ip_publique_instance>
    

6.5. Destruction de l'Infrastructure

Quand vous avez terminé avec cette leçon et que vous ne voulez plus que ces ressources consomment des crédits AWS, vous pouvez les détruire proprement :

terraform destroy

Explication : Cette commande va supprimer toutes les ressources gérées par ce fichier Terraform. Comme pour apply, Terraform vous montrera un plan de destruction (avec des -) et vous demandera une confirmation (yes). C'est un grand avantage de Terraform : il nettoie l'environnement complètement et de manière cohérente.


7. Conclusion : Votre Premier Pas vers l'IaC Maîtrisée

Félicitations ! Vous venez de provisionner votre toute première infrastructure cloud complète (VPC, sous-réseau, passerelle, table de routage, groupe de sécurité et instance EC2) en utilisant Terraform.

Ce que vous avez appris et accompli est fondamental :

  • Vous comprenez maintenant la synergie entre les composants réseau et calcul dans un environnement cloud.
  • Vous avez mis en pratique le cycle de vie complet de Terraform (init, plan, apply, destroy).
  • Vous avez vu comment Terraform transforme un code déclaratif en infrastructure réelle, gérant les dépendances et l'ordre de création.
  • Vous avez touché du doigt la puissance de l'IaC : reproductibilité, versionnement, collaboration facilitée, et élimination des erreurs manuelles.

Ceci n'est que le début. Dans les leçons suivantes, nous explorerons des concepts plus avancés comme la modularisation, la gestion de l'état (remote state), l'intégration continue, et la gestion d'infrastructures plus complexes. Vous êtes sur la bonne voie pour maîtriser le déploiement et la gestion de vos applications cloud avec confiance !