DevOps Elastic Hayway
Document

SUBSCRIBE TO GET FULL ACCESS TO THE E-BOOKS FOR FREE 🎁SUBSCRIBE NOW

Professional Dropdown with Icon

SUBSCRIBE NOW TO GET FREE ACCESS TO EBOOKS

TerraformLesson 17 / 2412 min readUpdated September 13, 2026

À la fin de ce tutoriel, vous saurez distinguer EBS et instance store, déclarer un aws_ebs_volume gp3 chiffré avec tags, comprendre aws_volume_attachment (conceptuel / optionnel), aperçu des snapshots, et exécuter un lab minimal en Region ca-central-1 — Terraform ≥ 1.9, AWS provider ~> 5.0. Message clé : volume EBS = ressource indépendante de l’EC2 ; destroy obligatoire ; snapshots = coût.

Niveau : Intermédiaire · Temps estimé : 30–40 min · Versions testées : Terraform ≥ 1.9, AWS provider ~> 5.0 · Dernière vérification : 2026-09-10

Slug proposé : terraform-ebs · Série : Terraform · Remplace / fusionne : #1669 (Volume EBS avec Terraform)

Prérequis

  • Avoir suivi Provisioners (terraform-provisioners) : last resort, cycle apply/destroy
  • Avoir suivi Workspaces (terraform-workspaces) et idéalement Variables (terraform-variables)
  • Terraform ≥ 1.9, AWS CLI v2, profil de lab (aws sts get-caller-identity OK)
  • Notions EC2 / AZ utiles (voir maillage VPC et IAM) ; le lab volume ne crée pas d’EC2 obligatoire

Coût estimé : quelques cents maximum pour un gp3 petit (ex. 8–10 Gio) en Free Tier friendly. Les snapshots coûtent en stockage — ne les laissez pas après le lab. Destroy obligatoire en fin de session. Aucun secret dans le HCL / tfvars.

Auth sans secrets. Utilisez AWS_PROFILE / SSO. Jamais d’access_key / secret_key dans le provider. Pas de clé KMS CMK hardcodée dans le dépôt : chiffrement AES-256 (clé gérée AWS) suffit pour ce lab.

Ce que nous allons construire

Lab terraform ebs (ca-central-1) — Free Tier friendly
  ├── versions.tf / providers.tf  → TF ≥ 1.9, aws ~> 5.0, region ca-central-1
  ├── Étapes 1–4                  → EBS vs instance store + aws_ebs_volume + attachment + snapshots
  ├── aws_ebs_volume gp3 petit    → encrypted, tags, AZ ca-central-1a
  ├── (optionnel) aws_volume_attachment → note conceptuelle / data existante
  ├── destroy obligatoire         → volume + snapshots éventuels
  └── Checklist + erreurs + quiz

(Alt : « Terraform EBS : volume gp3 chiffré, attachment EC2, snapshots — ca-central-1 ».)

Étape 1 — EBS vs instance store

Avant d’écrire du HCL, clarifiez le stockage EC2 :

Critère EBS (Elastic Block Store) Instance store
Persistance Survit au stop / restart (sauf delete_on_termination) Éphémère — perdu au stop / terminate / failure
Portée Volume lié à une AZ ; attachable à une instance de cette AZ Disques locaux de l’hôte
Cas d’usage OS data, bases, disques applicatifs Cache, scratch, workloads tolérants à la perte
Terraform aws_ebs_volume, root via aws_instance / launch template Souvent via type d’instance (pas un volume EBS classique)
Snapshot Oui (aws_ebs_snapshot) Non (pas de snapshot EBS natif)

Mot-clé SEO : avec terraform ebs, vous gérez un bloc réseau persistant, pas le stockage temporaire de l’hyperviseur. Pour un lab P2 : gp3 petit, chiffré, tagué, puis destroy.

Étape 2 — aws_ebs_volume (gp3, size, encrypted, tags)

Ressource centrale pour un volume data indépendant :

# versions.tf
terraform {
  required_version = ">= 1.9.0"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

# providers.tf
provider "aws" {
  region = "ca-central-1"
  # Auth : AWS_PROFILE / SSO — jamais de clés ici
}

# variables.tf
variable "project" {
  type        = string
  description = "Préfixe lab unique (sans secret)."
}

variable "availability_zone" {
  type        = string
  description = "AZ du volume (doit matcher l’instance si attachment)."
  default     = "ca-central-1a"
}

# main.tf — volume data Free Tier friendly
resource "aws_ebs_volume" "data" {
  availability_zone = var.availability_zone
  size              = 8
  type              = "gp3"
  encrypted         = true
  # iops / throughput : laisser défauts gp3 pour le lab (coût + simplicité)

  tags = {
    Name      = "${var.project}-ebs-data"
    ManagedBy = "terraform"
    Lab       = "terraform-ebs"
    Region    = "ca-central-1"
  }
}

output "volume_id" {
  description = "ID du volume EBS créé."
  value       = aws_ebs_volume.data.id
}

output "volume_az" {
  description = "AZ du volume (critique pour attachment)."
  value       = aws_ebs_volume.data.availability_zone
}

Points à retenir :

  1. availability_zone est obligatoire — un volume EBS n’est pas multi-AZ.
  2. type = "gp3" : défaut moderne ; IOPS/throughput réglables plus tard (hors Free Tier « petit »).
  3. encrypted = true : bonne pratique ; sans kms_key_id, AWS utilise la clé gérée du service.
  4. size en Gio : 8–10 Gio suffit pour apprendre — évitez 100 Gio « par habitude ».
  5. Tags : Name + Lab facilitent le nettoyage console / Cost Explorer.

Le volume existe sans EC2 : état available jusqu’à un attachment.

Étape 3 — aws_volume_attachment (optionnel / conceptuel)

L’attachment lie un volume à une instance dans la même AZ. Pour ce tuto, l’instance n’est pas créée (coût, SG, AMI). Deux approches pédagogiques :

A. Note conceptuelle (recommandée pour le lab minimal)

# CONCEPTUEL — ne pas appliquer sans instance existante dans la même AZ
# resource "aws_volume_attachment" "data" {
#   device_name = "/dev/xvdf"
#   volume_id   = aws_ebs_volume.data.id
#   instance_id = aws_instance.app.id   # ou data.aws_instance.existing.id
# }

B. Data source vers une instance déjà running (si vous en avez une de lab dans ca-central-1a) :

# Optionnel : instance préexistante taguée Lab=terraform-ebs-host
data "aws_instance" "existing" {
  count = var.attach_existing ? 1 : 0

  filter {
    name   = "tag:Lab"
    values = ["terraform-ebs-host"]
  }

  filter {
    name   = "instance-state-name"
    values = ["running"]
  }
}

resource "aws_volume_attachment" "data" {
  count = var.attach_existing ? 1 : 0

  device_name = "/dev/xvdf"
  volume_id   = aws_ebs_volume.data.id
  instance_id = data.aws_instance.existing[0].id
}

variable "attach_existing" {
  type        = bool
  description = "true seulement si une EC2 lab tourne dans la même AZ."
  default     = false
}

Règles dures :

  • AZ mismatch → erreur API (étape 7).
  • device_name : convention Linux /dev/xvdf (le guest peut voir nvme… — normal sur Nitro).
  • Après attachment : formatage / montage = user_data / SSM, pas un provisioner (voir tuto précédent).
  • Root volume : souvent géré dans aws_instance (root_block_device) — hors scope de ce lab « volume data ».

Pour valider le terraform ebs sans EC2 : créez uniquement aws_ebs_volume, vérifiez l’ID en output, puis destroy.

Étape 4 — Snapshots : aperçu et coûts

Un snapshot EBS est une copie incrémentale stockée dans S3 (côté AWS). En Terraform : aws_ebs_snapshot (source = volume_id).

Aperçu minimal (illustratif — ne créez pas de snapshot durable en lab gratuit) :

# Illustratif — décommentez seulement pour un test court, puis destroy
# resource "aws_ebs_snapshot" "data" {
#   volume_id   = aws_ebs_volume.data.id
#   description = "Lab snapshot ${var.project} — à détruire"
#   tags = {
#     Lab = "terraform-ebs"
#   }
# }

Coûts / bonnes pratiques :

Sujet Conseil P2
Stockage snapshot Facturé même après destroy du volume — destroy le snapshot aussi
Incrémental Premier snapshot ≈ taille utilisée ; suivants = deltas
Lifecycle En prod : AWS Backup / DLM — pas des snapshots orphelins manuels
Lab Préférez ne pas snapshotter ; si test : destroy immédiat
Restauration Nouveau aws_ebs_volume avec snapshot_id (même Region ; AZ à choisir)

Message SEO : terraform ebs sans gouvernance de snapshots = dette cloud silencieuse.

Étape 5 — Lab minimal ca-central-1 + destroy

Objectif : un volume gp3 8 Gio chiffré, sans EC2 obligatoire.

mkdir -p ~/terraform-ebs-lab && cd ~/terraform-ebs-lab
# Collez versions.tf, providers.tf, variables.tf, main.tf (étape 2)
# Option attach_existing : laissez false / omettez le bloc attachment

export AWS_PROFILE=lab
export AWS_REGION=ca-central-1
PROJECT="votreprenom20260910"

terraform init
terraform fmt
terraform validate
terraform plan  -var="project=${PROJECT}"
terraform apply -auto-approve -var="project=${PROJECT}"

terraform output
# volume_id = vol-...
# volume_az = ca-central-1a

aws ec2 describe-volumes 
  --volume-ids "$(terraform output -raw volume_id)" 
  --region ca-central-1 
  --query 'Volumes[0].{State:State,Size:Size,Type:VolumeType,Encrypted:Encrypted}'

# Destroy obligatoire — ne laissez pas le volume (ni snapshot)
terraform destroy -auto-approve -var="project=${PROJECT}"

cd ~
rm -rf ~/terraform-ebs-lab

Vérification console / CLI : aucun vol- tagué Lab=terraform-ebs ne doit rester en ca-central-1. Si vous avez créé un snapshot de test : aws ec2 describe-snapshots --owner-ids self puis suppression.

Étape 6 — Checklist

  1. Distinguer EBS (persistant, AZ-bound) et instance store (éphémère).
  2. Déclarer aws_ebs_volume : type = "gp3", size petit, encrypted = true, tags.
  3. Comprendre aws_volume_attachment : même AZ, device_name, instance requise.
  4. Traiter les snapshots comme des ressources payantes à lifecycle / destroy.
  5. Lab en ca-central-1, TF ≥ 1.9, provider ~> 5.0.
  6. Jamais de secrets / clés KMS CMK en clair dans le dépôt.
  7. terraform destroy + vérif absence de volumes/snapshots orphelins.

Nettoyage

cd ~/terraform-ebs-lab
PROJECT="votreprenom20260910"
terraform destroy -auto-approve -var="project=${PROJECT}"
cd ~
rm -rf ~/terraform-ebs-lab

# Filet de sécurité (si apply manuel hors state)
# aws ec2 describe-volumes --filters Name=tag:Lab,Values=terraform-ebs --region ca-central-1
# aws ec2 describe-snapshots --owner-ids self --filters Name=tag:Lab,Values=terraform-ebs --region ca-central-1

Erreurs fréquentes

Symptôme Cause Correction
InvalidVolume.ZoneMismatch / attachment refused Volume et instance dans des AZ différentes Aligner availability_zone du volume sur l’AZ de l’instance (ca-central-1a1b)
Erreur KMS / Client.InvalidKMSKey kms_key_id invalide, mauvaise Region, ou IAM sans kms:CreateGrant Lab : encrypted = true sans CMK custom ; prod : policy KMS + même Region
Volume in-use, destroy bloqué Attachment encore présent Destroy l’aws_volume_attachment (ou détacher) avant le volume
Coût après destroy volume Snapshots restants Destroy / supprimer les snapshots tagués lab
device_name déjà pris Conflit /dev/xvdf Autre lettre (xvdg…) ou inspecter les volumes attachés
Plan recrée le volume Changement AZ / encrypted / type incompatible Attendu : certains attributs forcent replace — backup avant
Attach sans formatage HCL OK, OS sans FS SSM / user_data pour mkfs + mount — pas un provisioner

Quiz (3 questions)

1. Un volume EBS est lié à :

  • A. Toute la Region (multi-AZ natif)
  • B. Une Availability Zone précise
  • C. Uniquement à l’instance store de l’hôte

2. Pour un lab Free Tier friendly avec terraform ebs, quel type privilégier ?

  • A. io2 1000 Gio
  • B. gp3 petit (ex. 8 Gio), encrypted
  • C. Instance store uniquement

3. Après terraform destroy du volume, que vérifier encore ?

  • A. Rien — le destroy couvre toujours les snapshots
  • B. Les snapshots orphelins (coût stockage) et tags Lab
  • C. Uniquement le provider version

Réponses : 1‑B · 2‑B · 3‑B

Pourquoi / quand gérer EBS avec Terraform

Un volume EBS survit (selon config) au cycle d’une instance : bases de données, disques de données, disques transitoires que vous voulez quand même tracer en IaC. Terraform rend explicites taille, type (gp3), chiffrement, AZ et attachement. Utilisez ce lab quand vous maîtrisez déjà Workflow, Variables et un minimum d’EC2 (instance + SG).

EBS vs instance store — rappel

EBS Instance store
Persistance Volume réseau, snapshotable Disque hôte, éphémère
AZ Lié à une AZ Lié à l’instance
Cas d’usage Données à conserver / déplacer Cache, scratch
Terraform aws_ebs_volume, attachment, snapshot Rarement « géré » comme volume durable

Pièges EBS fréquents (au-delà du tableau d’erreurs)

  • Volume créé en ca-central-1a et instance en 1b : attachement impossible.
  • Snapshots oubliés après destroy du volume : facturation silencieuse.
  • encrypted = true avec CMK custom sans droits kms:CreateGrant : apply cassé — en lab, chiffrement géré AWS suffit.
  • Modifier un attribut force-new (AZ, certains flags) sans backup : replace destructeur.
  • Formater/monter dans un provisioner Terraform : préférez user_data / SSM (voir tuto Provisioners — pourquoi les éviter).
  • Laisser une instance + volume allumés hors lab : destroy et vérifiez volumes/snapshots tagués.

Quand créer le volume séparément vs block device intégré

  • Block device dans aws_instance : simple pour le disque racine / disques liés au lifecycle instance.
  • aws_ebs_volume + aws_volume_attachment : disque de données que vous voulez détacher, snapshotter, réattacher ailleurs.

Ce tuto privilégie le second pour rendre visibles attachment et AZ.

Coût et Free Tier (discipline)

Choisissez gp3 petit (ex. 8 Gio), Region ca-central-1, chiffrement activé, tags Lab. Pas d’io2 provisionné, pas de milliers de Gio « pour voir ». Terraform ≥ 1.9, provider ~> 5.0, aucun secret / ARN KMS sensible en clair dans Git.

FAQ terraform EBS

Le destroy détache-t-il automatiquement ? L’ordre du graphe gère attachment puis volume si tout est dans le state ; un attachment orphelin hors state bloque encore.

Puis-je étendre la taille sans recreate ? Souvent update in-place côté AWS/Terraform selon l’attribut ; lisez le plan. L’OS doit ensuite étendre le système de fichiers.

Snapshots via Terraform ? Oui (aws_ebs_snapshot) ; traitez-les comme resources payantes avec lifecycle clair.

Multi-AZ pour un même volume ? Non : un volume EBS = une AZ. Pour multi-AZ, architecture (réplication, EFS, etc.).

Tags obligatoires ? Fortement recommandés (Project, Lab, Name) pour le filet de sécurité CLI post-lab.

SSM plutôt que SSH pour mkfs ? Oui dans l’esprit de la série AWS (moins de clés SSH à gérer).

Que vérifier après destroy ? describe-volumes / describe-snapshots filtrés sur vos tags en ca-central-1.

Pour aller plus loin

Maillage série Terraform (P2)

← Précédent Provisioners (terraform-provisioners)
→ Suivant ALB (terraform-alb)
Aussi IAM (aws-iam-users-groupes-roles-politiques) · VPC (aws-vpc-sous-reseaux-igw)
Carte Overview · Install · Workflow · Blocks · Providers · Variables · Locals · State · Modules · Workspaces · Labs AWS

Cas réel — un volume orphelin après destroy d’instance

Sans aws_volume_attachment (ou l’équivalent root géré), un EBS survit et facture. Le lab impose destroy + vérif CLI. En prod, les tags Lab / ManagedBy servent précisément à retrouver ces orphelins. Snapshot avant resize : un type de volume changé n’est pas toujours in-place.

Piège : attacher le même volume à deux instances « pour aller vite ». AWS refuse ou corrompt. Un volume = un attachement actif. Multi-AZ : le volume vit dans une AZ ; le déplacer n’est pas un update de tag.

À retenir : EBS est persistant par défaut. Votre destroy de lab doit le prouver, pas le supposer.

Retour parcours Terraform — hub de la série et leçons sœurs.

Share your love

Leave a Reply

Your email address will not be published. Required fields are marked *