Infrastructure as Code avec 200 ressources : ce que les tutoriels Terraform ne te disent pas
Patterns IaC de production pour des systèmes réels. Gestion d'état à grande échelle, conception de modules, hybride CDK + Terraform, détection de drift, GitOps avec Flux.
L'IaC, ce n'est pas "terraform init"
Tous les tutoriels Terraform commencent de la même façon : tu écris un fichier .tf, tu lances terraform init, tu lances terraform apply, et tu regardes ton instance EC2 apparaître. Ça te fait passer de zéro à une ressource. Ça ne te prépare pas à gérer 200+ ressources réparties sur 30 services AWS avec une équipe d'ingénieurs qui doivent tous pouvoir modifier l'infrastructure en toute sécurité.
Nous gérons l'infrastructure de plusieurs systèmes en production, des clusters Kubernetes avec Pimcore et OpenSearch aux architectures serverless avec Lambda, DynamoDB et API Gateway. Les patterns de cet article sont ceux qui ont survécu à la production. Pour savoir comment nous déployons les applications sur cette infrastructure, consulte notre page services cloud.
Gestion de l'état à grande échelle
L'état Terraform est le fichier le plus critique de ton infrastructure. Il fait le lien entre tes fichiers .tf et les ressources réelles. Si tu le perds, Terraform ne sait plus ce qui existe. Si tu le corrompus, Terraform risque de détruire des ressources en production.
État distant (non négociable)
# backend.tf
terraform {
backend "s3" {
bucket = "company-terraform-state"
key = "prod/platform/terraform.tfstate"
region = "eu-central-1"
encrypt = true
dynamodb_table = "terraform-locks"
}
}
| Règle | Pourquoi |
|---|---|
| État distant dans S3 (ou équivalent) | Les fichiers d'état locaux se perdent, impossible de les partager |
| Chiffrement au repos | L'état contient des secrets (mots de passe de bases de données, clés API) |
| Verrouillage DynamoDB | Empêche deux ingénieurs de lancer apply simultanément |
| Versioning sur le bucket S3 | Récupération en cas de corruption de l'état |
Organisation de l'état
Un gros fichier d'état pour tout, c'est un cauchemar de maintenance. Découpe par environnement et domaine :
terraform/
├── environments/
│ ├── prod/
│ │ ├── platform/ # EKS, VPC, réseau
│ │ ├── databases/ # RDS, ElastiCache, OpenSearch
│ │ ├── compute/ # Lambda, ECS, Fargate
│ │ ├── storage/ # Buckets S3, CloudFront
│ │ └── monitoring/ # CloudWatch, alertes
│ ├── staging/
│ │ └── (même structure)
│ └── dev/
│ └── (même structure)
├── modules/
│ ├── vpc/
│ ├── eks-cluster/
│ ├── rds-postgres/
│ ├── opensearch/
│ ├── redis/
│ └── lambda-function/
└── global/
├── iam/ # Rôles IAM, politiques
├── route53/ # Zones DNS
└── ecr/ # Registres de conteneurs
Chaque répertoire est un workspace Terraform séparé avec son propre fichier d'état. Les modifications du réseau ne risquent pas de casser la base de données. Les modifications du monitoring ne nécessitent pas un plan qui touche à toutes les ressources.
Références inter-états
Les workspaces doivent se référencer entre eux. Le workspace VPC exporte l'ID du VPC. Le workspace base de données le lit :
# Dans databases/main.tf
data "terraform_remote_state" "platform" {
backend = "s3"
config = {
bucket = "company-terraform-state"
key = "prod/platform/terraform.tfstate"
region = "eu-central-1"
}
}
resource "aws_db_instance" "main" {
vpc_security_group_ids = [data.terraform_remote_state.platform.outputs.db_security_group_id]
db_subnet_group_name = data.terraform_remote_state.platform.outputs.db_subnet_group_name
}
Conception de modules
Quand extraire un module
Pas chaque ressource n'a besoin d'un module. Extrais quand :
- Le même pattern est utilisé dans 3+ endroits (DRY)
- Le groupe de ressources a une frontière claire (VPC, cluster de base de données)
- La configuration a des valeurs par défaut sensées qui réduisent la duplication
N'extrais pas quand :
- C'est utilisé une seule fois (abstraction prématurée)
- Le module aurait 20+ variables (trop de boutons à tourner)
- L'abstraction cache des détails importants (réseau, sécurité)
Conception de l'interface du module
Un bon module a peu de variables requises, des valeurs par défaut sensées et des outputs clairs :
# modules/rds-postgres/variables.tf
variable "name" {
description = "Nom de l'instance de base de données"
type = string
}
variable "vpc_id" {
description = "VPC dans lequel déployer"
type = string
}
variable "subnet_ids" {
description = "Sous-réseaux pour le groupe de sous-réseaux DB"
type = list(string)
}
variable "instance_class" {
description = "Type d'instance RDS"
type = string
default = "db.t3.medium"
}
variable "engine_version" {
description = "Version PostgreSQL"
type = string
default = "15.4"
}
variable "allocated_storage" {
description = "Stockage en Go"
type = number
default = 50
}
variable "multi_az" {
description = "Activer le déploiement multi-AZ"
type = bool
default = false # true pour prod, false pour staging/dev
}
Le consommateur du module écrit :
module "database" {
source = "../../modules/rds-postgres"
name = "pimcore-prod"
vpc_id = module.vpc.vpc_id
subnet_ids = module.vpc.private_subnet_ids
multi_az = true
}
Cinq lignes au lieu de cinquante. Le module gère les security groups, les parameter groups, les subnet groups, le chiffrement, la rétention des sauvegardes et le monitoring.
CDK + Terraform : l'approche hybride pragmatique
Certaines équipes misent tout sur CDK. D'autres tout sur Terraform. Nous utilisons les deux, et ça fonctionne.
| Cas d'usage | Outil | Pourquoi |
|---|---|---|
| Réseau, bases de données, clusters | Terraform | Déclaratif, plan-before-apply, gestion d'état |
| Fonctions Lambda + API Gateway | CDK | Meilleur bundling Lambda, constructs API Gateway |
| Politiques IAM complexes | CDK | Logique TypeScript pour les politiques conditionnelles |
| Ressources Kubernetes | Kustomize + Flux | GitOps, boucles de réconciliation |
| Infrastructure statique | Terraform | Simple, lisible, bien compris |
La frontière est claire : Terraform gère l'infrastructure qui change rarement (VPC, RDS, cluster EKS). CDK gère l'infrastructure qui change avec les déploiements applicatifs (fonctions Lambda, routes API). Kustomize + Flux gère les workloads Kubernetes.
Ils coexistent grâce aux outputs. Terraform exporte l'ID du VPC, l'endpoint du cluster et la chaîne de connexion à la base de données. CDK les lit depuis SSM Parameter Store ou le remote state Terraform.
Le problème du drift
Le drift se produit quand quelqu'un modifie l'infrastructure via la console (ClickOps), via une commande CLI, ou via un autre outil. L'état réel diverge de l'état Terraform.
Détecter le drift
# Lancer le plan régulièrement (CI, job planifié)
terraform plan -detailed-exitcode
# Codes de sortie :
# 0 = pas de changements (l'état correspond à la réalité)
# 1 = erreur
# 2 = changements détectés (drift !)
Lance la détection de drift dans la CI sur un planning (quotidien pour la production, hebdomadaire pour le staging). Alerte quand un drift est détecté. Ne fais pas de remédiation automatique. Investigue d'abord.
Causes courantes du drift
| Cause | Prévention |
|---|---|
| Changements via la console (ClickOps) | Appliquer la politique "pas de changements console". Utiliser les SCPs pour restreindre. |
| Changements d'auto-scaling | Ignorer les attributs d'auto-scaling dans Terraform (lifecycle { ignore_changes }) |
| Mises à jour des services AWS | Fixer les versions des providers. Mettre à jour délibérément. |
| Terraform d'une autre équipe | Fichiers d'état séparés par équipe/domaine. |
| Hotfix manuel pendant un incident | Documenter le changement. L'appliquer dans Terraform après l'incident. |
# Ignorer les changements d'auto-scaling (drift attendu)
resource "aws_ecs_service" "app" {
desired_count = 2
lifecycle {
ignore_changes = [desired_count] # L'auto-scaling modifie cette valeur
}
}
GitOps avec Flux
Pour les workloads Kubernetes, nous utilisons Flux pour le GitOps. La boucle de réconciliation remplace kubectl apply par un modèle pull-based.
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Dépôt Git │────▶│ Flux │────▶│ Kubernetes │
│ (manifests) │ │ Controller │ │ Cluster │
└─────────────┘ └─────────────┘ └─────────────┘
│
│ Réconcilie toutes les 1 min
│ Détecte le drift
│ Applique automatiquement
# flux-system/kustomization.yaml
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: platform
namespace: flux-system
spec:
interval: 1m
sourceRef:
kind: GitRepository
name: infrastructure
path: ./kubernetes/resources/overlay/prod
prune: true
healthChecks:
- apiVersion: apps/v1
kind: Deployment
name: pimcore
namespace: production
Flux interroge le dépôt Git toutes les minutes. Si les manifests ont changé, il les applique. Si quelqu'un a modifié une ressource manuellement (drift), Flux la rétablit pour correspondre à Git. C'est une véritable réconciliation, pas juste de l'automatisation de déploiement.
Sealed Secrets
Les secrets ne peuvent pas aller dans Git en texte clair. Utilise Bitnami Sealed Secrets :
# Chiffrer le secret pour le cluster
kubeseal --cert sealed-secrets.pem \
-f secrets/database-secrets.yaml \
-o yaml > secrets/database-secrets-sealed.yaml
# Commiter la version scellée (sûr dans Git)
# Flux l'applique, le controller le déchiffre dans le cluster
Pour savoir comment nous gérons les secrets dans les déploiements Kubernetes de Pimcore spécifiquement, consulte notre guide de mise à niveau Pimcore qui couvre l'ordre complet de déploiement.
Gérer 30+ services AWS
À l'échelle enterprise, tu gères beaucoup de services. L'organisation fait la différence.
Catalogue de services
| Catégorie | Services | Module Terraform ? |
|---|---|---|
| Réseau | VPC, sous-réseaux, NAT, ALB, Route53 | Oui (module vpc) |
| Compute | EKS, ECS Fargate, Lambda | Oui (par type de service) |
| Base de données | RDS PostgreSQL, DynamoDB | Oui (module rds-postgres) |
| Cache | ElastiCache Redis | Oui (module redis) |
| Recherche | OpenSearch | Oui (module opensearch) |
| Stockage | S3, EFS | Inline (assez simple) |
| CDN | CloudFront | Inline |
| Messagerie | SQS, MSK (Kafka), RabbitMQ | Inline |
| Auth | Cognito | CDK (config complexe) |
| Monitoring | CloudWatch, X-Ray | Inline |
| CI/CD | ECR, CodeBuild | Inline |
| Sécurité | IAM, KMS, Secrets Manager | Workspace global |
Stratégie de tagging
Chaque ressource doit être taguée pour l'allocation des coûts, l'identification du propriétaire et la gestion du cycle de vie :
locals {
common_tags = {
Environment = var.environment # prod, staging, dev
Project = var.project_name # pimcore, commerce, ai
ManagedBy = "terraform"
Team = var.team # platform, backend, data
CostCenter = var.cost_center
}
}
resource "aws_instance" "example" {
tags = merge(local.common_tags, {
Name = "pimcore-web-1"
Role = "web"
})
}
Filtre AWS Cost Explorer par le tag Project pour voir exactement combien coûte chaque système. Filtre par ManagedBy pour trouver les ressources créées manuellement (non taguées "terraform").
Pièges courants
-
Un seul fichier d'état pour tout. Un
terraform planqui touche 200 ressources prend des minutes et une erreur affecte tout. Découpe par domaine et environnement. -
Pas de verrouillage d'état. Deux ingénieurs lancent
terraform applysimultanément. Les changements de l'un sont perdus ou l'état est corrompu. Utilise le verrouillage DynamoDB. -
Des modules avec 20+ variables. Si l'interface de ton module est aussi complexe que les ressources brutes, l'abstraction n'apporte aucune valeur. Garde les interfaces de module réduites.
-
Remédiation automatique du drift. Détecter le drift, c'est bien. Le corriger automatiquement, c'est dangereux. Le "drift" pourrait être un hotfix valide pendant un incident. Investigue avant de revenir en arrière.
-
Des secrets dans les fichiers d'état. L'état Terraform contient chaque attribut de chaque ressource, y compris les mots de passe de bases de données. Chiffre l'état au repos et restreins les accès.
-
Pas de pinning des versions des providers. Une mise à jour de provider change le comportement des ressources. Fixe les versions dans
required_providerset mets à jour délibérément. -
ClickOps pour "juste ce truc-là". Les changements en console créent du drift invisible jusqu'au prochain
terraform plan. Applique l'infrastructure-as-code pour tout. -
Pas de tagging. Sans tags, impossible d'attribuer les coûts, d'identifier les propriétaires ou de trouver les ressources créées manuellement.
Points clés à retenir
-
Découpe l'état par domaine et environnement. Réseau, bases de données, compute et monitoring devraient être des workspaces séparés. Les changements de l'un ne doivent pas risquer d'affecter l'autre.
-
Les modules sont pour les patterns, pas pour l'abstraction. Extrais quand le même groupe de ressources apparaît 3+ fois. Ne crée pas de modules pour les ressources ponctuelles.
-
CDK + Terraform, c'est pragmatique. Terraform pour l'infrastructure statique, CDK pour Lambda/API Gateway, Kustomize + Flux pour Kubernetes. Chaque outil là où il excelle.
-
La détection de drift est un job planifié. Lance
terraform planquotidiennement dans la CI. Alerte sur le drift. Investigue avant de remédier. -
GitOps avec Flux offre une vraie réconciliation. Pas juste de l'automatisation de déploiement. Flux détecte et annule les changements manuels. Sealed Secrets gardent les identifiants en sécurité dans Git.
-
Tague tout. Environnement, projet, équipe, centre de coûts, managed-by. Sans tags, l'attribution des coûts et l'audit des ressources sont impossibles.
Nous gérons l'infrastructure pour les déploiements cloud, les plateformes logicielles sur mesure et les systèmes d'ingénierie de données. Si tu as besoin d'aide avec l'IaC à grande échelle, contacte notre équipe ou demande un devis.
Sujets couverts
Guides connexes
Guide Entreprise des Systèmes d'IA Agentiques
Guide technique des systemes d'IA agentiques en entreprise. Decouvre l'architecture, les capacites et les applications des agents IA autonomes.
Lire le guideCommerce Agentique : Comment laisser les agents IA acheter en toute securite
Comment concevoir un commerce agentique gouverne. Moteurs de politiques, portes d'approbation HITL, reçus HMAC, idempotence, isolation multi-tenant et le protocole Agentic Checkout complet.
Lire le guideLes 9 endroits où ton système IA laisse fuir des données (et comment colmater chacun)
Cartographie systématique de chaque point de fuite de données dans les systèmes IA. Prompts, embeddings, logs, appels d'outils, mémoire d'agent, messages d'erreur, cache, données de fine-tuning et transferts entre agents.
Lire le guidePrêt à construire des systèmes IA prêts pour la production ?
Notre équipe est spécialisée dans les systèmes IA prêts pour la production. Discutons de comment nous pouvons aider.
Démarrer une conversation