Infrastructure as Code avec Terraform
Infrastructure as Code avec Terraform
Pourquoi l'Infrastructure as Code ?
L'Infrastructure as Code (IaC) est le pilier fondamental du DevOps moderne. Au lieu de configurer manuellement des serveurs via des interfaces graphiques, on décrit l'infrastructure dans des fichiers de configuration versionnés.
Les avantages clés
- Reproductibilité : un même fichier produit toujours la même infrastructure
- Versionnement : chaque changement est tracé dans Git
- Revue de code : les changements d'infra passent par des pull requests
- Automatisation : déploiement en un seul
terraform apply - Documentation vivante : le code est la documentation
Terraform : les fondamentaux avancés
Providers et resources
Terraform utilise des providers pour interagir avec les APIs cloud. Chaque provider expose des resources et des data sources.
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
backend "s3" {
bucket = "mon-terraform-state"
key = "prod/infrastructure.tfstate"
region = "eu-west-3"
}
}
provider "aws" {
region = var.aws_region
}
Modules réutilisables
Un module Terraform encapsule un ensemble de resources dans un composant réutilisable :
module "vpc" {
source = "./modules/vpc"
cidr_block = "10.0.0.0/16"
availability_zones = ["eu-west-3a", "eu-west-3b", "eu-west-3c"]
environment = var.environment
tags = local.common_tags
}
module "eks_cluster" {
source = "./modules/eks"
cluster_name = "prod-cluster"
vpc_id = module.vpc.vpc_id
subnet_ids = module.vpc.private_subnet_ids
node_count = 3
instance_type = "t3.xlarge"
depends_on = [module.vpc]
}
State management et workspaces
Le state est le fichier qui maintient la correspondance entre votre code et les ressources réelles. En équipe, il doit être stocké dans un backend distant.
# Utilisation des workspaces pour gérer plusieurs environnements
# terraform workspace new staging
# terraform workspace new production
resource "aws_instance" "app" {
count = terraform.workspace == "production" ? 3 : 1
ami = data.aws_ami.ubuntu.id
instance_type = terraform.workspace == "production" ? "t3.xlarge" : "t3.medium"
tags = {
Environment = terraform.workspace
}
}
Patterns avancés
Boucles et expressions dynamiques
variable "services" {
type = map(object({
port = number
replicas = number
cpu = string
memory = string
}))
default = {
api = { port = 3000, replicas = 3, cpu = "500m", memory = "512Mi" }
web = { port = 4200, replicas = 2, cpu = "250m", memory = "256Mi" }
worker = { port = 0, replicas = 1, cpu = "1000m", memory = "1Gi" }
}
}
resource "kubernetes_deployment" "service" {
for_each = var.services
metadata {
name = each.key
labels = {
app = each.key
}
}
spec {
replicas = each.value.replicas
selector {
match_labels = {
app = each.key
}
}
template {
spec {
container {
name = each.key
image = "${var.registry}/${each.key}:${var.image_tag}"
resources {
requests = {
cpu = each.value.cpu
memory = each.value.memory
}
}
}
}
}
}
}
Gestion des secrets avec Vault
data "vault_generic_secret" "db_credentials" {
path = "secret/data/production/database"
}
resource "aws_db_instance" "main" {
engine = "postgres"
engine_version = "15.4"
instance_class = "db.r6g.xlarge"
username = data.vault_generic_secret.db_credentials.data["username"]
password = data.vault_generic_secret.db_credentials.data["password"]
storage_encrypted = true
multi_az = true
backup_retention_period = 30
deletion_protection = true
}
Bonnes pratiques
- Toujours utiliser un backend distant pour le state (S3, GCS, Azure Blob)
- Verrouiller les versions des providers et modules
- Séparer les environnements avec des workspaces ou des dossiers distincts
- Utiliser
terraform plansystématiquement avantapply - Ne jamais stocker de secrets en clair dans les fichiers
.tf - Structurer en modules pour réutiliser et tester l'infrastructure
- Intégrer Terraform dans le CI/CD avec des plans automatiques sur les PR