Providers et ressources
Les providers : des plugins qui parlent aux APIs
Terraform ne sait pas nativement comment créer une instance AWS, un bucket Azure ou un dépôt GitHub. Ce sont les providers qui font le lien entre Terraform et les APIs des différentes plateformes.
Un provider est un plugin (écrit en Go) qui expose les ressources et data sources d'un service. Il traduit tes blocs HCL en appels API concrets.
Cloud public
AWS, Azure, Google Cloud, OVH, DigitalOcean… Chaque cloud a son provider officiel maintenu par l'éditeur.
Infrastructure
Kubernetes, Helm, Docker, VMware… Pour gérer des ressources dans ta propre infrastructure.
Outils et services
GitHub, GitLab, Datadog, PagerDuty, Vault… Pour piloter des outils DevOps en Infrastructure as Code.
Utilitaires
Random, TLS, Local, Time… Des providers sans API externe, utiles pour générer des valeurs ou manipuler des fichiers locaux.
Déclarer un provider
On déclare les providers requis dans un bloc terraform avec required_providers,
puis on les configure dans un bloc provider.
# Déclarer les providers requis et leurs versions
terraform {
required_version = ">= 1.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
random = {
source = "hashicorp/random"
version = ">= 3.1"
}
}
}
# Configurer le provider AWS
provider "aws" {
region = "eu-west-3" # Paris
}
Le contrainte de version ~> 5.0 signifie « compatible avec 5.x, mais pas 6.0 ».
Toujours fixer les versions pour garantir la reproductibilité des déploiements.
Le registre Terraform
Tous les providers officiels et communautaires sont publiés sur registry.terraform.io. C'est la source de vérité pour :
- Trouver le nom exact d'un provider (
hashicorp/aws,integrations/github…) - Consulter la documentation de chaque ressource et data source
- Vérifier les versions disponibles et les changelogs
- Trouver des modules réutilisables publiés par la communauté
# Télécharger les providers déclarés dans required_providers
terraform init
# Les plugins sont téléchargés dans .terraform/providers/
# Un fichier .terraform.lock.hcl est créé pour figer les versions exactes
Les ressources : la syntaxe de base
Une ressource représente un composant d'infrastructure que Terraform va créer, modifier ou détruire. La syntaxe est toujours :
resource "TYPE_RESSOURCE" "NOM_LOCAL" {
attribut1 = valeur1
attribut2 = valeur2
# ...
}
# Exemple concret : un bucket S3
resource "aws_s3_bucket" "mon_bucket" {
bucket = "mon-bucket-unique-2024"
}
# Exemple : une instance EC2
resource "aws_instance" "web" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t3.micro"
tags = {
Name = "MonServeurWeb"
}
}
Le type (aws_instance) détermine quel objet est créé via le provider.
Le nom local (web) sert uniquement à référencer cette ressource dans le reste du code Terraform — il n'apparaît pas dans AWS.
Les data sources : lire sans créer
Un data source permet de lire des informations sur une ressource existante sans la créer ni la gérer. C'est utile pour récupérer des valeurs dynamiques (ID d'une AMI, ARN d'un certificat, liste de zones de disponibilité…).
# Récupérer la dernière AMI Amazon Linux 2023
data "aws_ami" "amazon_linux" {
most_recent = true
owners = ["amazon"]
filter {
name = "name"
values = ["al2023-ami-*-x86_64"]
}
}
# Utiliser l'AMI récupérée dans une ressource
resource "aws_instance" "web" {
ami = data.aws_ami.amazon_linux.id
instance_type = "t3.micro"
}
La syntaxe pour référencer un data source est data.<type>.<nom>.<attribut>.
Pour une ressource, pas besoin du préfixe data. : <type>.<nom>.<attribut>.
Références entre ressources
Les ressources peuvent se référencer mutuellement grâce à la syntaxe
<type>.<nom>.<attribut>.
Terraform résout automatiquement l'ordre de création.
# Un VPC
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
}
# Un subnet qui référence l'ID du VPC
resource "aws_subnet" "main" {
vpc_id = aws_vpc.main.id # référence au VPC ci-dessus
cidr_block = "10.0.1.0/24"
}
# Une instance EC2 dans ce subnet
resource "aws_instance" "web" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t3.micro"
subnet_id = aws_subnet.main.id # référence au subnet
}
Dépendances implicites vs depends_on
Quand tu références un attribut d'une ressource dans une autre, Terraform crée une dépendance implicite : il sait qu'il doit créer le VPC avant le subnet.
Parfois, une dépendance existe sans référence directe d'attribut. Dans ce cas, on utilise
depends_on pour la déclarer explicitement.
# Politique IAM
resource "aws_iam_role_policy" "app_policy" {
name = "app-policy"
role = aws_iam_role.app.id
policy = "..."
}
# L'instance doit attendre que la politique soit créée,
# mais ne référence pas directement son attribut
resource "aws_instance" "app" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t3.micro"
depends_on = [aws_iam_role_policy.app_policy]
}
Bonne pratique : utilise depends_on en dernier recours.
Préfère toujours les références directes d'attributs qui créent des dépendances implicites
— le code est plus lisible et moins fragile.
Exemple complet : VPC + subnet + EC2
Voici un exemple réaliste qui assemble toutes les notions vues : providers, ressources, data sources et références croisées.
# ── Provider ──────────────────────────────────────────
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = "eu-west-3"
}
# ── Data source : dernière AMI Amazon Linux ───────────
data "aws_ami" "amazon_linux" {
most_recent = true
owners = ["amazon"]
filter {
name = "name"
values = ["al2023-ami-*-x86_64"]
}
}
# ── Réseau ────────────────────────────────────────────
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
tags = { Name = "vpc-lab" }
}
resource "aws_subnet" "main" {
vpc_id = aws_vpc.main.id # dépendance implicite
cidr_block = "10.0.1.0/24"
availability_zone = "eu-west-3a"
tags = { Name = "subnet-lab" }
}
# ── Serveur ───────────────────────────────────────────
resource "aws_instance" "web" {
ami = data.aws_ami.amazon_linux.id # depuis data source
instance_type = "t3.micro"
subnet_id = aws_subnet.main.id # dépendance implicite
tags = { Name = "web-lab" }
}
- Un provider est un plugin qui expose les ressources d'une API (AWS, Azure, GitHub…). On le déclare dans
required_providersavec une version. - Le registre Terraform (
registry.terraform.io) liste tous les providers et leur documentation. - Une ressource se déclare avec
resource "type" "nom_local" {}. Le type vient du provider, le nom local est libre. - Un data source (
data "type" "nom" {}) lit une ressource existante sans la créer. - Les références (
aws_subnet.main.id) créent des dépendances implicites.depends_onsert pour les dépendances sans référence directe.