ITSkillsCenter
Blog

Terraform : Infrastructure as Code

8 دقائق للقراءة

Ce que vous saurez faire à la fin

  1. Décrire toute votre infrastructure cloud (AWS, GCP, Azure, OVH, Scaleway) sous forme de fichiers texte versionnés.
  2. Provisionner et détruire un environnement complet (réseau, serveurs, base de données, DNS) en une commande.
  3. Gérer plusieurs environnements (dev, staging, prod) à partir du même code grâce aux workspaces et aux variables.
  4. Stocker l’état Terraform de manière sécurisée et collaborative (S3 + DynamoDB ou GCS).
  5. Mettre en place des revues de code d’infrastructure (terraform plan dans GitHub Actions ou GitLab CI).

Durée : 6h. Pré-requis : Compte sur au moins un cloud provider, Terraform 1.7+ installé (gratuit, opensource), Git, éditeur VS Code avec extension HashiCorp Terraform, compréhension basique du cloud (VPC, instances, IAM), un dépôt Git privé (GitHub gratuit ou GitLab).

Étape 1 — Comprendre l’Infrastructure as Code

L’IaC consiste à décrire votre infrastructure dans des fichiers texte plutôt que via des clics dans une console web. Les avantages pour une PME sénégalaise sont concrets : reproductibilité (recréer l’environnement de dev sur le poste d’un nouveau développeur en 10 minutes), traçabilité (chaque changement passe par un commit Git revu par un collègue), réversibilité (rollback instantané vers la version précédente), et économie (destruction automatique des environnements de test la nuit pour économiser 40 à 70 % de la facture cloud).

Terraform est l’outil de référence créé par HashiCorp. Il supporte plus de 3 000 providers : AWS, GCP, Azure, OVH, Scaleway, Cloudflare, GitHub, Datadog, et bien d’autres.

Étape 2 — Installer Terraform

# Linux (Ubuntu/Debian)
wget -O- https://apt.releases.hashicorp.com/gpg | \
    sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg

echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] \
    https://apt.releases.hashicorp.com $(lsb_release -cs) main" | \
    sudo tee /etc/apt/sources.list.d/hashicorp.list

sudo apt update && sudo apt install terraform

# macOS
brew tap hashicorp/tap
brew install hashicorp/tap/terraform

# Windows (PowerShell admin)
choco install terraform

# Vérifier
terraform version
# Terraform v1.14.9

Étape 3 — Initialiser un projet Terraform

Créez un dossier dédié et un premier fichier de configuration. Terraform lit automatiquement tous les fichiers .tf du dossier courant.

mkdir infra-pme-dakar && cd infra-pme-dakar

# Structure recommandée
touch main.tf variables.tf outputs.tf terraform.tfvars
mkdir modules environments
# main.tf
terraform {
  required_version = ">= 1.7"

  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.40"
    }
  }
}

provider "aws" {
  region = var.aws_region
}

Étape 4 — Définir les variables et le backend

# variables.tf
variable "aws_region" {
  description = "Région AWS pour la PME"
  type        = string
  default     = "eu-west-3"
}

variable "environment" {
  description = "Environnement : dev, staging, prod"
  type        = string
}

variable "company_name" {
  description = "Nom court de la société"
  type        = string
  default     = "pme-dakar"
}

variable "instance_type" {
  type    = string
  default = "t3.micro"
}
# terraform.tfvars (jamais commité, ajouter au .gitignore)
environment   = "dev"
instance_type = "t3.micro"

Étape 5 — Créer un backend distant pour partager l’état

Par défaut, Terraform stocke l’état dans terraform.tfstate en local. Pour travailler à plusieurs ou depuis une CI, mettez l’état sur S3 avec verrouillage DynamoDB.

# Créer le bucket et la table de verrouillage manuellement (one-shot)
aws s3api create-bucket \
    --bucket pme-dakar-tfstate \
    --region eu-west-3 \
    --create-bucket-configuration LocationConstraint=eu-west-3

aws s3api put-bucket-versioning \
    --bucket pme-dakar-tfstate \
    --versioning-configuration Status=Enabled

aws dynamodb create-table \
    --table-name terraform-locks \
    --attribute-definitions AttributeName=LockID,AttributeType=S \
    --key-schema AttributeName=LockID,KeyType=HASH \
    --billing-mode PAY_PER_REQUEST \
    --region eu-west-3
# Ajouter le backend dans main.tf
terraform {
  backend "s3" {
    bucket         = "pme-dakar-tfstate"
    key            = "infra/terraform.tfstate"
    region         = "eu-west-3"
    dynamodb_table = "terraform-locks"
    encrypt        = true
  }
}

Étape 6 — Initialiser et planifier

# Télécharger les providers et configurer le backend
terraform init

# Vérifier la syntaxe
terraform validate

# Formater proprement les fichiers
terraform fmt -recursive

# Voir ce que Terraform va créer/modifier/détruire
terraform plan -out=tfplan.out

# Appliquer après validation
terraform apply tfplan.out

Étape 7 — Créer un VPC complet pour la PME

Plutôt que d’écrire 200 lignes pour un VPC, utilisez le module officiel terraform-aws-modules/vpc/aws maintenu par la communauté.

# network.tf
module "vpc" {
  source  = "terraform-aws-modules/vpc/aws"
  version = "~> 5.5"

  name = "${var.company_name}-${var.environment}"
  cidr = "10.10.0.0/16"

  azs             = ["eu-west-3a", "eu-west-3b"]
  private_subnets = ["10.10.1.0/24", "10.10.2.0/24"]
  public_subnets  = ["10.10.101.0/24", "10.10.102.0/24"]

  enable_nat_gateway     = true
  single_nat_gateway     = true # 1 seul NAT pour économiser
  enable_dns_hostnames   = true
  enable_dns_support     = true

  tags = {
    Project     = "PME Dakar"
    Environment = var.environment
    ManagedBy   = "Terraform"
  }
}

Étape 8 — Provisionner une instance EC2 et un groupe de sécurité

# server.tf
resource "aws_security_group" "web" {
  name        = "web-${var.environment}"
  description = "Autorise HTTPS et SSH depuis Dakar"
  vpc_id      = module.vpc.vpc_id

  ingress {
    description = "HTTPS"
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  ingress {
    description = "SSH bureau Dakar"
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["41.82.0.0/16"] # Plage Sonatel approximative
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

resource "aws_instance" "web" {
  ami           = "ami-0c55b159cbfafe1f0" # Ubuntu 22.04 eu-west-3
  instance_type = var.instance_type
  subnet_id     = module.vpc.public_subnets[0]

  vpc_security_group_ids = [aws_security_group.web.id]

  tags = {
    Name        = "web-${var.environment}"
    Environment = var.environment
  }
}

Étape 9 — Définir les sorties (outputs)

# outputs.tf
output "vpc_id" {
  description = "ID du VPC créé"
  value       = module.vpc.vpc_id
}

output "web_public_ip" {
  description = "IP publique du serveur web"
  value       = aws_instance.web.public_ip
}

output "web_dns" {
  description = "DNS public AWS du serveur"
  value       = aws_instance.web.public_dns
}
terraform output
# vpc_id = "vpc-0abc..."
# web_public_ip = "13.36.42.108"
# web_dns = "ec2-13-36-42-108.eu-west-3.compute.amazonaws.com"

Étape 10 — Gérer plusieurs environnements avec workspaces

# Créer un workspace par environnement
terraform workspace new dev
terraform workspace new staging
terraform workspace new prod

# Lister les workspaces
terraform workspace list

# Basculer
terraform workspace select prod

# Le state est isolé par workspace dans le backend S3

Alternative recommandée pour une PME : un dossier par environnement avec son propre backend, plus simple à raisonner que les workspaces pour les équipes débutantes.

Étape 11 — Créer un module réutilisable

Si plusieurs projets de la PME utilisent la même architecture, encapsulez-la dans un module local.

mkdir -p modules/serveur-web
touch modules/serveur-web/{main.tf,variables.tf,outputs.tf}
# modules/serveur-web/main.tf
resource "aws_instance" "this" {
  ami           = var.ami
  instance_type = var.instance_type
  subnet_id     = var.subnet_id

  tags = merge(var.tags, {
    Module = "serveur-web"
  })
}

# Utilisation depuis main.tf
module "site_vitrine" {
  source        = "./modules/serveur-web"
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t3.micro"
  subnet_id     = module.vpc.public_subnets[0]
  tags          = { Project = "Site vitrine" }
}

Étape 12 — Importer une ressource existante

Si vous avez déjà créé manuellement un bucket S3 ou une instance, vous pouvez l’intégrer à Terraform sans destruction.

# Déclarer la ressource dans .tf
# resource "aws_s3_bucket" "legacy" {
#   bucket = "ancien-bucket-pme"
# }

# Importer
terraform import aws_s3_bucket.legacy ancien-bucket-pme

# Vérifier que plan ne propose aucune modification
terraform plan

Étape 13 — Détruire un environnement

# Destruction d'un environnement de test à la fin de la journée
terraform workspace select dev
terraform destroy -auto-approve

# Estimation des coûts évités : 60 à 80 % de la facture mensuelle
# si dev/staging sont détruits chaque soir et le week-end

Automatisez cette destruction nocturne via un cron GitHub Action pour les environnements non-prod : économies typiques de 18 000 à 45 000 FCFA/mois pour une PME utilisant 5 services AWS.

Étape 14 — Mettre en place une CI Terraform avec GitHub Actions

# .github/workflows/terraform.yml
name: Terraform CI

on:
  pull_request:
    paths: ['infra/**']
  push:
    branches: [main]
    paths: ['infra/**']

jobs:
  terraform:
    runs-on: ubuntu-latest
    defaults:
      run:
        working-directory: infra
    steps:
      - uses: actions/checkout@v4

      - uses: hashicorp/setup-terraform@v3
        with:
          terraform_version: 1.7.5

      - name: Configure AWS
        uses: aws-actions/configure-aws-credentials@v4
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: eu-west-3

      - run: terraform fmt -check -recursive
      - run: terraform init
      - run: terraform validate
      - run: terraform plan -no-color

      - name: Apply (main uniquement)
        if: github.ref == 'refs/heads/main'
        run: terraform apply -auto-approve

Erreurs courantes à éviter

  • Commit du fichier terraform.tfstate : il contient des secrets en clair. Ajoutez-le au .gitignore et utilisez un backend distant.
  • Variables sensibles dans tfvars commitées : utilisez TF_VAR_* en variables d’environnement ou un gestionnaire de secrets.
  • terraform apply sans plan préalable : risque de destruction de production. Toujours plan -out puis apply tfplan.out.
  • Versions de provider non figées : un provider qui se met à jour entre deux apply peut casser votre infra. Utilisez ~> 5.40 ou figez avec un fichier .terraform.lock.hcl commité.
  • Dérive manuelle (clic dans la console AWS) : un collègue qui modifie une ressource hors Terraform crée un drift. Lancez terraform plan régulièrement et corrigez.
  • State corrompu : ne jamais éditer terraform.tfstate à la main. Utilisez terraform state mv, state rm, state pull/push.
  • Modules trop génériques : ne pas surdimensionner. Un module simple et clair vaut mieux qu’un module ultra-paramétrable que personne ne comprend.

Checklist de mise en production

  • [ ] Terraform 1.7+ installé sur tous les postes de l’équipe
  • [ ] Backend distant S3 + DynamoDB (ou GCS) configuré et chiffré
  • [ ] Versioning activé sur le bucket de state
  • [ ] Fichier .gitignore incluant *.tfstate, *.tfvars, .terraform/
  • [ ] Versions providers figées avec lock file commité
  • [ ] Variables sensibles stockées dans Secrets Manager / GitHub Secrets
  • [ ] Modules locaux versionnés ou modules officiels utilisés
  • [ ] Workspace ou dossier séparé par environnement (dev/staging/prod)
  • [ ] Pipeline CI exécutant fmt / validate / plan sur chaque PR
  • [ ] Apply en production protégé par revue obligatoire (CODEOWNERS)
  • [ ] Cron de destruction nocturne sur dev/staging
  • [ ] Tags ManagedBy=Terraform sur toutes les ressources
  • [ ] Documentation README expliquant le workflow init/plan/apply
  • [ ] Sauvegarde régulière du state dans un compartiment d’archive
Besoin d'un site web ?

Confiez-nous la Création de Votre Site Web

Site vitrine, e-commerce ou application web — nous transformons votre vision en réalité digitale. Accompagnement personnalisé de A à Z.

À partir de 250.000 FCFA
Parlons de Votre Projet
Publicité