Skip to content
Learni
Voir tous les tutoriels
DevOps

Comment implémenter Infrastructure as Code avec Terraform en 2026

18 minINTERMEDIATE
Read in English

Introduction

L'Infrastructure as Code (IaC) révolutionne la gestion d'infrastructures en traitant les ressources cloud comme du code source : versionnable, testable et reproductible. En 2026, avec la complexité croissante des clouds hybrides, Terraform s'impose comme l'outil open-source leader grâce à son langage HCL déclaratif et sa compatibilité avec 2500+ providers (AWS, Azure, GCP).

Ce tutoriel intermédiaire vous guide pour déployer un bucket S3 sécurisé avec versioning et politique IAM sur AWS. Pourquoi c'est crucial ? Une infra manuelle génère des dérives (drift), des coûts imprévus et des downtimes. Avec IaC, vous appliquez des idempotences : terraform apply reconstruit exactement l'état désiré.

Analogie : comme Git pour le code, Terraform versionne votre infra via un state file chiffré (optionnel S3 backend). Résultat : CI/CD fluide, audits conformes GDPR/SOC2. Prêt à transformer vos déploiements en code ? (128 mots)

Prérequis

  • Terraform CLI ≥ 1.9.0 installé (téléchargement)
  • Compte AWS avec droits IAM (AdministratorAccess pour tests)
  • AWS CLI configurée (aws configure avec access key/secret)
  • Connaissances de base en HCL et AWS S3
  • Git pour versionner le projet
  • Éditeur comme VS Code avec extension HashiCorp Terraform

Initialiser le projet Terraform

terminal-init.sh
mkdir terraform-iac-s3 && cd terraform-iac-s3
git init
echo '# IaC S3 Bucket Terraform' > README.md
terraform init

Cette commande crée un répertoire projet, l'initialise en Git pour le versionning, et exécute terraform init qui télécharge les providers et modules nécessaires. Piège : sans Git, pas de historique ; toujours exécuter dans un dossier vide pour éviter les conflits de state.

Configurer le provider AWS

Le provider définit comment Terraform interagit avec AWS. Il utilise vos credentials CLI par défaut, mais supporte variables d'env ou rôles IAM pour la sécurité. Créez main.tf avec version pinning pour reproductibilité.

Définir le provider et variables

main.tf
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.40"
    }
  }
  required_version = ">= 1.5"
}

provider "aws" {
  region = var.aws_region
}

variable "aws_region" {
  description = "Région AWS"
  type        = string
  default     = "eu-west-1"
}

variable "bucket_name" {
  description = "Nom unique du bucket S3"
  type        = string
}

Ce fichier fixe la version Terraform/providers pour éviter les breaking changes, configure le provider avec une variable région, et prépare bucket_name. Utilisez ~> 5.40 pour minor updates sécurisés ; piège : noms buckets globaux uniques, préfixez avec mon-app-2026-.

Créer le bucket S3 de base

Définissez la ressource S3 avec versioning activé pour récupération données. Terraform gère l'idempotence : apply répété n'ajoute pas de duplicatas.

Ressource S3 bucket avec versioning

s3.tf
resource "aws_s3_bucket" "secure_bucket" {
  bucket = var.bucket_name

  tags = {
    Name        = "Secure IaC Bucket"
    Environment = "prod"
    ManagedBy   = "Terraform"
  }
}

resource "aws_s3_bucket_versioning" "secure_bucket_versioning" {
  bucket = aws_s3_bucket.secure_bucket.id
  versioning_configuration {
    status = "Enabled"
  }
}

resource "aws_s3_bucket_server_side_encryption_configuration" "secure_bucket_encryption" {
  bucket = aws_s3_bucket.secure_bucket.id
  rule {
    apply_server_side_encryption_by_default {
      sse_algorithm = "AES256"
    }
  }
}

Crée un bucket tagué, active versioning (rétention 128 versions) et chiffrement AES256 at-rest. Références comme aws_s3_bucket.secure_bucket.id créent des dépendances implicites. Piège : sans tags, traçabilité nulle ; toujours activer encryption pour conformité.

Ajouter une politique de sécurité

Bloquez l'accès public et limitez uploads à un rôle IAM spécifique. Les policies JSON sont parsées via aws_iam_policy_document.

Politique bucket et IAM role

policy.tf
data "aws_iam_policy_document" "secure_bucket_policy" {
  statement {
    sid    = "DenyUnEncryptedObjectUploads"
    effect = "Deny"
    principals {
      type        = "*"
      identifiers = ["*"]
    }
    actions = ["s3:PutObject*"]
    resources = ["${aws_s3_bucket.secure_bucket.arn}/*"]
    condition {
      test     = "StringNotEquals"
      variable = "s3:x-amz-server-side-encryption"
      values   = ["AES256"]
    }
  }
}

resource "aws_s3_bucket_policy" "secure_bucket_policy" {
  bucket = aws_s3_bucket.secure_bucket.id
  policy = data.aws_iam_policy_document.secure_bucket_policy.json
}

resource "aws_iam_role" "s3_uploader" {
  name = "s3-uploader-role"
  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Action = "sts:AssumeRole"
      Effect = "Allow"
      Principal = { Service = "ec2.amazonaws.com" }
    }]
  })
}

La data source génère une policy JSON denyant uploads non-chiffrés ; attachée au bucket. Crée un rôle IAM pour EC2 uploads. Piège : policies malformées causent 403 ; validez avec terraform plan et AWS Policy Simulator.

Définir les outputs et state remote

Outputs exposent des valeurs (ex: bucket ARN pour apps). Pour prod, stockez state en S3 + DynamoDB lock.

Outputs et backend S3

outputs.tf
output "bucket_arn" {
  description = "ARN du bucket S3"
  value       = aws_s3_bucket.secure_bucket.arn
}

output "bucket_name_output" {
  description = "Nom du bucket"
  value       = aws_s3_bucket.secure_bucket.bucket
}

terraform {
  backend "s3" {
    bucket         = "mon-terraform-state-2026"
    key            = "iac-s3/terraform.tfstate"
    region         = "eu-west-1"
    dynamodb_table = "terraform-locks"
  }
}

Outputs pour intégration CI/CD ; backend S3 collabore multi-équipes avec locks DynamoDB (créez-les avant). Piège : state local perdu en delete dossier ; migrez vers remote avec terraform init -migrate-state.

Planifier et appliquer l'infrastructure

terminal-apply.sh
terraform validate
tfenv install 1.9.2
tfenv use 1.9.2
terraform fmt -recursive
terraform plan -var="bucket_name=mon-iac-s3-bucket-$(date +%s)-unique"
terraform apply -auto-approve -var="bucket_name=mon-iac-s3-bucket-$(date +%s)-unique"
terraform output -json

validate/fmt/plan vérifient syntaxe/drift ; apply déploie. Utilisez timestamp pour unicité bucket. Piège : sans -var, default échoue si non-unique ; output -json pour pipelines.

Nettoyage avec destroy

terminal-destroy.sh
terraform plan -destroy
terraform destroy -auto-approve
terraform state rm aws_s3_bucket.secure_bucket # Optionnel pour cleanup sélectif

destroy supprime tout idempotemment ; state rm pour ressources orphelines. Piège : oublie destroy = coûts AWS ; toujours plan -destroy preview.

Bonnes pratiques

  • Modularisez : Séparez en modules réutilisables (module "vpc" { source = "./modules/vpc" }).
  • State sécurisé : Toujours backend S3 + OIDC pour GitHub Actions.
  • Variables & secrets : terraform.tfvars ignoré Git ; utilisez Vault/Terraform Cloud.
  • Tests : Intégrez terratest ou checkov en CI pour scans IaC.
  • Versions pinning : ~> providers, tfenv pour lock Terraform version.

Erreurs courantes à éviter

  • Bucket name non-unique : Ajoutez UUID/timestamp ; erreur BucketAlreadyExists.
  • State drift : Exécutez terraform refresh post-changes manuels.
  • Provider version drift : Sans pinning, init upgrade casse ; utilisez terraform providers lock.
  • Cycles de dépendances : Évitez refs circulaires avec depends_on explicite.

Pour aller plus loin

  • Docs officielles : Terraform AWS Provider
  • Outils avancés : Terragrunt pour DRY, Atlantis pour PR reviews.
  • CI/CD : Intégrez GitHub Actions avec OIDC.
  • Découvrez nos formations Learni DevOps pour maîtriser Kubernetes as Code et advanced IaC.