Introduction à Terraform
Terraform est un outil d'Infrastructure as Code (IaC) développé par HashiCorp. Il permet de décrire, versionner et automatiser le déploiement de ton infrastructure cloud ou on-premise.
Fonctionnement de Terraform
Terraform utilise un modèle déclaratif :
-
Déclaration : Tu écris ce que tu veux dans des fichiers
.tf(ex: "Je veux une instance EC2 avec 2 Go de RAM"). -
Comparaison : Terraform compare ta déclaration avec le fichier d'état (
tfstate), qui contient l'état actuel de ton infrastructure. - Planification : Terraform génère un plan d'exécution pour atteindre l'état souhaité.
-
Application : Tu valides le plan avec
terraform apply, et Terraform applique les changements.
tfstate. C'est à toi de détecter les
dérives (drift) avec terraform plan.
Concepts Clés
Concepts Fondamentaux
Exemple :
provider "aws" {
region = "eu-west-1"
}
resource.
Exemple :
resource "aws_instance" "mon_serveur" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
}
Exemple :
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "3.0.0"
# ... paramètres ...
}
tfstate) : Fichier JSON qui enregistre l'état actuel
de ton infrastructure. Ne jamais le modifier manuellement !
Backend : Où stocker le
tfstate (local, S3, Terraform Cloud, etc.).
terraform {
backend "s3" {
bucket = "mon-bucket-tfstate"
key = "prod/terraform.tfstate"
region = "eu-west-1"
}
}
Modules Terraform
Pourquoi utiliser des modules ?
Les modules permettent de :
- Réutiliser des configurations (ex: un VPC standardisé).
- Simplifier la maintenance (modifier un module = mise à jour partout).
- Partager des architectures entre équipes (via un registry public ou privé).
Tu y trouveras des modules prêts à l'emploi pour AWS, Azure, GCP, etc.
Commandes Utiles
Gestion de l'État (terraform state)
Ces commandes permettent de manipuler le fichier d'état (tfstate).
À utiliser avec prudence !
# Supprime une ressource de l'état (sans la détruire dans le cloud)
terraform state rm aws_instance.mon_serveur
# Télécharge l'état distant (ex: depuis S3)
terraform state pull > terraform.tfstate
# Envoie un état local vers le backend distant
terraform state push terraform.tfstate
# Affiche les détails d'une ressource dans l'état
terraform state show aws_instance.mon_serveur
# Liste toutes les ressources dans l'état
terraform state list
# Déplace une ressource dans l'état (ex: renommage)
terraform state mv aws_instance.ancien_nom aws_instance.nouveau_nom
# Remplace un provider dans l'état (ex: changement de version)
terraform state replace-provider registry.terraform.io/hashicorp/aws registry.terraform.io/hashicorp/aws/4.0.0
terraform state rm: Pour supprimer une ressource de l'état après l'avoir détruite manuellement dans le cloud.terraform state mv: Pour renommer une ressource sans la recréer.terraform state pull/push: Pour sauvegarder ou restaurer un état.
Sortie & Visualisation
Ces commandes aident à comprendre ce que Terraform va faire ou a fait.
# Génère un graphe de dépendances (au format DOT)
terraform graph | dot -Tsvg > graph.svg
# Affiche l'état actuel ou un plan sauvegardé
terraform show
# Affiche les outputs définis dans ton code
terraform output
# Affiche les changements prévus (sans appliquer)
terraform plan -out=tfplan
terraform show -json tfplan | jq
terraform graph: Utilise Graphviz pour visualiser les dépendances entre ressources.terraform plan -out=...: Sauvegarde le plan pour une application ultérieure.terraform show -json: Formate la sortie en JSON pour un traitement automatisé (ex: avecjq).
Importation / Remplacement
Pour intégrer des ressources existantes (créées manuellement) dans ton état Terraform.
# Importe une ressource existante dans l'état Terraform
# Syntax: terraform import ADRESSE_RESSOURCE ID_REEL
terraform import aws_instance.mon_serveur i-0123456789abcdef0
# Remplace une ressource sans la détruire (ex: changement de type)
terraform apply -replace="aws_instance.ancienne[0]"
- Crée un bloc
resourcevide dans ton code pour la ressource à importer. - Exécute
terraform importpour lier la ressource réelle à ce bloc. - Complète le bloc
resourceavec les paramètres actuels de la ressource. - Exécute
terraform planpour vérifier que tout est synchronisé.
Blocs de Configuration
Blocs Principaux
| Bloc | Description | Exemple |
|---|---|---|
provider |
Configure l'accès à un cloud provider (AWS, Azure, etc.). |
|
resource |
Déclare une ressource à créer (instance, bucket, etc.). |
|
variable |
Déclare une variable pour paramétrer ton code. |
|
output |
Exporte une valeur après application (ex: IP publique). |
|
locals |
Déclare des variables locales pour simplifier ton code. |
|
Meta-Arguments
Utilisation Avancée
| Meta-Argument | Description | Exemple |
|---|---|---|
count |
Crée plusieurs instances identiques d'une ressource. |
|
for_each |
Crée une ressource pour chaque élément d'un map ou set. |
|
depends_on |
Force une dépendance explicite entre ressources. |
|
lifecycle |
Contrôle le cycle de vie d'une ressource (ex: ignorer les changements). |
|
CI/CD Pipelines
Intégration Continue
Pour automatiser le déploiement de ton infrastructure, tu peux intégrer Terraform dans un pipeline CI/CD (GitHub Actions, GitLab CI, etc.).
- TFLint : Vérifie la syntaxe et les bonnes pratiques dans tes fichiers Terraform.
- Terraform Docs : Génère automatiquement de la documentation.
- Terragrunt : Pour gérer des configurations Terraform complexes.
- Infracost : Estime le coût de ton infrastructure avant déploiement.
# Exemple de pipeline GitHub Actions pour Terraform
name: Terraform CI
on:
push:
branches: [ main ]
pull_request:
jobs:
terraform:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Terraform
uses: hashicorp/setup-terraform@v2
- name: Terraform Init
run: terraform init
- name: Terraform Validate
run: terraform validate
- name: Terraform Plan
run: terraform plan -no-color
- name: Terraform Apply (Auto-merge only)
if: github.event_name == 'push'
run: terraform apply -auto-approve
Bonnes Pratiques
Éviter les Dérives (Drift)
Évite de modifier manuellement les ressources dans la console AWS/Azure. Toute modification doit passer par Terraform.
Utilise des politiques IAM pour empêcher les modifications manuelles sur les ressources gérées par Terraform.
# Exemple de politique IAM pour protéger une instance EC2
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Deny",
"Action": [
"ec2:TerminateInstances",
"ec2:StopInstances",
"ec2:ModifyInstanceAttribute"
],
"Resource": "arn:aws:ec2:*:*:instance/*",
"Condition": {
"StringNotLike": {
"aws:RequestTag/Terraform": "true"
}
}
}
]
}
Exécute régulièrement terraform plan pour identifier les écarts entre ton code et l'infrastructure réelle.
Utilise des outils comme Terraform Cloud/Enterprise pour une détection automatique.
Active le versioning sur ton backend (ex: S3) pour pouvoir restaurer un état précédent en cas d'erreur.
Cas Pratique : Gestion des Dérives
Scénario
Problème :
Tu as créé une instance EC2 manuellement dans la console AWS, mais elle n'est pas déclarée dans ton code Terraform.
terraform plan ne détecte pas cette ressource → dérive !
- Code Terraform : 1 instance EC2 (
aws_instance.web). - Console AWS : 2 instances EC2 (1 gérée par Terraform, 1 manuelle).
terraform plan: Ne voit que la première instance.
- Ajoute un bloc
resourcevide pour la ressource manuelle dans ton code. - Utilise
terraform importpour lier la ressource réelle à ce bloc. - Complète le bloc avec les paramètres actuels de la ressource.
- Exécute
terraform planpour vérifier la synchronisation.
Inspection et Modification de l'État
Outils Disponibles
Terraform fournit des commandes pour inspecter et modifier l'état (tfstate).
À utiliser avec prudence !
# Affiche l'état actuel au format lisible
terraform show
# Liste toutes les ressources dans l'état
terraform state list
# Affiche les détails d'une ressource spécifique
terraform state show aws_instance.mon_serveur
# Supprime une ressource de l'état (sans la détruire dans le cloud)
terraform state rm aws_instance.mon_serveur
# Déplace une ressource dans l'état (ex: renommage)
terraform state mv aws_instance.ancien_nom aws_instance.nouveau_nom
# Remplace un provider dans l'état (ex: mise à jour de version)
terraform state replace-provider registry.terraform.io/hashicorp/aws registry.terraform.io/hashicorp/aws/4.0.0
- Les modifications de l'état ne modifient pas l'infrastructure réelle.
- Une erreur dans l'état peut rendre ton infrastructure incohérente.
- Toujours faire un
terraform planaprès une modification de l'état.
Attributs Calculés ou Read-Only
Documentation Officielle
Dans la documentation de chaque ressource (ex: aws_instance), les attributs sont classés en 3 catégories :
| Type | Description | Exemple |
|---|---|---|
| Required | Attributs obligatoires pour créer la ressource. | ami, instance_type (pour aws_instance) |
| Optional | Attributs optionnels que tu peux définir. | tags, subnet_id |
| Computed | Attributs calculés automatiquement par le provider. Read-only ! | public_ip, arn, id |
aws_instance :
resource "aws_instance" "web" {
# Required
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
# Optional
tags = {
Name = "mon-serveur"
}
# Computed (read-only, définis automatiquement par AWS)
# public_ip = "54.123.45.67" # ❌ Ne pas définir manuellement !
}
# Pour utiliser un attribut computed :
output "instance_public_ip" {
value = aws_instance.web.public_ip # ✅ OK : lecture seule
}
Exercice : Module Terraform pour un Portfolio
Contexte
Tu veux déployer un site web statique (portfolio) avec :
- Une image Docker basée sur Nginx (
portfolio:1.3.0). - Une infrastructure légère et économique.
- Un accès public via une IP ou un nom de domaine.
Besoin :
- Un VPC avec un sous-réseau public.
- Un IAM Role pour permettre à ECS d'accéder aux ressources AWS.
- Un service ECS (ou une instance EC2) pour héberger ton container.
- Un Load Balancer ou une IP publique pour exposer le site.
Problème : Changement d'IP Publique
Après un redémarrage de ton instance EC2 (sans Elastic IP ni Load Balancer), son IP publique change.
Terraform détecte ce changement lors du prochain plan.
-
Si c'est juste un output (ex:
public_ip) qui a changé, tu n'as rien à faire : Terraform mettra à jour l'état automatiquement au prochainapply. -
Si la ressource elle-même a été modifiée manuellement (ex: type d'instance),
tu dois :
- Mettre à jour sa définition dans ton code
.tf. - Exécuter
terraform applypour synchroniser.
- Mettre à jour sa définition dans ton code
-
Si la ressource a été recréée manuellement (ex: nouvelle instance avec un nouvel ID) :
- Supprime l'ancienne ressource de l'état :
terraform state rm aws_instance.mon_ec2. - Importe la nouvelle ressource :
terraform import aws_instance.mon_ec2 i-nouvelid. - Vérifie avec
terraform plan.
- Supprime l'ancienne ressource de l'état :
# Exemple de correction pour une IP publique changée
# 1. Vérifie le changement
terraform plan
# 2. Applique les changements (Terraform mettra à jour l'état automatiquement)
terraform apply
# Si la ressource a été recréée manuellement :
# 1. Supprime l'ancienne référence dans l'état
terraform state rm aws_instance.mon_ec2
# 2. Importe la nouvelle ressource
terraform import aws_instance.mon_ec2 i-0435a04ca22d472ee
# 3. Vérifie que tout est synchronisé
terraform plan
Conclusion
Terraform est un outil puissant pour gérer ton infrastructure en tant que code. En suivant les bonnes pratiques et en maîtrisant les commandes présentées ici, tu peux :
- Automatiser le déploiement de ton infrastructure.
- Éviter les dérives et maintenir une infrastructure stable et reproductible.
- Collaborer efficacement avec ton équipe grâce au versioning et aux modules.
- Détecter et corriger rapidement les écarts entre ton code et l'infrastructure réelle.
Pour aller plus loin, explore la documentation officielle et les modules publics !