Project Oxygen & Ideo-LabIDEO LAB Dashboard 2026

⚙️DevOps – Terraform, State, GitLab CI/CD & Gestion d'incidents (Part 2)

Guide pratique IDEO‑Lab pour nouveaux DevOps : infrastructure as code, modules, state, pipelines, déploiement contrôlé et production.

3.3

Runbooks DevOps

Procédures claires pour rollback, restart, saturation, DB, réseau et pipeline bloqué.

RunbookOpsSRE
3.3

RoadMap DevOps

Procédures claires sur la RoadMap devOps.

RunbookOpsSRE
4.1

Cheat‑sheet

Commandes Terraform, GitLab, debug pipeline et vérifications production.

CommandsDebugAudit
1.5

Design Terraform avancé

Naming, locals, validations, count/for_each, lifecycle et dépendances.

Designlocalslifecycle
1.6

Import & drift

Rattacher l'existant, detecter la dérive et reprendre le contrôle IaC.

importdriftaudit
1.7

Tests Terraform

Validation locale, plan de test, sandbox, Terratest et tests de modules.

testsandboxterratest
1.8

Coûts & FinOps

Comprendre l'impact coût des changements infra avant apply.

costFinOpstags
2.5

Merge Request infra

Comment documenter une MR Terraform lisible et validable.

MRreviewapproval
2.6

Templates GitLab CI

Factoriser les jobs CI/CD pour eviter la duplication.

includeextendstemplates
2.7

Approvals & protections

Branches protegees, environnements proteges, approvals et separation des droits.

protectedapprovalprod
3.3 Runbooks DevOps : procédures SRE pour production
Un runbook transforme la panique en procédure

Un runbook est une procédure opérationnelle claire qui explique quoi vérifier, quelles commandes lancer, dans quel ordre, avec quels risques et comment valider le retour à un état normal.

En production, le runbook évite l’improvisation. Il permet à un DevOps, un SRE, un développeur d’astreinte ou un support technique de suivre une méthode reproductible, même sous pression.

Objectif professionnel : chaque incident fréquent doit avoir une procédure claire : rollback, restart, saturation, DB, réseau, DNS, pipeline, state lock, certificats, secrets.
Ce qu’un bon runbook doit contenir
SectionContenu attendu
SymptômesComment reconnaître le problème : alerte, log, métrique, comportement.
ImpactQuels utilisateurs, services ou données peuvent être touchés.
VérificationsCommandes et dashboards à consulter avant action.
ActionsProcédure étape par étape, idéalement réversible.
ValidationComment confirmer que le service est revenu à la normale.
EscaladeQui appeler si la procédure ne fonctionne pas.
RollbackComment revenir en arrière ou mitiger.
Runbooks prioritaires pour une équipe DevOps
Runbooks essentiels
                            │
                            ├── Rollback infrastructure
                            ├── Rollback application
                            ├── Restart service Linux
                            ├── Saturation CPU / RAM / disque
                            ├── Base de données lente ou saturée
                            ├── DNS / certificat / load balancer
                            ├── Pipeline Terraform bloqué
                            ├── State lock Terraform
                            ├── Secret exposé
                            ├── Incident sécurité
                            └── Provider cloud dégradé
Runbook vs documentation
DocumentButStyle
DocumentationExpliquer un système.Descriptif, pédagogique.
RunbookAgir pendant une situation précise.Procédural, direct, vérifiable.
PlaybookCoordonner une réponse plus large.Rôles, scénarios, communication.
Post-mortemAnalyser après incident.Chronologie, RCA, actions préventives.
Règle : un runbook doit être testable. S’il contient des phrases vagues comme “vérifier que tout va bien”, il doit être amélioré.
Template professionnel de runbook
Structure standard
# Runbook : titre court

                            ## Objectif
                            Décrire le problème que ce runbook permet de traiter.

                            ## Symptômes
                            - Alerte :
                            - Logs :
                            - Métriques :
                            - Comportement utilisateur :

                            ## Impact possible
                            - Services touchés :
                            - Utilisateurs touchés :
                            - Données / sécurité :
                            - Niveau de gravité probable :

                            ## Pré-requis
                            - Accès nécessaires :
                            - Outils :
                            - Variables :
                            - Dashboards :

                            ## Étapes de diagnostic
                            1. ...
                            2. ...
                            3. ...

                            ## Actions de mitigation
                            1. ...
                            2. ...
                            3. ...

                            ## Validation du retour au nominal
                            - Healthcheck :
                            - Logs :
                            - Métriques :
                            - Test métier :

                            ## Rollback
                            - Action de retour arrière :
                            - Risque :
                            - Vérification :

                            ## Escalade
                            - Qui contacter :
                            - Quand escalader :

                            ## Notes post-incident
                            - Ticket :
                            - Post-mortem :
                            - Actions préventives :
Qualité attendue
CritèreBon runbookMauvais runbook
ClartéÉtapes numérotées, commandes exactes.Texte vague ou théorique.
SécuritéPrécise les actions dangereuses.Commandes destructives sans avertissement.
ValidationExplique comment mesurer le succès.Dit seulement “vérifier”.
EscaladeIndique quand appeler un expert.Laisse l’opérateur bloqué.
Mise à jourVersionné et revu après incident.Obsolète depuis plusieurs mois.
Diagramme d’utilisation
Alerte déclenchée
                            │
                            ▼
                            Identifier runbook correspondant
                            │
                            ▼
                            Lire prérequis et risques
                            │
                            ▼
                            Exécuter diagnostic
                            │
                            ▼
                            Choisir mitigation
                            │
                            ▼
                            Valider retour nominal
                            │
                            ▼
                            Documenter résultat
                            │
                            ▼
                            Mettre à jour runbook si manque détecté
Bonne pratique : après chaque incident, relire le runbook utilisé et corriger ce qui a manqué.
Runbook : rollback infrastructure Terraform

À utiliser lorsqu’un changement Terraform a provoqué ou semble avoir provoqué une dégradation : réseau bloqué, IAM cassé, load balancer mal configuré, DNS incorrect, security group trop restrictif.

Procédure
1. Déclarer l'incident si impact production.
                            2. Identifier le dernier apply Terraform.
                            3. Identifier le commit, la MR et le plan appliqué.
                            4. Lire les logs du job apply.
                            5. Lancer un plan refresh-only si nécessaire.
                            6. Déterminer si rollback complet ou patch minimal.
                            7. Revenir au commit précédent ou créer un correctif ciblé.
                            8. Générer un nouveau plan.
                            9. Vérifier qu'il ne détruit pas de ressource critique.
                            10. Faire relire le plan.
                            11. Appliquer avec approval.
                            12. Vérifier logs, métriques, health checks.
                            13. Documenter l'incident et la cause.
Attention : ne jamais lancer un rollback Terraform à l’aveugle. Le plan de rollback peut contenir des destructions ou remplacements.
Commandes utiles
# Identifier l'état courant
                            terraform state list
                            terraform plan -refresh-only

                            # Revenir à un commit précédent
                            git revert <commit_id>
                            git push origin main

                            # Générer un plan de rollback
                            terraform plan -out=tfplan -var-file="prod.tfvars"
                            terraform show -no-color tfplan > rollback-plan.txt

                            # Appliquer après review
                            terraform apply tfplan
Validation post-rollback
ZoneVérification
CloudRessource revenue à l’état attendu.
ApplicationHealthcheck OK, endpoints critiques OK.
LogsPlus d’erreurs nouvelles liées au changement.
Metrics5xx, latence, saturation revenus au nominal.
StatePas de drift inattendu après rollback.
Alternative : en incident critique, un patch minimal est parfois plus sûr qu’un rollback complet.
Runbook : restart contrôlé d’un service Linux

Redémarrer un service peut résoudre un blocage, mais peut aussi masquer la cause, interrompre des traitements ou aggraver l’incident. Le restart doit être contrôlé.

Diagnostic avant restart
# État du service
                            systemctl status app.service --no-pager

                            # Logs récents
                            journalctl -u app.service -n 100 --no-pager

                            # Ressources système
                            uptime
                            free -h
                            df -h

                            # Processus
                            ps aux | grep app
                            top
Procédure restart
1. Confirmer impact et nécessité du restart.
                            2. Vérifier s'il existe plusieurs instances.
                            3. Prévenir dans le canal incident si production.
                            4. Capturer logs avant restart.
                            5. Redémarrer une instance à la fois si possible.
                            6. Vérifier status systemd.
                            7. Vérifier healthcheck applicatif.
                            8. Surveiller logs et métriques.
                            9. Documenter l'action.
Commandes restart
# Restart contrôlé
                            sudo systemctl restart app.service

                            # Vérifier état
                            sudo systemctl status app.service --no-pager

                            # Suivre logs
                            sudo journalctl -u app.service -f

                            # Vérifier healthcheck
                            curl -fsS http://127.0.0.1:8000/health/
                            curl -fsS https://example.com/health/
Quand éviter un restart immédiat ?
SituationPourquoi attendre
Suspicion fuite mémoireCapturer métriques/process avant de perdre les indices.
Incident sécuritéPréserver preuves et logs.
Migration DB en coursRisque d’interruption dangereuse.
Cluster sans redondanceRestart = downtime direct.
Bonne pratique : préférer rolling restart si plusieurs instances existent.
Runbook : saturation serveur Linux

À utiliser en cas de CPU élevé, RAM saturée, disque plein, load average anormal, I/O wait important ou service instable sur un serveur Linux.

Commandes diagnostic rapides
# Charge système
                            uptime
                            top
                            ps aux --sort=-%cpu | head
                            ps aux --sort=-%mem | head

                            # Mémoire
                            free -h
                            dmesg | grep -i "killed process"

                            # Disque
                            df -h
                            df -i
                            du -sh /var/log/* | sort -h
                            du -sh /tmp/* | sort -h

                            # Erreurs système
                            journalctl -p err -n 100 --no-pager

                            # Services critiques
                            systemctl status nginx --no-pager
                            systemctl status app.service --no-pager
Attention : ne supprimez jamais massivement des fichiers sans comprendre leur rôle, surtout dans /var/lib, bases de données ou volumes applicatifs.
Diagnostic par symptôme
SymptômeCause possibleAction
CPU hautBoucle, trafic élevé, job lourd.Identifier process, scale, limiter job.
RAM saturéeFuite mémoire, cache, trop de workers.Identifier process, réduire workers, restart ciblé.
Disque pleinLogs, backups, uploads, cache.Nettoyage contrôlé, rotation, extension volume.
Inodes pleinsTrop de petits fichiers.Identifier dossier, purge contrôlée.
I/O wait élevéDisque saturé, DB, logs intensifs.Analyser I/O, réduire écriture, augmenter capacité.
Mitigation disque plein
1. Identifier le volume plein avec df -h.
                            2. Identifier gros dossiers avec du.
                            3. Vérifier logs applicatifs et Nginx.
                            4. Compresser ou purger uniquement fichiers sûrs.
                            5. Redémarrer service seulement si nécessaire.
                            6. Ajouter logrotate ou corriger rétention.
                            7. Ajouter alerte disque 75/85/95%.
Règle : si la saturation touche une base de données, escalader avant suppression manuelle.
Runbook : base de données lente ou saturée

Les incidents DB sont critiques : une mauvaise action peut empirer la latence, tuer des sessions utiles ou provoquer une perte de données. Il faut diagnostiquer avant d’agir.

Symptômes fréquents
SymptômeCause possible
Connexions saturéesPool mal réglé, fuite connexion, pic trafic.
Slow queriesIndex manquant, requête non optimisée, volume élevé.
Locks longsTransaction bloquée, migration, batch.
CPU DB élevéRequêtes lourdes, scan complet, tri massif.
Disk fullWAL/binlog, backups, tables temporaires.
Replication lagReplica trop lent, charge écriture élevée.
Commandes génériques Linux côté DB
# Ressources serveur
                            top
                            free -h
                            df -h
                            iostat -xz 1 5

                            # Logs
                            journalctl -u postgresql -n 100 --no-pager
                            journalctl -u mysql -n 100 --no-pager
                            journalctl -u mariadb -n 100 --no-pager
Procédure DB
1. Confirmer impact applicatif : 5xx, latence, timeouts.
                            2. Vérifier connexions DB et saturation.
                            3. Identifier requêtes lentes ou locks.
                            4. Vérifier dernier déploiement ou migration.
                            5. Éviter restart DB brutal sauf nécessité critique.
                            6. Mitiger : rollback app, réduire workers, tuer requête fautive si validé.
                            7. Vérifier retour métriques DB.
                            8. Documenter requête, index, migration ou config responsable.
Mitigations possibles
CasMitigation
Requête lente nouvelleRollback release ou désactiver feature.
Connexions saturéesRéduire concurrency workers, ajuster pool.
Lock bloquantIdentifier transaction, kill seulement après validation.
Disk DB presque pleinExtension volume, purge contrôlée, escalade DBA.
Règle : ne jamais supprimer des fichiers DB directement dans le filesystem pour “libérer de la place”.
Runbook : réseau, DNS, load balancer et certificats

Les incidents réseau sont souvent visibles comme des timeouts, 502/503/504, erreurs TLS, DNS incorrect, target group unhealthy ou connectivité DB impossible.

Commandes diagnostic
# DNS
                            dig example.com
                            dig +short example.com
                            nslookup example.com

                            # HTTP / TLS
                            curl -v https://example.com/
                            curl -fsS https://example.com/health/
                            openssl s_client -connect example.com:443 -servername example.com

                            # Connectivité port
                            nc -vz db.internal 5432
                            nc -vz redis.internal 6379

                            # Routes locales
                            ip addr
                            ip route
                            ss -tulpn
Symptômes fréquents
SymptômeCause probable
502Backend indisponible ou target unhealthy.
503Aucun backend disponible.
504Timeout upstream.
TLS errorCertificat expiré, mauvais SNI, chaîne incomplète.
DNS mauvaisRecord incorrect, TTL, propagation.
Procédure réseau
Incident réseau détecté
                            │
                            ▼
                            Identifier couche
                            ├── DNS
                            ├── TLS
                            ├── Load balancer
                            ├── Security group / firewall
                            ├── Route table
                            └── Backend service
                            │
                            ▼
                            Tester depuis plusieurs points
                            ├── local
                            ├── serveur
                            ├── réseau interne
                            └── externe
                            │
                            ▼
                            Relier à un changement récent
                            ├── Terraform apply
                            ├── certificat renouvelé
                            ├── DNS modifié
                            └── service déployé
                            │
                            ▼
                            Mitigation ciblée
Mitigations typiques
CasMitigation
DNS incorrectRestaurer record précédent, tenir compte TTL.
Certificat expiréRenouveler, recharger proxy/load balancer.
Security group bloque DBRestaurer règle source SG vers port DB.
Targets unhealthyVérifier healthcheck path, app, port, logs.
Timeout upstreamVérifier app, DB, proxy timeout, saturation.
Bonne pratique : en réseau, toujours identifier la couche fautive avant de modifier : DNS, TLS, LB, firewall, route, application.
Runbook : pipeline Terraform bloqué

À utiliser lorsqu’un pipeline infra échoue ou reste bloqué : runner indisponible, state lock, backend inaccessible, provider error, variables manquantes ou artefact de plan absent.

Procédure pipeline bloqué
1. Identifier le job exact en échec.
                            2. Lire les logs depuis le début.
                            3. Vérifier runner disponible et tags.
                            4. Vérifier image CI et version Terraform.
                            5. Vérifier variables accessibles à la branche.
                            6. Vérifier terraform init et backend.
                            7. Vérifier state lock.
                            8. Vérifier artifact tfplan si apply.
                            9. Corriger la cause minimale.
                            10. Relancer uniquement le job nécessaire.
                            11. Informer l'équipe si production concernée.
Commandes utiles
# Runner
                            gitlab-runner verify
                            gitlab-runner list

                            # Terraform
                            terraform --version
                            terraform providers
                            terraform init
                            terraform validate
                            terraform plan -refresh-only
                            terraform state list

                            # Lock, seulement après analyse
                            terraform force-unlock LOCK_ID
Règle : ne jamais faire force-unlock sans preuve que le job détenteur du lock est terminé ou mort.
Diagnostic par symptôme
SymptômeCause probableAction
Job pendingRunner absent ou tags incompatibles.Vérifier runners/tags/protection.
Variable videVariable protected non disponible.Vérifier branche protégée et scope.
init échoueBackend inaccessible.Vérifier credentials, bucket, réseau.
State lockApply actif ou lock orphelin.Identifier job détenteur.
Apply sans tfplanArtifact manquant ou expiré.Relancer plan puis apply.
Provider errorVersion/provider/API/cloud.Lire erreur, vérifier versions et quotas.
Flux décisionnel
Pipeline échoué
                            │
                            ▼
                            Est-ce un job prod ?
                            │
                            ├── Oui : informer équipe + prudence renforcée
                            └── Non : diagnostic standard
                            │
                            ▼
                            Erreur runner, variable, backend, lock ou provider ?
                            │
                            ▼
                            Corriger cause minimale
                            │
                            ▼
                            Relancer plan
                            │
                            ▼
                            Relancer apply uniquement si plan OK
Runbook : secret exposé ou incident sécurité CI

À utiliser si un secret apparaît dans Git, dans les logs CI, dans un artifact, dans un ticket, ou si un runner/pipeline semble compromis.

Procédure immédiate
1. Identifier le secret exposé.
                            2. Déterminer son périmètre : dev, staging, prod.
                            3. Révoquer ou désactiver le secret.
                            4. Créer un nouveau secret avec droits minimaux.
                            5. Mettre à jour GitLab/Vault/Secret Manager.
                            6. Relancer les pipelines nécessaires.
                            7. Vérifier que les services fonctionnent.
                            8. Auditer les logs d'utilisation.
                            9. Nettoyer logs/artifacts si possible.
                            10. Documenter incident et prévention.
Règle : un secret exposé doit être considéré compromis. Le supprimer du dépôt ou du log ne suffit pas.
Priorité selon secret
SecretPrioritéAction
Cloud prod adminCritiqueRévocation immédiate + audit cloud.
DB prod passwordCritiqueRotation + analyse accès DB.
Token GitLab writeÉlevéeRévoquer, vérifier actions repo.
Registry push tokenÉlevéeRotation, vérifier images poussées.
Token dev lectureMoyenneRotation planifiée rapide.
Prévention
  • Secret detection activée sur merge requests.
  • Variables masked/protected/scoped.
  • OIDC ou credentials courts si possible.
  • Pas de echo $SECRET ni env dans les jobs.
  • Artifacts explicitement listés.
  • Rotation documentée.
Après incident : ajouter un garde-fou qui empêche la même fuite de se reproduire.
Qualité, maintenance et tests des runbooks

Un runbook obsolète est dangereux. Les runbooks doivent être versionnés, testés, relus après incident et intégrés à la culture d’astreinte.

Critères de qualité
CritèreValidation
ActionnableUn opérateur peut suivre les étapes sans deviner.
À jourCommandes, services, chemins et dashboards valides.
SécuriséActions dangereuses clairement signalées.
MesurableChaque procédure indique comment vérifier le résultat.
EscalableIndique quand escalader et à qui.
TestéExercices réguliers ou simulation en staging.
Revue périodique
Tous les 3 mois :
                            [ ] Vérifier commandes.
                            [ ] Vérifier noms de services.
                            [ ] Vérifier liens dashboards.
                            [ ] Vérifier contacts d'escalade.
                            [ ] Vérifier accès nécessaires.
                            [ ] Tester en staging si possible.
                            [ ] Mettre à jour après incidents récents.
Exercice GameDay
Simulation contrôlée
                            │
                            ▼
                            Choisir scénario
                            ├── disque presque plein
                            ├── service down
                            ├── pipeline lock
                            └── DB lente
                            │
                            ▼
                            Suivre runbook
                            │
                            ▼
                            Mesurer
                            ├── temps diagnostic
                            ├── clarté étapes
                            ├── erreurs rencontrées
                            └── manque documentaire
                            │
                            ▼
                            Améliorer runbook
Où stocker les runbooks ?
SupportAvantage
Git repoVersioning, review, historique.
Wiki interneFacile à lire et partager.
Incident toolAccessible depuis alertes.
Dashboard linksRunbook directement lié à l’alerte.
Attention : si le runbook n’est accessible que quand GitLab est disponible, prévoir un accès de secours pour incidents critiques.
Checklist runbooks DevOps / SRE
Checklist création
PointValidation attendue
Symptômes clairsAlertes, logs, métriques associés.
Impact décritServices, utilisateurs, données, gravité.
Commandes exactesCopiables, contextualisées, non destructives par défaut.
Risques visiblesActions dangereuses signalées.
Validation définieHealthcheck, logs, métriques, test métier.
Rollback indiquéRetour arrière ou mitigation documentée.
Escalade indiquéeQuand et vers qui escalader.
Owner définiUne équipe responsable du runbook.
Checklist runbooks prioritaires
RunbookPriorité
Service down / restart contrôléCritique
Rollback applicatifCritique
Rollback TerraformCritique
Disque pleinCritique
Base de données lente/saturéeCritique
Pipeline Terraform bloquéÉlevée
DNS / certificat / load balancerÉlevée
Secret exposéCritique sécurité
Définition d’un bon runbook : une personne compétente mais non experte du sujet peut restaurer ou diagnostiquer sans improviser.
Mini-cheat-sheet
Runbook = symptômes + impact + diagnostic + action + validation + rollback + escalade

                            Toujours préciser :
                            [ ] Quand utiliser
                            [ ] Quand ne pas utiliser
                            [ ] Commandes exactes
                            [ ] Risques
                            [ ] Signaux de succès
                            [ ] Qui appeler
                            [ ] Quoi documenter après action
3.4 RoadMap DevOps : progression infra, CI/CD, SRE et production
Objectif de cette RoadMap DevOps

Cette roadmap propose une progression claire pour devenir opérationnel côté DevOps infrastructure : Linux, réseau, cloud, Terraform, GitLab CI/CD, sécurité, observabilité, incidents, runbooks et pratiques SRE.

Le but n’est pas seulement d’apprendre des outils. Le but est de construire une capacité professionnelle : livrer de l’infrastructure de façon fiable, sécurisée, automatisée, observable et récupérable en cas d’incident.

Objectif final : être capable de créer, déployer, surveiller, corriger et documenter une plateforme de production avec Terraform, GitLab CI/CD, remote state, secrets protégés, dashboards, alertes et runbooks.
Les grands blocs à maîtriser
DomaineCompétence attendue
LinuxServices systemd, logs, permissions, réseau, diagnostic CPU/RAM/disque.
RéseauDNS, TLS, HTTP, ports, firewall, load balancer, security groups.
CloudCompute, VPC, IAM, stockage, base de données managée, monitoring cloud.
TerraformProviders, modules, state, remote backend, plan/apply, drift, imports.
GitLab CI/CDStages, runners, variables, approvals, artifacts, environnements protégés.
SécuritéSecrets, OIDC, IAM least privilege, scans IaC, branches protégées.
ObservabilitéLogs, metrics, traces, dashboards, alerting, SLO.
IncidentsTriage, mitigation, rollback, communication, RCA, post-mortem.
Chemin de progression
Fondations
                            │
                            ├── Linux
                            ├── Réseau
                            ├── Git
                            └── Cloud basics
                            │
                            ▼
                            Infrastructure as Code
                            ├── Terraform basics
                            ├── modules
                            ├── remote state
                            └── sécurité
                            │
                            ▼
                            Industrialisation
                            ├── GitLab CI/CD
                            ├── runners
                            ├── variables protégées
                            ├── approvals
                            └── apply contrôlé
                            │
                            ▼
                            Production
                            ├── observabilité
                            ├── alerting
                            ├── runbooks
                            ├── rollback
                            └── incidents
                            │
                            ▼
                            Maturité SRE
                            ├── SLO
                            ├── error budget
                            ├── post-mortems
                            └── amélioration continue
Principe pédagogique
PhaseQuestion clé
ComprendreEst-ce que je sais expliquer ce que fait l’outil ?
ConstruireEst-ce que je sais créer un environnement reproductible ?
SécuriserEst-ce que je limite les accès, secrets et risques ?
AutomatiserEst-ce que la CI/CD exécute les contrôles correctement ?
ExploiterEst-ce que je peux diagnostiquer et restaurer en production ?
Attention : apprendre Terraform sans Linux, réseau, IAM et observabilité donne une compétence incomplète pour la production.
Niveaux de progression DevOps
Niveau 1 : Junior opérationnel
CompétenceAttendu
LinuxSavoir lire logs, redémarrer un service, vérifier CPU/RAM/disque.
TerraformComprendre init, plan, apply, variables, outputs, state.
GitLab CI/CDLire un pipeline, comprendre stages et jobs.
CloudComprendre VM, réseau, security groups, DNS, stockage.
IncidentSavoir suivre un runbook sans improviser.
Niveau 2 : DevOps autonome
Terraform modulesCréer modules propres et réutilisables.
Remote stateMettre en place backend distant, locking et séparation env.
Pipeline infraConstruire fmt, validate, scan, plan, apply manuel.
Sécurité CIVariables protégées, scopes, IAM minimal, secrets hors Git.
ObservabilitéCréer dashboards et alertes utiles.
Niveau 3 : DevOps confirmé / SRE
CompétenceAttendu
Architecture infraDécouper states, modules, comptes, environnements et domaines.
CI/CD avancéeTemplates, approvals, policies, runners protégés, OIDC.
ProductionDéploiements contrôlés, fenêtres, rollback, post-checks.
Incident responseCommander un incident, mitiger, communiquer, RCA.
SRESLO, error budget, runbooks testés, amélioration continue.
Niveau 4 : Platform Engineer
Self-serviceCréer modules et pipelines consommables par les équipes dev.
GuardrailsPolicy-as-code, standards sécurité, golden paths.
FinOpsMaîtriser coûts, tags, budgets, optimisation cloud.
Reliability engineeringMesurer, piloter et améliorer la fiabilité système.
Bonne progression : passer de “je sais lancer des commandes” à “je sais construire un système fiable que d’autres peuvent utiliser sans danger”.
RoadMap 12 semaines : progression réaliste
SemaineObjectifExercice pratiqueLivrable attendu
1Linux, Git, réseau de base.Installer une VM, Nginx, service systemd, logs.Serveur accessible + runbook diagnostic Linux.
2Cloud basics.Créer VM, security group, DNS, volume, firewall.Mini architecture cloud documentée.
3Terraform bases.Créer ressources simples via Terraform.Code Terraform init/plan/apply propre.
4Variables, outputs, structure fichiers.Paramétrer dev/staging/prod avec tfvars.Projet Terraform structuré.
5Modules Terraform.Créer module network + compute.Modules documentés avec inputs/outputs.
6Remote state + locking.Configurer backend distant par environnement.State distant, verrouillé, non commité.
7GitLab CI/CD infra.Créer pipeline fmt/validate/plan.MR avec plan Terraform en artefact.
8Apply contrôlé.Ajouter apply manuel staging/prod.Pipeline protégé avec approvals.
9Sécurité CI.Variables masked/protected/scoped, scan IaC.Secrets hors Git + rapport sécurité.
10Observabilité.Logs centralisés, metrics, dashboard, alertes.Dashboard production minimal.
11Incidents et runbooks.Simuler disque plein, rollback, pipeline lock.3 runbooks testés + timeline incident.
12Projet final.Déployer une mini app complète avec CI/CD et monitoring.Plateforme demo production-ready.
Résultat après 12 semaines
  • Comprendre les fondamentaux Linux, cloud et réseau.
  • Créer une infrastructure Terraform propre.
  • Utiliser modules, remote state et locking.
  • Créer pipeline GitLab CI/CD infra avec plan/apply contrôlé.
  • Sécuriser variables, secrets et environnements.
  • Créer dashboard, alertes et runbooks.
  • Simuler incidents et produire un post-mortem.
Diagramme de progression
Semaines 1-2
                            Fondations Linux / Cloud

                            Semaines 3-6
                            Terraform solide

                            Semaines 7-9
                            Industrialisation CI/CD + sécurité

                            Semaines 10-11
                            Observabilité + incidents

                            Semaine 12
                            Projet complet production-ready
Attention : cette roadmap doit être pratiquée. Lire sans construire ne suffit pas pour devenir DevOps opérationnel.
Parcours Terraform détaillé
Ordre d’apprentissage
ÉtapeCompétenceExercice
1Providers et resources.Créer une VM ou un bucket.
2Variables et outputs.Paramétrer région, nom, taille.
3Plan/apply.Lire les changements +, ~, -.
4State.Comprendre state list et state show.
5Modules.Créer module réseau et compute.
6Remote backend.State distant + lock.
7Drift et import.Importer une ressource existante.
8Production safety.Prévenir destroy, séparer env, review plan.
Exercices Terraform progressifs
Exercice 1 :
                            Créer une ressource simple avec tags.

                            Exercice 2 :
                            Ajouter variables.tf, outputs.tf, locals.tf.

                            Exercice 3 :
                            Créer dev.tfvars et prod.tfvars.

                            Exercice 4 :
                            Créer un module network.

                            Exercice 5 :
                            Créer un module compute qui consomme network outputs.

                            Exercice 6 :
                            Configurer backend distant.

                            Exercice 7 :
                            Simuler drift et le corriger proprement.

                            Exercice 8 :
                            Ajouter prevent_destroy sur ressource critique.
Compétence attendue
JuniorSait lire un plan et appliquer en dev.
AutonomeSait structurer modules, state et env.
ConfirméSait gérer drift, import, rollback, sécurité et production.
Cap à atteindre : ne jamais appliquer un plan que l’on ne sait pas expliquer.
Parcours GitLab CI/CD Infrastructure
Compétences CI/CD à acquérir
BlocÀ maîtriser
Syntaxe YAMLStages, jobs, variables, rules, needs, artifacts.
RunnersTags, runners protégés, runners dédiés infra.
Terraform pipelinefmt, validate, security, plan, apply, post-check.
Environnementsdev, staging, prod, protected environments.
ApprovalsApply manuel, review plan, approval prod.
SecretsVariables masked/protected/scoped, OIDC, IAM minimal.
DebugLogs pipeline, artifacts, state lock, variables absentes.
Pipeline cible
Merge Request
                            │
                            ├── terraform fmt
                            ├── terraform validate
                            ├── scan sécurité
                            └── terraform plan
                            │
                            ▼
                            Review du plan
                            │
                            ▼
                            Merge main
                            │
                            ▼
                            Plan production
                            │
                            ▼
                            Approval
                            │
                            ▼
                            Apply manuel
                            │
                            ▼
                            Post-checks
Exercices CI/CD
Exercice 1 :
                            Créer pipeline avec stages lint/validate.

                            Exercice 2 :
                            Ajouter terraform plan avec artifact plan.txt.

                            Exercice 3 :
                            Ajouter checkov ou trivy config.

                            Exercice 4 :
                            Ajouter apply manuel en staging.

                            Exercice 5 :
                            Protéger variables et environnement production.

                            Exercice 6 :
                            Ajouter post_deploy_checks avec curl /health.

                            Exercice 7 :
                            Simuler state lock et écrire runbook.

                            Exercice 8 :
                            Factoriser jobs avec includes/templates.
Maturité CI/CD
NiveauPipeline
Basiquefmt + validate.
Correctfmt + validate + plan en MR.
Proscan + plan artefact + apply manuel + approvals.
AvancéOIDC + policy-as-code + templates + post-checks + audit.
Règle : un pipeline infra ne doit pas seulement exécuter. Il doit contrôler, protéger et documenter.
Parcours Cloud, Linux et réseau
Fondations Linux
SujetÀ savoir faire
Servicessystemctl status/start/stop/restart, logs systemd.
Logsjournalctl, logs Nginx, logs applicatifs.
Ressourcestop, free, df, du, iostat.
Réseaucurl, dig, nc, ss, routes.
Sécuritéusers, permissions, SSH, firewall, certificats.
Commandes indispensables
systemctl status nginx
                            journalctl -u nginx -n 100 --no-pager
                            df -h
                            du -sh /var/log/* | sort -h
                            free -h
                            top
                            ss -tulpn
                            curl -v https://example.com/
                            dig example.com
                            nc -vz host 443
Fondations Cloud
SujetCompétence attendue
ComputeVM, autoscaling, containers, images.
NetworkVPC, subnets, routes, NAT, load balancer.
SecurityIAM, roles, policies, security groups, KMS.
DataManaged DB, backups, snapshots, storage.
DNS / TLSRecords DNS, certificats, renouvellement, validation.
MonitoringCloud metrics, logs, alarms, audit events.
Mini-architecture à construire
Internet
                            │
                            ▼
                            DNS + TLS
                            │
                            ▼
                            Load Balancer
                            │
                            ▼
                            Application VM / Container
                            │
                            ├── logs
                            ├── metrics
                            └── healthcheck
                            │
                            ▼
                            Database managed
                            │
                            ├── backups
                            ├── private access
                            └── monitoring
Objectif : comprendre ce que Terraform crée réellement dans le cloud, pas seulement écrire du HCL.
Parcours Observabilité
Progression observabilité
ÉtapeObjectifLivrable
1Centraliser les logs.Logs app/proxy consultables.
2Ajouter métriques système.CPU/RAM/disque/réseau visibles.
3Ajouter métriques applicatives.RPS, 5xx, p95/p99.
4Créer dashboard global.Vue production en 30 secondes.
5Créer alertes critiques.Service down, 5xx, disque, DB.
6Ajouter runbooks aux alertes.Alerte actionnable.
7Corréler déploiements et incidents.Annotations deploy/Terraform.
Golden signals
Latency:
                            p50, p95, p99

                            Traffic:
                            requests/sec, jobs/min

                            Errors:
                            HTTP 5xx, exceptions, failed jobs

                            Saturation:
                            CPU, RAM, disk, DB connections, queue backlog
Dashboard cible
Production Overview
                            │
                            ├── Availability
                            ├── HTTP 5xx
                            ├── Latency p95 / p99
                            ├── Traffic
                            ├── CPU / RAM / Disk
                            ├── Database health
                            ├── Queue backlog
                            ├── Last deployments
                            └── Active alerts
Alertes minimales
AlerteCondition indicative
Service downHealthcheck KO 2 à 5 minutes.
High 5xx5xx > 2% pendant 5 minutes.
High latencyp95 > seuil pendant 10 minutes.
Disk highDisque > 85%.
DB saturationConnexions ou locks élevés.
Pipeline prod failedJob apply ou deploy prod échoué.
Règle : une alerte doit avoir une action claire et un runbook associé.
Parcours Incidents / SRE
Compétences incident à acquérir
CompétenceObjectif
TriageQualifier impact, gravité, périmètre.
MitigationRestaurer vite avec action réversible.
RollbackRevenir à une version ou config stable.
CommunicationMessages courts, factuels, réguliers.
RCAComprendre cause racine et facteurs contributifs.
Post-mortemTransformer incident en amélioration.
SLOMesurer la fiabilité depuis le point de vue utilisateur.
Exercices simulation
Simulation 1 :
                            Healthcheck applicatif KO.
                            Objectif : diagnostiquer logs + restart contrôlé.

                            Simulation 2 :
                            Disque presque plein.
                            Objectif : identifier dossier, mitigation, prévention.

                            Simulation 3 :
                            Terraform state lock.
                            Objectif : identifier job détenteur, éviter force-unlock abusif.

                            Simulation 4 :
                            Security group DB cassé.
                            Objectif : rollback règle réseau.

                            Simulation 5 :
                            Déploiement app provoque 5xx.
                            Objectif : rollback + post-mortem.
Process incident cible
Alerte
                            │
                            ▼
                            Déclaration incident
                            │
                            ├── gravité
                            ├── canal
                            ├── Incident Commander
                            └── timeline
                            │
                            ▼
                            Mitigation
                            ├── rollback
                            ├── scale
                            ├── feature flag
                            └── patch minimal
                            │
                            ▼
                            Vérification retour nominal
                            │
                            ▼
                            Communication de stabilisation
                            │
                            ▼
                            Post-mortem
                            │
                            ├── RCA
                            ├── actions préventives
                            └── suivi
Maturité SRE
NiveauPratique
DébutantRéagit aux alertes sans procédure claire.
IntermédiaireUtilise runbooks et dashboards.
ProRCA, post-mortems, actions préventives suivies.
AvancéSLO, error budget, GameDays, chaos testing contrôlé.
Objectif SRE : réduire le MTTR, limiter la récidive et améliorer la fiabilité sans bloquer toute capacité de livraison.
Projets pratiques pour valider la RoadMap
Projet 1 : mini plateforme web
ObjectifDéployer une application simple derrière Nginx ou load balancer.
InfraVM ou container, DNS, TLS, firewall/security group.
TerraformModules network + compute + DNS.
CI/CDPipeline plan/apply manuel.
ObservabilitéLogs, healthcheck, dashboard minimal.
Projet 2 : backend distant Terraform
ObjectifMettre en place remote state sécurisé.
ExigencesLocking, chiffrement, versioning, isolation env.
LivrableState dev/staging/prod séparé + documentation.
Projet 3 : pipeline infra complet
ObjectifCréer pipeline GitLab CI/CD Terraform production-ready.
Stagesfmt, validate, security, plan, apply, post-check.
SécuritéVariables protected, runner protégé, approvals.
LivrableMR avec plan lisible + apply manuel protégé.
Projet 4 : simulation incident
ObjectifTester réponse incident sur environnement non-prod.
ScénariosDisque plein, service down, pipeline lock, SG cassé.
LivrablesTimeline, runbook corrigé, post-mortem.
Conseil : chaque projet doit produire un livrable visible : code, pipeline, diagramme, dashboard, runbook ou post-mortem.
Projet final recommandé
Mini production platform
                    │
                    ├── Terraform modules
                    ├── remote state par environnement
                    ├── GitLab CI/CD plan/apply
                    ├── secrets protégés
                    ├── app déployée
                    ├── DNS/TLS
                    ├── logs + metrics
                    ├── dashboard
                    ├── alertes
                    ├── runbooks
                    └── simulation incident + post-mortem
RoadMap de maturité DevOps pour une équipe
Niveaux de maturité équipe
NiveauSituationPriorité
0. ManuelClickOps, changements console, pas de state partagé.Mettre l’infra critique en Terraform.
1. VersionnéTerraform dans Git, mais peu de CI/CD.Ajouter fmt/validate/plan en MR.
2. ContrôléPlan en CI, remote state, apply manuel.Protéger branches, variables, environments.
3. SécuriséScans, approvals, secrets gérés, IAM minimal.Ajouter OIDC, policies, audit.
4. ObservableDashboards, alertes, logs, post-checks.Runbooks et SLO.
5. SRE matureSLO, error budget, GameDays, amélioration continue.Optimisation fiabilité/coût/vitesse.
RoadMap équipe en 5 étapes
Étape 1 : Stop ClickOps
                            ├── inventorier infra
                            ├── créer Terraform baseline
                            └── remote state

                            Étape 2 : CI/CD minimale
                            ├── fmt
                            ├── validate
                            └── plan en MR

                            Étape 3 : Contrôle production
                            ├── branches protégées
                            ├── variables protégées
                            ├── apply manuel
                            └── approvals

                            Étape 4 : Observabilité
                            ├── logs
                            ├── metrics
                            ├── dashboards
                            └── alertes

                            Étape 5 : SRE
                            ├── runbooks
                            ├── post-mortems
                            ├── SLO
                            └── GameDays
KPIs de maturité
Change failure rateCombien de changements provoquent incidents.
MTTRTemps moyen de restauration.
Deployment frequencyCapacité à livrer régulièrement.
Lead timeTemps entre commit et production.
Alert noiseVolume d’alertes inutiles.
Vision mature : DevOps ne consiste pas à tout automatiser aveuglément, mais à automatiser avec garde-fous, observabilité et capacité de récupération.
Checklist finale RoadMap DevOps
Checklist compétences individuelles
CompétenceValidation
LinuxJe sais diagnostiquer service, logs, CPU, RAM, disque.
RéseauJe sais tester DNS, TLS, ports, HTTP, load balancer.
TerraformJe sais lire un plan et expliquer chaque changement.
ModulesJe sais créer modules propres avec inputs/outputs.
StateJe sais configurer remote state, locking et séparation env.
GitLab CI/CDJe sais créer pipeline fmt/validate/plan/apply manuel.
SécuritéJe sais protéger secrets, variables, IAM, runners.
ObservabilitéJe sais créer logs, metrics, dashboards et alertes utiles.
IncidentsJe sais suivre un runbook, mitiger et documenter.
Checklist plateforme production-ready
ÉlémentAttendu
Infra as CodeInfrastructure critique décrite dans Terraform.
Remote stateDistant, chiffré, verrouillé, isolé.
CI/CDPlan en MR, apply manuel prod, artifacts.
EnvironnementsDev/staging/prod séparés.
SecretsPas dans Git, variables protégées ou secret manager.
ApprovalsProduction protégée.
ObservabilitéDashboard + alertes critiques + logs.
RunbooksRollback, restart, saturation, DB, pipeline lock.
Post-mortemProcess RCA et actions préventives.
Objectif final : être capable de livrer une infrastructure fiable, mais aussi de la surveiller, l’expliquer, la réparer et l’améliorer.
Mini-cheat-sheet RoadMap
1. Linux + réseau
                            2. Cloud basics
                            3. Terraform basics
                            4. Modules Terraform
                            5. Remote state + locking
                            6. GitLab CI/CD infra
                            7. Secrets + IAM least privilege
                            8. Environnements dev/staging/prod
                            9. Déploiement contrôlé
                            10. Observabilité
                            11. Runbooks
                            12. Incidents + post-mortems + SRE
4.1 Cheat-sheet DevOps Infra : commandes, debug, audit et production
Cheat-sheet DevOps infra : objectif

Cette cheat-sheet regroupe les commandes et réflexes essentiels pour travailler efficacement sur une infrastructure moderne : Terraform, GitLab CI/CD, Linux, réseau, debugging pipeline, sécurité, audit et vérifications production.

Elle est pensée comme un support opérationnel : avant une merge request, avant un apply production, pendant un incident, ou pour préparer un entretien DevOps.

Principe : une commande DevOps ne doit jamais être lancée mécaniquement. Il faut comprendre le contexte, l’environnement ciblé, le state, le risque et le résultat attendu.
Domaines couverts
DomaineUsage
TerraformInitialiser, valider, planifier, appliquer, importer, inspecter.
StateDiagnostiquer drift, lock, remote state, ressources connues.
GitLab CI/CDAnalyser pipeline, runners, artifacts, variables et environments.
LinuxDiagnostiquer services, logs, CPU, RAM, disque, réseau local.
RéseauTester DNS, TLS, ports, HTTP, load balancer, connectivité.
ProductionVérifier health checks, logs, métriques, alertes et rollback.
SécuritéSecrets, IAM, audit, logs sensibles, variables protégées.
Flux mental avant action
Avant toute commande sensible
                            │
                            ├── Quel environnement ?
                            │     ├── dev
                            │     ├── staging
                            │     └── prod
                            │
                            ├── Quel state Terraform ?
                            │     ├── backend
                            │     ├── key
                            │     └── lock
                            │
                            ├── Quel impact ?
                            │     ├── réseau
                            │     ├── IAM
                            │     ├── database
                            │     ├── compute
                            │     └── DNS
                            │
                            ├── Quel rollback ?
                            │
                            └── Comment vérifier après ?
Commandes à traiter avec prudence
CommandePourquoi prudence
terraform applyModifie réellement l’infrastructure.
terraform destroyDétruit les ressources gérées.
terraform state rmTerraform oublie une ressource sans la supprimer.
terraform force-unlockPeut casser un apply encore actif.
rm -rfSuppression potentiellement irréversible.
systemctl restartPeut provoquer une coupure de service.
Règle production : si une commande peut supprimer, redémarrer, déverrouiller, remplacer ou exposer, elle nécessite une vérification préalable.
Commandes Terraform essentielles
Cycle standard
# Initialiser le dossier Terraform
                            terraform init

                            # Formater le code
                            terraform fmt -recursive
                            terraform fmt -check -recursive

                            # Valider la configuration
                            terraform validate

                            # Générer un plan
                            terraform plan

                            # Générer un plan sauvegardé
                            terraform plan -out=tfplan

                            # Lire un plan binaire en texte
                            terraform show -no-color tfplan

                            # Appliquer le plan exact
                            terraform apply tfplan

                            # Appliquer directement
                            terraform apply

                            # Afficher les outputs
                            terraform output
Bonne pratique : en production, générer un tfplan, le relire, puis appliquer exactement ce plan.
Commandes avec variables
# Plan avec fichier variables
                            terraform plan -var-file="dev.tfvars"
                            terraform plan -var-file="staging.tfvars"
                            terraform plan -var-file="prod.tfvars"

                            # Plan sauvegardé avec tfvars
                            terraform plan -var-file="prod.tfvars" -out=tfplan

                            # Variable inline
                            terraform plan -var="environment=prod"

                            # Utiliser une variable d'environnement
                            export TF_VAR_environment="prod"
                            terraform plan
Lecture rapide du plan
SymboleSignificationRéflexe
+CréationVérifier coût, tags, sécurité.
~ModificationComprendre l’impact.
-/+RemplacementAnalyse obligatoire.
-SuppressionStop si non attendu.
Attention : toute suppression ou recréation en production doit être justifiée avant l’apply.
Structure Terraform propre
versions.tf     # versions Terraform et providers
                    providers.tf    # configuration provider
                    backend.tf      # configuration remote state
                    variables.tf    # inputs
                    locals.tf       # valeurs calculées
                    main.tf         # ressources ou appels modules
                    outputs.tf      # outputs utiles
                    *.tfvars        # valeurs par environnement
State Terraform, drift, import et lock
Inspection du state
# Lister les ressources connues du state
                            terraform state list

                            # Afficher une ressource précise
                            terraform state show aws_instance.web

                            # Afficher les outputs
                            terraform output

                            # Exporter le state courant localement
                            terraform state pull > state-backup.json

                            # Pousser un state modifié
                            # À éviter sauf procédure contrôlée
                            terraform state push state-backup.json
Drift detection
# Voir les écarts entre state et infrastructure réelle
                            terraform plan -refresh-only

                            # Appliquer uniquement la mise à jour du state
                            terraform apply -refresh-only
Attention : un drift peut révéler un hotfix manuel. Ne pas corriger automatiquement sans comprendre.
Import / move / remove
# Importer une ressource existante dans Terraform
                            terraform import aws_security_group.web sg-0123456789abcdef0

                            # Déplacer une ressource dans le state
                            terraform state mv aws_instance.web aws_instance.app

                            # Retirer une ressource du state sans la détruire
                            terraform state rm aws_instance.web
State lock
# Déverrouiller un lock orphelin
                            # Seulement après preuve qu'aucun apply n'est actif
                            terraform force-unlock LOCK_ID
Remote state
data "terraform_remote_state" "network" {
                            backend = "s3"

                            config = {
                            bucket = "company-terraform-state-prod"
                            key    = "prod/network/terraform.tfstate"
                            region = "eu-west-3"
                            }
                            }
Règle : ne jamais faire force-unlock, state rm ou state push sans sauvegarde, revue et compréhension exacte.
Diagnostic state rapide
SymptômeCommandeBut
Ressource inconnueterraform state listVoir si Terraform la gère.
Diff inattenduterraform plan -refresh-onlyDétecter drift.
Apply bloquéLogs pipeline + lock IDIdentifier détenteur du lock.
Ressource existanteterraform importRattacher au state.
GitLab CI/CD : commandes, YAML et debug rapide
Git essentiel pour infra
# État du repo
                            git status

                            # Créer une branche
                            git checkout -b infra/change-name

                            # Voir les changements
                            git diff
                            git diff --staged

                            # Ajouter / commit
                            git add .
                            git commit -m "Update Terraform infrastructure"

                            # Historique
                            git log --oneline -10

                            # Revenir à un commit par revert
                            git revert <commit_id>

                            # Voir fichiers modifiés
                            git show --stat
GitLab Runner
# Vérifier runners
                            gitlab-runner verify
                            gitlab-runner list

                            # Service runner
                            systemctl status gitlab-runner --no-pager
                            journalctl -u gitlab-runner -n 100 --no-pager
                            journalctl -u gitlab-runner -f
Template pipeline Terraform minimal
stages:
                            - lint
                            - validate
                            - plan
                            - apply

                            variables:
                            TF_IN_AUTOMATION: "true"
                            TF_INPUT: "false"
                            TF_ROOT: "infra/live/prod/app"

                            default:
                            image: hashicorp/terraform:1.6.6
                            before_script:
                            - cd "$TF_ROOT"
                            - terraform init

                            terraform_fmt:
                            stage: lint
                            script:
                            - terraform fmt -check -recursive

                            terraform_validate:
                            stage: validate
                            script:
                            - terraform validate

                            terraform_plan:
                            stage: plan
                            script:
                            - terraform plan -out=tfplan
                            - terraform show -no-color tfplan > plan.txt
                            artifacts:
                            paths:
                            - "$TF_ROOT/tfplan"
                            - "$TF_ROOT/plan.txt"
                            expire_in: 3 days

                            terraform_apply:
                            stage: apply
                            script:
                            - terraform apply tfplan
                            when: manual
                            rules:
                            - if: '$CI_COMMIT_BRANCH == "main"'
Bonne pratique : conserver le plan lisible en artifact pour review et audit.
Mots-clés GitLab utiles
Mot-cléUsage
stagesOrdre logique du pipeline.
rulesConditions d’exécution des jobs.
needsDépendances rapides entre jobs.
artifactsConserver plan, rapports, logs utiles.
environmentAssocier job à dev/staging/prod.
when: manualApply manuel contrôlé.
tagsSélectionner runner adapté.
Linux : diagnostic production rapide
État système
# Charge et uptime
                            uptime

                            # CPU / process
                            top
                            ps aux --sort=-%cpu | head
                            ps aux --sort=-%mem | head

                            # Mémoire
                            free -h
                            dmesg | grep -i "killed process"

                            # Disque
                            df -h
                            df -i
                            du -sh /var/log/* | sort -h
                            du -sh /tmp/* | sort -h

                            # Réseau local
                            ss -tulpn
                            ip addr
                            ip route
Services systemd
# Statut service
                            systemctl status nginx --no-pager
                            systemctl status app.service --no-pager

                            # Redémarrage contrôlé
                            sudo systemctl restart app.service

                            # Activer/désactiver au boot
                            sudo systemctl enable app.service
                            sudo systemctl disable app.service
Logs
# Logs service
                            journalctl -u app.service -n 100 --no-pager
                            journalctl -u app.service -f

                            # Erreurs système récentes
                            journalctl -p err -n 100 --no-pager

                            # Nginx
                            tail -f /var/log/nginx/access.log
                            tail -f /var/log/nginx/error.log

                            # Chercher erreurs HTTP 500
                            grep " 500 " /var/log/nginx/access.log | tail

                            # Logs depuis une heure
                            journalctl --since "1 hour ago" --no-pager
Saturation disque
df -h
                            du -sh /var/log/* | sort -h
                            journalctl --disk-usage

                            # Nettoyage journal systemd contrôlé
                            sudo journalctl --vacuum-time=7d

                            # Attention : vérifier avant suppression manuelle
Règle : ne jamais supprimer des fichiers dans un répertoire de base de données pour libérer de l’espace.
Diagnostic par symptôme
SymptômeCommandesHypothèse
Service downsystemctl status, journalctl -uCrash, config, dépendance KO.
Lenteurtop, free -h, logs appCPU, RAM, DB, API externe.
Disque pleindf -h, du -shLogs, backups, uploads.
Port non ouvertss -tulpn, nc -vzService non lancé, firewall, bind.
Réseau, DNS, HTTP, TLS et load balancer
DNS
# Résolution DNS
                            dig example.com
                            dig +short example.com
                            nslookup example.com

                            # Vérifier un record précis
                            dig A example.com
                            dig CNAME www.example.com
                            dig TXT example.com

                            # Voir TTL
                            dig example.com
HTTP / HTTPS
# Tester endpoint
                            curl -v https://example.com/
                            curl -fsS https://example.com/health/

                            # Voir headers
                            curl -I https://example.com/

                            # Tester avec host header
                            curl -H "Host: example.com" http://IP_ADDRESS/

                            # Mesurer temps
                            curl -w "@curl-format.txt" -o /dev/null -s https://example.com/
TLS / certificats
# Vérifier certificat TLS
                            openssl s_client -connect example.com:443 -servername example.com

                            # Dates certificat
                            echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null \
                            | openssl x509 -noout -dates

                            # Certbot
                            sudo certbot certificates
                            sudo certbot renew --dry-run
Connectivité ports
# Tester port TCP
                            nc -vz example.com 443
                            nc -vz db.internal 5432
                            nc -vz redis.internal 6379

                            # Ports ouverts localement
                            ss -tulpn

                            # Routes
                            ip route
                            traceroute example.com
Attention : un problème HTTP 502/503/504 peut venir du load balancer, du backend, du healthcheck, du réseau ou de l’application.
Diagnostic HTTP rapide
CodeCause fréquenteVérification
502Backend invalide ou indisponible.Logs proxy + service app.
503Aucun backend disponible.Targets LB, healthcheck, autoscaling.
504Timeout upstream.App lente, DB lente, timeout proxy.
TLS errorCertificat expiré ou mauvais SNI.openssl s_client, certbot, LB cert.
NXDOMAINDNS absent ou zone incorrecte.dig, zone DNS, registrar.
Vérifications production avant / pendant / après apply
Avant apply production
ContrôleCommande / preuve
Bon environnementAfficher $CI_ENVIRONMENT_NAME, $TF_ROOT, backend key.
Plan reluterraform show -no-color tfplan
Pas de destroy inattenduReview du plan.
State distantterraform init avec backend attendu.
Monitoring prêtDashboards ouverts.
Rollback connuRunbook ou procédure.
Pendant apply
# Ne pas lancer plusieurs apply
                            # Surveiller logs du job
                            # Noter toute ressource en erreur
                            # Ne pas force-unlock sans preuve
                            # Si échec partiel : relancer plan avant correction
Après apply production
# Outputs Terraform
                            terraform output

                            # Health checks
                            curl -fsS https://example.com/health/
                            curl -fsS https://example.com/api/status/

                            # Logs applicatifs
                            journalctl -u app.service -n 100 --no-pager

                            # Nginx errors
                            tail -n 100 /var/log/nginx/error.log

                            # Vérifier erreurs 5xx
                            grep " 500 " /var/log/nginx/access.log | tail
Signaux de santé
DomaineSignal attendu
HTTPHealthcheck OK, 5xx stables.
Latencep95/p99 sans hausse anormale.
InfraCPU/RAM/disque normaux.
DBConnexions, locks, slow queries OK.
AlertingAucune nouvelle alerte critique.
Bonne pratique : un apply réussi n’est pas suffisant. La production doit être vérifiée par des signaux réels.
Debug pipeline Terraform / GitLab
Pipeline bloqué ou failed
SymptômeCause probableVérification
Job pendingRunner indisponible ou mauvais tags.Runner list, tags job.
Variable videVariable protected/scoped inaccessible.Branche, environnement, scope variable.
terraform init échoueBackend ou credentials.Bucket, state, IAM, réseau.
State lockAutre apply actif ou lock orphelin.Job détenteur, logs pipeline.
Artifact absentMauvais path ou expiration.artifacts.paths, dependencies, needs.
Plan local différent CIVariables ou versions différentes.Terraform version, provider lock, tfvars.
Méthode de debug
Job échoué
                            │
                            ▼
                            Lire logs depuis le début
                            │
                            ├── image Docker
                            ├── dossier courant
                            ├── variables non sensibles
                            ├── terraform version
                            ├── terraform init
                            ├── provider error
                            └── backend / state
                            │
                            ▼
                            Corriger cause minimale
                            │
                            ▼
                            Relancer plan
                            │
                            ▼
                            Apply seulement si plan OK
Commandes debug CI sûres
# Afficher contexte non sensible
                            echo "Branch: $CI_COMMIT_BRANCH"
                            echo "Environment: $CI_ENVIRONMENT_NAME"
                            echo "Terraform root: $TF_ROOT"
                            terraform --version

                            # Vérifier présence variable sans l'afficher
                            if [ -z "$AWS_ACCESS_KEY_ID" ]; then
                            echo "AWS_ACCESS_KEY_ID is missing"
                            exit 1
                            else
                            echo "AWS_ACCESS_KEY_ID is present"
                            fi

                            # Terraform debug utile
                            terraform providers
                            terraform validate
                            terraform plan -refresh-only
À ne pas faire
# Dangereux : affiche secrets potentiels
                            env
                            printenv
                            echo "$AWS_SECRET_ACCESS_KEY"

                            # Dangereux en job sensible
                            set -x

                            # Dangereux sans analyse
                            terraform force-unlock LOCK_ID
Règle : ne jamais déboguer un secret en l’affichant. Vérifier sa présence, pas sa valeur.
Sécurité, secrets, audit et contrôles rapides
Secrets GitLab / CI
ContrôleAttendu
MaskedSecrets masqués dans logs.
ProtectedSecrets prod disponibles seulement branches/tags protégés.
Environment scopedSecrets limités à dev/staging/prod.
RotationProcédure connue et testée.
OIDCPréférer credentials temporaires si possible.
Least privilegeRôle CI limité aux actions nécessaires.
Secret scanning local
# Exemples d'outils possibles
                            gitleaks detect
                            trufflehog filesystem .
                            detect-secrets scan

                            # Recherche simple à la main
                            grep -R "AWS_SECRET" .
                            grep -R "PRIVATE KEY" .
                            grep -R "password" .
Scan IaC
# Checkov
                            checkov -d .

                            # tfsec
                            tfsec .

                            # Trivy config
                            trivy config .

                            # Terraform format/validate
                            terraform fmt -check -recursive
                            terraform validate
Audit rapide après incident
QuestionOù chercher
Qui a lancé le pipeline ?GitLab pipeline / job details.
Quel commit a changé l’infra ?MR, commit, plan artifact.
Quel rôle cloud a agi ?Cloud audit logs / CloudTrail.
Un secret a-t-il fuité ?Logs CI, artifacts, Git history.
Le state a-t-il été modifié ?Backend state versioning / logs.
Attention : les artifacts peuvent contenir des informations sensibles. Ne jamais archiver tout le workspace par facilité.
.gitignore Terraform minimal
.terraform/
                    *.tfstate
                    *.tfstate.*
                    crash.log
                    crash.*.log
                    *.tfvars
                    *.tfvars.json
                    override.tf
                    override.tf.json
                    *_override.tf
                    *_override.tf.json
Réponses courtes pour entretien DevOps
Terraform
J’utilise Terraform pour décrire l’infrastructure as code,
                            avec une structure claire en modules, variables, outputs et environnements séparés.
                            Je fais toujours relire le plan avant apply, surtout en production.
                            Je fais attention au remote state, au locking, au drift et aux risques de destroy/replace.
                            Mon approche est de rendre l’infrastructure reproductible, traçable et contrôlée.
GitLab CI/CD infra
Oui, j’ai travaillé sur des pipelines GitLab CI/CD orientés infrastructure.
                            Je structure les étapes fmt, validate, security scan, plan, review et apply manuel.
                            J’utilise des artifacts pour conserver le plan, des variables protégées et des branches protégées.
                            En production, l’apply doit être contrôlé, approuvé et vérifié après exécution.
State Terraform
Je considère le state Terraform comme un composant critique.
                            En production, il doit être distant, chiffré, verrouillé, versionné et isolé par environnement.
                            Je fais attention au drift, aux imports et aux opérations sensibles comme state rm ou force-unlock.
                            Je ne commite jamais de tfstate dans Git.
Incidents production
Oui, j’ai déjà géré des incidents production.
                            Ma méthode est de qualifier l’impact, stabiliser, mitiger, restaurer le service,
                            puis analyser la cause racine à froid.
                            Je privilégie rollback, contournement ou correction minimale selon le contexte.
                            Après incident, je formalise un post-mortem avec actions préventives.
Secrets et sécurité CI
Je fais attention à ne jamais stocker de secrets dans Git.
                            J’utilise des variables GitLab masked, protected et scopées par environnement.
                            Je privilégie les credentials courts, OIDC ou secret manager lorsque c’est possible.
                            Côté cloud, j’applique le principe du moindre privilège avec des rôles séparés par environnement.
Observabilité
Je mets en place logs, métriques, alertes et dashboards pour piloter la production.
                            Les signaux importants sont les 5xx, la latence p95/p99, la saturation système,
                            les connexions DB, les queues et les échecs pipeline.
                            Une bonne alerte doit être actionnable et liée à un runbook.
Formule synthétique très professionnelle
Mon approche DevOps est orientée production :
                    infrastructure as code, pipelines contrôlés, secrets protégés, observabilité,
                    rollback documenté et amélioration continue après incident.
Checklist opérationnelle finale
Avant merge request infra
PointOK ?
terraform fmt -check -recursiveFormat validé.
terraform validateConfiguration valide.
Plan généréPlan lisible en artifact.
Destroy/replace relusJustifiés ou absents.
Secrets absentsPas de secret dans Git, logs, plan.
Scan IaCPas de risque bloquant.
RollbackProcédure claire.
Avant apply production
Bon environnementProduction clairement ciblée.
Bon stateBackend distant + key correcte.
Locking actifPas d’apply concurrent.
Approval obtenuReviewer compétent.
Fenêtre adaptéeSi changement risqué.
Dashboards ouvertsSurveillance prête.
Après apply production
ZoneValidation
TerraformApply terminé sans erreur, outputs cohérents.
CloudRessources healthy.
HTTPHealthcheck OK.
LogsPas de nouvelle erreur critique.
Metrics5xx, latence, CPU/RAM stables.
DBConnexions, locks, slow queries OK.
AlertingAucune alerte critique nouvelle.
DocumentationChange request mise à jour.
Définition d’un bon geste DevOps : commande comprise, impact maîtrisé, résultat vérifié, rollback connu, trace conservée.
Ultra cheat-sheet
terraform fmt -check -recursive
                            terraform validate
                            terraform plan -out=tfplan
                            terraform show -no-color tfplan > plan.txt
                            terraform apply tfplan
                            terraform plan -refresh-only
                            terraform state list

                            git status
                            git diff
                            git log --oneline -10

                            systemctl status app.service
                            journalctl -u app.service -n 100
                            df -h
                            free -h
                            curl -fsS https://example.com/health/
                            dig example.com
                            nc -vz host port
1.5 Design Terraform avancé : naming, locals, validations, for_each, lifecycle et dépendances
Le design Terraform avancé : écrire du code sûr, lisible et stable

Le design Terraform avancé ne consiste pas à rendre le code “plus intelligent”. Il consiste à rendre l’infrastructure prévisible, lisible, contrôlée, réutilisable et moins dangereuse en production.

Un bon code Terraform permet à un autre DevOps de comprendre rapidement : quels paramètres sont exposés, quelles valeurs sont calculées, quelles ressources seront créées, quelles dépendances existent, quels garde-fous protègent les ressources critiques et comment le plan doit être relu.

Objectif professionnel : un module Terraform doit être simple à utiliser, difficile à mal utiliser, stable dans le temps et clair à relire dans une merge request.
Les piliers du design Terraform
PilierButExemple
NamingCréer des noms prévisibles et cohérents.project-env-component-region
LocalsCentraliser les valeurs calculées.Préfixes, tags, maps, conventions.
ValidationsBloquer les mauvaises entrées tôt.Environnement limité à dev/staging/prod.
for_eachCréer plusieurs ressources avec des clés stables.Subnets, DNS records, security rules.
LifecycleProtéger ou contrôler les changements sensibles.prevent_destroy sur database.
DépendancesLaisser Terraform construire un graphe propre.Références directes plutôt que depends_on abusif.
Vision globale
variables.tf
                            │
                            ├── inputs typés
                            ├── descriptions
                            ├── defaults sûrs
                            └── validations
                            │
                            ▼
                            locals.tf
                            │
                            ├── name_prefix
                            ├── common_tags
                            ├── maps normalisées
                            └── valeurs calculées
                            │
                            ▼
                            main.tf
                            │
                            ├── resources
                            ├── for_each / dynamic blocks
                            ├── lifecycle
                            └── dépendances implicites
                            │
                            ▼
                            outputs.tf
                            │
                            ├── valeurs utiles
                            ├── IDs nécessaires
                            └── aucun secret inutile
Bon design vs mauvais design
Bon designMauvais design
Noms prévisibles et cohérents.Noms codés en dur partout.
Variables typées et validées.Variables libres sans contraintes.
Modules spécialisés et lisibles.Module géant “qui fait tout”.
for_each avec clés stables.count fragile sur listes réordonnées.
Lifecycle sur ressources critiques.Database destructible par erreur.
Outputs minimaux.Outputs bavards ou sensibles.
Règle : un module trop générique, rempli de conditions et de cas spéciaux, devient souvent plus dangereux qu’un module simple et spécialisé.
Naming Terraform : conventions lisibles et robustes

Le naming est fondamental. Il permet d’identifier rapidement à quel projet, environnement, composant, région ou équipe appartient une ressource.

Convention recommandée
locals {
                            name_prefix = "${var.project}-${var.environment}-${var.component}"

                            common_tags = {
                            Project     = var.project
                            Environment = var.environment
                            Component   = var.component
                            ManagedBy   = "terraform"
                            Owner       = var.owner
                            }
                            }
Exemples de noms
RessourceNom recommandé
Load balancer API prodideo-prod-api-alb
Security group web stagingideo-staging-web-sg
Database productionideo-prod-main-db
Redis devideo-dev-cache-redis
Bucket logsideo-prod-logs-eu-west-3
Bonne pratique : les noms doivent permettre de reconnaître une ressource sans ouvrir 10 écrans dans la console cloud.
Variables de naming
variable "project" {
                            description = "Project name used in resource naming."
                            type        = string
                            }

                            variable "environment" {
                            description = "Environment name."
                            type        = string

                            validation {
                            condition     = contains(["dev", "staging", "prod"], var.environment)
                            error_message = "Environment must be dev, staging, or prod."
                            }
                            }

                            variable "component" {
                            description = "Application or infrastructure component."
                            type        = string
                            }

                            variable "owner" {
                            description = "Team or owner responsible for this resource."
                            type        = string
                            }
Nommage : erreurs fréquentes
ErreurConséquence
Noms codés en durDuplication et conflits entre environnements.
Pas d’environnement dans le nomConfusion dev/staging/prod.
Noms trop longsLimites provider dépassées.
Noms non stablesTerraform peut vouloir remplacer des ressources.
Noms avec caractères non autorisésPlan ou apply échoue selon provider.
Attention : changer le nom d’une ressource peut parfois forcer son remplacement. Toujours relire le plan.
Locals : centraliser les valeurs calculées

Les locals permettent de calculer une fois des valeurs réutilisées partout : préfixes, tags, noms, maps normalisées, règles transformées, listes filtrées. Ils rendent le code plus lisible et évitent les répétitions.

Exemple propre de locals.tf
locals {
                            name_prefix = "${var.project}-${var.environment}-${var.component}"

                            common_tags = merge(
                            {
                            Project     = var.project
                            Environment = var.environment
                            Component   = var.component
                            ManagedBy   = "terraform"
                            },
                            var.extra_tags
                            )

                            is_prod = var.environment == "prod"

                            default_backup_retention_days = local.is_prod ? 14 : 3
                            default_deletion_protection   = local.is_prod ? true : false
                            }
Utilisation dans une ressource
resource "aws_security_group" "web" {
                            name        = "${local.name_prefix}-web-sg"
                            description = "Security group for web traffic"
                            vpc_id      = var.vpc_id

                            tags = local.common_tags
                            }
Bonne pratique : si une expression est répétée plus de deux fois, elle mérite probablement un local.
Cas d’usage des locals
UsageExemple
Préfixe de nom${var.project}-${var.environment}
Tags communsProject, Environment, Owner, ManagedBy.
Valeur conditionnelleBackup plus long en production.
Map normaliséeTransformer une liste en map pour for_each.
Feature flagsActiver monitoring seulement en staging/prod.
Locals à éviter
# Mauvais : local trop magique et illisible
                            locals {
                            everything = {
                            for x in var.services :
                            x.name => merge(x, {
                            final_name = "${var.project}-${var.environment}-${x.name}"
                            enabled    = try(x.enabled, true)
                            settings   = try(x.settings, {})
                            })
                            }
                            }
Attention : les locals doivent clarifier le code, pas créer une couche de magie que personne ne sait déboguer.
Diagramme d’usage
variables brutes
                    │
                    ▼
                    locals
                    ├── conventions
                    ├── calculs
                    ├── tags
                    ├── defaults intelligents
                    └── maps propres
                    │
                    ▼
                    resources lisibles
                    │
                    ▼
                    outputs utiles
Validations : bloquer les mauvaises entrées avant production

Les validations Terraform permettent d’éviter des erreurs de configuration avant le plan ou l’apply. Elles sont essentielles pour les modules partagés, car elles empêchent les utilisateurs du module de passer des valeurs dangereuses, incohérentes ou non supportées.

Validation d’environnement
variable "environment" {
                            description = "Deployment environment."
                            type        = string

                            validation {
                            condition     = contains(["dev", "staging", "prod"], var.environment)
                            error_message = "Environment must be dev, staging, or prod."
                            }
                            }
Validation CIDR
variable "vpc_cidr" {
                            description = "CIDR block for the VPC."
                            type        = string

                            validation {
                            condition     = can(cidrhost(var.vpc_cidr, 0))
                            error_message = "vpc_cidr must be a valid CIDR block."
                            }
                            }
Validation taille instance
variable "instance_type" {
                            description = "EC2 instance type."
                            type        = string

                            validation {
                            condition = contains([
                            "t3.micro",
                            "t3.small",
                            "t3.medium"
                            ], var.instance_type)

                            error_message = "Instance type must be one of the approved values."
                            }
                            }
Validations utiles en production
VariableValidation recommandée
environmentLimiter à dev, staging, prod.
allowed_cidr_blocksInterdire 0.0.0.0/0 sur ports sensibles.
backup_retention_daysMinimum plus élevé en production.
deletion_protectionForcer true en production pour DB.
instance_typeLimiter à une liste approuvée.
domain_nameVérifier format ou suffixe autorisé.
Validation objet complexe
variable "services" {
                            description = "Map of services to deploy."
                            type = map(object({
                            image         = string
                            desired_count = number
                            public        = bool
                            }))

                            validation {
                            condition = alltrue([
                            for service in var.services :
                            service.desired_count >= 1
                            ])
                            error_message = "Each service must have desired_count greater than or equal to 1."
                            }
                            }
Bonne pratique : une validation doit produire un message d’erreur clair, compréhensible par un nouveau DevOps.
count, for_each et dynamic blocks

count et for_each permettent de créer plusieurs ressources. En production, for_each est souvent préférable car il utilise des clés stables, alors que count dépend des index de liste.

count : simple mais fragile
resource "aws_subnet" "private" {
                            count = length(var.private_subnets)

                            vpc_id     = var.vpc_id
                            cidr_block = var.private_subnets[count.index]

                            tags = merge(local.common_tags, {
                            Name = "${local.name_prefix}-private-${count.index + 1}"
                            })
                            }
Risque : si la liste est réordonnée, les index changent. Terraform peut vouloir remplacer ou modifier les mauvaises ressources.
Quand utiliser count ?
Activation simplecount = var.enabled ? 1 : 0
Ressource optionnelleCréer ou non une ressource unique.
Liste non critiqueCas simples avec faible risque de réordonnancement.
for_each : recommandé pour les collections stables
variable "private_subnets" {
                            type = map(object({
                            cidr_block        = string
                            availability_zone = string
                            }))
                            }

                            resource "aws_subnet" "private" {
                            for_each = var.private_subnets

                            vpc_id            = var.vpc_id
                            cidr_block        = each.value.cidr_block
                            availability_zone = each.value.availability_zone

                            tags = merge(local.common_tags, {
                            Name = "${local.name_prefix}-private-${each.key}"
                            })
                            }
Exemple tfvars
private_subnets = {
                            "a" = {
                            cidr_block        = "10.20.11.0/24"
                            availability_zone = "eu-west-3a"
                            }

                            "b" = {
                            cidr_block        = "10.20.12.0/24"
                            availability_zone = "eu-west-3b"
                            }
                            }
Bonne pratique : utiliser for_each avec des clés métier stables : a, b, api, worker, admin.
Dynamic blocks : utile mais à doser
resource "aws_security_group" "service" {
                    name   = "${local.name_prefix}-sg"
                    vpc_id = var.vpc_id

                    dynamic "ingress" {
                    for_each = var.ingress_rules

                    content {
                    description = ingress.value.description
                    from_port   = ingress.value.from_port
                    to_port     = ingress.value.to_port
                    protocol    = ingress.value.protocol
                    cidr_blocks = ingress.value.cidr_blocks
                    }
                    }

                    tags = local.common_tags
                    }
Attention : trop de dynamic blocks rendent le module difficile à lire. Pour les règles critiques, la clarté vaut souvent mieux que la généricité.
Lifecycle : protéger et contrôler les changements sensibles

Le bloc lifecycle permet d’ajouter des garde-fous sur certaines ressources : empêcher la destruction, créer avant de détruire, ignorer certains changements ou remplacer une ressource quand une dépendance change.

prevent_destroy
resource "aws_db_instance" "main" {
                            identifier = "${local.name_prefix}-db"

                            lifecycle {
                            prevent_destroy = true
                            }
                            }

Très utile pour les ressources critiques : bases de données, buckets contenant des données, clés KMS, volumes persistants.

create_before_destroy
resource "aws_launch_template" "app" {
                            name_prefix = "${local.name_prefix}-"

                            lifecycle {
                            create_before_destroy = true
                            }
                            }

Utile quand on veut réduire le downtime en créant la nouvelle ressource avant de supprimer l’ancienne.

Attention : prevent_destroy protège, mais ne remplace pas la revue du plan.
ignore_changes
resource "aws_autoscaling_group" "app" {
                            name = "${local.name_prefix}-asg"

                            desired_capacity = var.desired_capacity

                            lifecycle {
                            ignore_changes = [
                            desired_capacity
                            ]
                            }
                            }

Peut être utile si l’autoscaling modifie une valeur que Terraform ne doit pas corriger à chaque plan.

Lifecycle : cas d’usage
OptionUsageRisque
prevent_destroyProtéger DB, buckets, volumes.Peut bloquer un changement voulu.
create_before_destroyRéduire downtime sur ressources remplaçables.Peut nécessiter noms uniques.
ignore_changesIgnorer drift contrôlé.Peut masquer un vrai problème.
replace_triggered_byForcer remplacement si dépendance change.À utiliser avec prudence.
Règle : ignore_changes ne doit pas servir à cacher un drift qu’on ne comprend pas.
Dépendances Terraform : laisser le graphe travailler

Terraform construit un graphe de dépendances à partir des références entre ressources. Dans la plupart des cas, il ne faut pas ajouter depends_on manuellement : une référence explicite suffit.

Dépendance implicite recommandée
resource "aws_security_group" "web" {
                            name   = "${local.name_prefix}-web-sg"
                            vpc_id = aws_vpc.main.id
                            }

                            resource "aws_instance" "web" {
                            ami                    = var.ami_id
                            instance_type          = var.instance_type
                            vpc_security_group_ids = [aws_security_group.web.id]
                            }

Ici, l’instance dépend automatiquement du security group parce qu’elle référence son ID.

depends_on explicite
resource "aws_instance" "app" {
                            ami           = var.ami_id
                            instance_type = var.instance_type

                            depends_on = [
                            aws_cloudwatch_log_group.app
                            ]
                            }
Attention : depends_on doit rester exceptionnel. Trop de dépendances manuelles rendent le graphe rigide et difficile à comprendre.
Quand utiliser depends_on ?
CasJustification
Dépendance non visible dans les attributsTerraform ne peut pas la deviner.
Ordre requis par providerAPI externe nécessite une ressource prête.
Module dépendant d’un autre moduleSeulement si les outputs ne créent pas déjà la dépendance.
Provisioning spécialCas rares, souvent à éviter.
Diagramme du graphe
aws_vpc.main
                            │
                            ▼
                            aws_subnet.private
                            │
                            ▼
                            aws_security_group.app
                            │
                            ▼
                            aws_instance.app
                            │
                            ▼
                            aws_lb_target_group_attachment.app
Pièges de dépendances
Dépendance circulaireDeux ressources se référencent mutuellement.
depends_on globalRalentit et rigidifie tout le plan.
Data source trop tôtLecture d’un objet pas encore créé.
Module trop coupléChaque changement force trop d’autres modules.
Bonne pratique : préférer les références directes aux dépendances manuelles. Le code devient plus naturel et plus facile à maintenir.
Design avancé des modules Terraform

Un module Terraform est une API d’infrastructure. Son design doit être stable, documenté, sécurisé par défaut et assez simple pour être utilisé sans lire tout son code interne.

Contrat d’un module
ÉlémentBonne pratique
InputsPeu nombreux, typés, décrits et validés.
OutputsSeulement les valeurs utiles aux consommateurs.
DefaultsSûrs par défaut, jamais trop permissifs.
READMEExemple d’usage, inputs, outputs, limitations.
VersioningTags Git ou registry, pas de production sur main.
ResponsabilitéUn module doit avoir un périmètre clair.
Module spécialisé
module "api_service" {
                            source = "../../modules/compute-service"

                            project      = var.project
                            environment  = var.environment
                            component    = "api"
                            image        = var.api_image
                            desired_count = 3

                            vpc_id     = module.network.vpc_id
                            subnet_ids = module.network.private_subnet_ids

                            tags = local.common_tags
                            }
Module trop générique : danger
module "universal_resource"
                            │
                            ├── create_vpc
                            ├── create_db
                            ├── create_lb
                            ├── create_dns
                            ├── enable_cache
                            ├── enable_iam
                            ├── enable_monitoring
                            ├── 80 variables
                            └── 25 conditions
Problème : un module “universel” devient souvent impossible à relire, difficile à tester et dangereux à modifier.
Bon découpage
modules/
                            ├── network
                            ├── security-group
                            ├── load-balancer
                            ├── compute-service
                            ├── database-postgres
                            ├── redis-cache
                            ├── dns-record
                            └── monitoring-alarm
Règles de design module
SpécialiserUn module fait une chose importante.
Limiter optionsExposer seulement ce qui doit varier.
DocumenterREADME + exemples + limites.
Testerfmt, validate, scan, example plan.
VersionnerTag stable pour production.
Design Terraform orienté production

En production, le design Terraform doit réduire les erreurs humaines, limiter le blast radius, protéger les données, rendre les plans lisibles et faciliter le rollback ou la mitigation.

Garde-fous production
ZoneGarde-fou
Databasedeletion_protection, backups, prevent_destroy.
StateRemote backend, locking, versioning, chiffrement.
SecretsPas de secrets dans Git, outputs ou logs.
RéseauPas d’ouverture large sur ports sensibles.
IAMMoindre privilège, pas de wildcard inutile.
PlanReview obligatoire des destroy/replace.
ModulesVersion stable, pas de branche mutable en prod.
Exemple DB production
resource "aws_db_instance" "main" {
                            identifier              = "${local.name_prefix}-db"
                            engine                  = "postgres"
                            instance_class          = var.instance_class
                            allocated_storage       = var.allocated_storage
                            backup_retention_period = local.default_backup_retention_days
                            deletion_protection     = local.is_prod ? true : var.deletion_protection

                            lifecycle {
                            prevent_destroy = true
                            }

                            tags = local.common_tags
                            }
Review production du plan
terraform plan
                            │
                            ▼
                            Review obligatoire
                            ├── destroy ?
                            ├── replace ?
                            ├── DB touchée ?
                            ├── IAM modifié ?
                            ├── réseau ouvert ?
                            ├── DNS changé ?
                            ├── secrets affichés ?
                            └── coût modifié ?
                            │
                            ▼
                            Décision
                            ├── OK : apply contrôlé
                            └── KO : correction avant merge
Production design checklist
State isoléProd séparé de dev/staging.
Variables validéesEntrées dangereuses bloquées.
Naming clairRessources identifiables.
Tags completsOwner, env, cost, managed by Terraform.
Lifecycle adaptéProtection des ressources critiques.
Outputs sobresAucune valeur sensible inutile.
Plan lisiblePetit changement, review possible.
Objectif : rendre l’erreur difficile, visible tôt et récupérable rapidement.
Anti-patterns du design Terraform avancé
Anti-patternPourquoi c’est dangereuxCorrection professionnelle
Noms codés en dur partoutConflits, duplication, confusion env.Utiliser locals.name_prefix.
Variables sans typeErreurs détectées tard.Types explicites et validations.
Module trop génériqueIllisible, fragile, difficile à tester.Modules spécialisés par responsabilité.
count sur listes critiquesRéordonnancement peut provoquer mauvais diff.for_each avec clés stables.
ignore_changes abusifMasque drift ou problème réel.Limiter aux cas justifiés et documentés.
depends_on partoutGraphe rigide, plan moins lisible.Utiliser références directes.
Outputs sensiblesFuite dans logs, state ou remote state.Outputs minimaux, sensitive si nécessaire.
Pas de lifecycle sur DBSuppression accidentelle possible.prevent_destroy et protections provider.
Mauvais modèle
main.tf énorme
                            ├── noms codés en dur
                            ├── variables non typées
                            ├── count partout
                            ├── depends_on partout
                            ├── secrets en outputs
                            ├── pas de validations
                            └── pas de garde-fous lifecycle
Résultat : plans bruyants, changements risqués, maintenance difficile.
Bon modèle
Design clair
                            ├── variables typées
                            ├── validations utiles
                            ├── locals lisibles
                            ├── naming standardisé
                            ├── for_each stable
                            ├── lifecycle ciblé
                            ├── outputs minimaux
                            └── modules spécialisés
Résultat : code plus lisible, plan plus sûr, production mieux protégée.
Checklist Design Terraform avancé
Checklist code
PointValidation attendue
NamingConvention claire via locals.name_prefix.
TagsTags communs appliqués partout où possible.
VariablesTypes, descriptions, defaults sûrs.
ValidationsValeurs dangereuses ou invalides bloquées.
LocalsCalculs centralisés, lisibles, non magiques.
for_eachClés stables pour collections critiques.
LifecycleRessources critiques protégées.
OutputsUtiles, minimaux, non sensibles.
ModulesResponsabilité claire, README, version stable.
Checklist review production
QuestionPourquoi
Le plan contient-il un destroy ?Risque de suppression.
Le plan contient-il un replace ?Risque de downtime ou perte d’identité ressource.
Le naming a-t-il changé ?Peut forcer remplacement.
Un count a-t-il été modifié ?Risque d’index instable.
Un ignore_changes cache-t-il un drift ?Risque de masquer un vrai problème.
Une ressource data est-elle touchée ?Risque élevé.
Les secrets apparaissent-ils ?Risque sécurité.
Le rollback est-il clair ?Indispensable avant apply prod.
Définition d’un bon design Terraform : noms prévisibles, variables validées, locals lisibles, collections stables, lifecycle ciblé, dépendances naturelles et production protégée.
Mini-cheat-sheet
# Naming
                            local.name_prefix = "${var.project}-${var.environment}-${var.component}"

                            # Validation
                            contains(["dev", "staging", "prod"], var.environment)

                            # Prefer stable keys
                            for_each = var.services

                            # Optional resource
                            count = var.enabled ? 1 : 0

                            # Critical resource protection
                            lifecycle {
                            prevent_destroy = true
                            }

                            # Safer production flow
                            terraform fmt -check -recursive
                            terraform validate
                            terraform plan -out=tfplan
                            terraform show -no-color tfplan
                            terraform apply tfplan
1.6 Import & drift : rattacher l’existant, détecter la dérive et reprendre le contrôle IaC
Import & drift : reprendre le contrôle sans casser l’existant

Dans beaucoup d’entreprises, Terraform arrive après plusieurs années de création manuelle : instances, security groups, load balancers, bases de données, DNS, buckets, rôles IAM, certificats ou règles réseau déjà existants.

L’import Terraform permet de rattacher ces ressources existantes au state, sans les recréer. Le drift désigne l’écart entre le code Terraform, le state et la réalité cloud. Bien gérer les deux permet de reprendre progressivement le contrôle IaC.

Objectif professionnel : cartographier l’existant, écrire le code correspondant, importer proprement, vérifier le plan, puis réduire progressivement les changements manuels.
Les 3 réalités à aligner
ÉlémentRôleRisque si désaligné
Code TerraformDécrit l’état souhaité.Terraform veut modifier ou recréer.
State TerraformMémorise les ressources gérées et leurs IDs.Terraform ne sait pas ce qu’il possède.
Cloud réelInfrastructure effectivement déployée.Drift, surprise au prochain plan.
Diagramme Import / Drift
Infrastructure existante
                            │
                            ├── créée manuellement
                            ├── créée par ancien outil
                            ├── créée par console cloud
                            └── créée par script historique
                            │
                            ▼
                            Terraform import
                            │
                            ├── rattache au state
                            ├── nécessite un bloc resource
                            ├── ne crée pas la ressource
                            └── ne garantit pas que le code est complet
                            │
                            ▼
                            terraform plan
                            │
                            ├── zéro diff : alignement OK
                            ├── diff attendu : code à ajuster
                            └── destroy/replace : danger
                            │
                            ▼
                            IaC maîtrisé
Import vs drift
ConceptDéfinitionAction
ImportRattacher une ressource existante au state.Écrire code + importer ID provider.
DriftÉcart entre code/state/cloud réel.Analyser, décider, corriger code ou réel.
State moveRenommer ou déplacer une ressource dans le state.terraform state mv.
State removeRetirer une ressource du state sans la détruire.terraform state rm, avec prudence.
Règle : importer n’est pas “terminer”. Après import, le vrai travail commence : aligner le code jusqu’à obtenir un plan propre et compréhensible.
Inventaire : cartographier avant d’importer

Un import propre commence par un inventaire. Il faut comprendre les ressources existantes, leurs dépendances, leur criticité, leurs noms, leurs tags, leurs liens réseau et leur usage réel.

Ce qu’il faut inventorier
FamilleExemplesPriorité
RéseauVPC, subnets, routes, NAT, security groups.Très élevée
ComputeVM, autoscaling, launch templates, containers.Élevée
Load balancingALB, target groups, listeners, health checks.Très élevée
DataRDS, buckets, volumes, snapshots, Redis.Critique
IAMRoles, policies, users techniques, bindings.Critique sécurité
DNS / TLSZones, records, certificats, validations.Élevée
Template d’inventaire
Resource inventory:
                            - Cloud provider:
                            - Account / project:
                            - Environment:
                            - Resource type:
                            - Resource name:
                            - Provider ID:
                            - Owner:
                            - Criticality:
                            - Dependencies:
                            - Data risk:
                            - Current tags:
                            - Import target address:
                            - Validation command:
                            - Rollback / mitigation:
Ordre recommandé d’import
1. Ressources de base
                            ├── VPC
                            ├── subnets
                            ├── route tables
                            └── security groups

                            2. Ressources partagées
                            ├── IAM roles
                            ├── KMS
                            ├── DNS zones
                            └── certificates

                            3. Ressources applicatives
                            ├── load balancer
                            ├── target groups
                            ├── compute
                            └── autoscaling

                            4. Ressources data
                            ├── databases
                            ├── buckets
                            ├── volumes
                            └── caches
Critères de priorité
CritèrePourquoi
Criticité productionPlus c’est critique, plus il faut préparer.
DépendancesImporter d’abord les fondations utilisées par les autres.
Risque dataDB et stockage nécessitent garde-fous renforcés.
Complexité providerCertaines ressources ont beaucoup d’attributs calculés.
Historique de ClickOpsPlus il y a eu de changements manuels, plus le drift est probable.
Bonne pratique : commencer par un périmètre réduit en staging ou sur une ressource peu risquée, puis étendre progressivement.
Terraform import classique

La commande terraform import rattache une ressource existante à une adresse Terraform. Elle ne crée pas automatiquement un code parfait : il faut écrire le bloc resource, importer l’ID, puis ajuster le code jusqu’à obtenir un plan propre.

Processus import standard
# 1. Écrire le bloc resource minimal
                            resource "aws_security_group" "web" {
                            name   = "prod-web-sg"
                            vpc_id = var.vpc_id
                            }

                            # 2. Importer la ressource existante
                            terraform import aws_security_group.web sg-0123456789abcdef0

                            # 3. Inspecter la ressource importée
                            terraform state show aws_security_group.web

                            # 4. Lancer un plan
                            terraform plan

                            # 5. Compléter le code jusqu'à réduire le diff
                            terraform plan
Attention : un import réussi techniquement ne veut pas dire que le code est aligné. Le juge final est le terraform plan.
Exemple import security group
resource "aws_security_group" "api" {
                            name        = "${local.name_prefix}-api-sg"
                            description = "Security group for API service"
                            vpc_id      = var.vpc_id

                            tags = local.common_tags
                            }

                            # Commande import
                            terraform import aws_security_group.api sg-0abc123456789def0

                            # Vérification
                            terraform state show aws_security_group.api
                            terraform plan
Exemple import DNS record
resource "aws_route53_record" "api" {
                            zone_id = var.zone_id
                            name    = "api.example.com"
                            type    = "A"

                            alias {
                            name                   = aws_lb.api.dns_name
                            zone_id                = aws_lb.api.zone_id
                            evaluate_target_health = true
                            }
                            }

                            # L'ID d'import dépend du provider et du type de record.
                            terraform import aws_route53_record.api ZONEID_api.example.com_A
Bonne pratique : importer une ressource à la fois, planifier, ajuster, committer, puis passer à la suivante.
Import : ce qu’il faut vérifier après chaque ressource
ContrôleCommandeBut
Présence dans le stateterraform state listConfirmer l’import.
Détails importésterraform state show RESOURCEComprendre les attributs réels.
Diff restantterraform planIdentifier ce que le code ne décrit pas.
Risque destroy/replaceReview du planÉviter accident production.
Import blocks et génération de configuration

Les versions récentes de Terraform permettent d’utiliser des blocs import dans le code. Cette approche rend l’import plus traçable, relisible en merge request et plus adaptée aux workflows CI/CD.

Bloc import
import {
                            to = aws_security_group.api
                            id = "sg-0abc123456789def0"
                            }

                            resource "aws_security_group" "api" {
                            name   = "prod-api-sg"
                            vpc_id = var.vpc_id
                            }
Workflow avec import block
Écrire resource minimal
                            │
                            ▼
                            Ajouter bloc import
                            │
                            ▼
                            terraform plan
                            │
                            ├── vérifie import
                            ├── montre diff restant
                            └── permet review MR
                            │
                            ▼
                            terraform apply
                            │
                            └── state mis à jour
                            │
                            ▼
                            Retirer bloc import après réussite
                            │
                            ▼
                            Commit final propre
Avantage : l’import devient visible dans Git et peut être relu avant exécution.
Générer une configuration initiale
# Exemple conceptuel
                            terraform plan -generate-config-out=generated.tf

La génération de configuration peut aider à démarrer, mais le fichier généré doit être nettoyé, simplifié, commenté et adapté aux conventions du projet.

Après génération
ÉtapeAction
NettoyerRetirer attributs calculés ou inutiles.
RenommerAppliquer naming Terraform clair.
FactoriserDéplacer tags, noms, valeurs répétées dans locals.
ParamétrerRemplacer valeurs fixes par variables.
ProtégerAjouter lifecycle si ressource critique.
PlanifierRépéter terraform plan jusqu’à diff maîtrisé.
Attention : le code généré n’est pas forcément du bon design Terraform. C’est une base de travail, pas un livrable final.
Drift : détecter et traiter la dérive

Le drift apparaît quand la réalité cloud ne correspond plus au code Terraform ou au state. Il vient souvent de changements manuels dans la console, de hotfixs d’urgence, de scripts externes, de changements provider ou d’un import incomplet.

Détection du drift
# Voir les écarts entre state et infrastructure réelle
                            terraform plan -refresh-only

                            # Mettre à jour le state avec la réalité observée
                            terraform apply -refresh-only

                            # Plan standard après refresh
                            terraform plan
Exemple de drift
Code Terraform
                            instance_type = "t3.small"

                            State Terraform
                            instance_type = "t3.small"

                            Cloud réel
                            instance_type = "t3.medium"

                            Résultat :
                            terraform plan propose de revenir à t3.small
                            ou de modifier le state selon refresh
Attention : un drift peut être un hotfix de production légitime. Il ne faut pas l’écraser sans comprendre.
Causes fréquentes
CauseExempleTraitement
ClickOpsModification console cloud.Reporter dans Terraform ou restaurer.
Hotfix urgenceSecurity group ouvert temporairement.Documenter puis codifier ou annuler.
Script externeScript modifie tags ou scaling.Clarifier ownership.
AutoscalingDesired capacity modifiée.Éventuellement ignore_changes.
Import incompletAttribut non décrit dans code.Compléter resource block.
Provider upgradeAttribut calculé différemment.Lire changelog, pinner versions.
Décision sur drift
Drift détecté
                            │
                            ▼
                            Changement légitime ?
                            │
                            ├── Oui
                            │     ├── intégrer dans le code
                            │     ├── valider en MR
                            │     └── appliquer proprement
                            │
                            └── Non
                            ├── restaurer état Terraform
                            ├── supprimer changement manuel
                            └── renforcer garde-fou
                            │
                            ▼
                            Documenter la décision
State operations : déplacer, retirer, inspecter

Les opérations sur le state sont puissantes et dangereuses. Elles modifient la mémoire de Terraform, pas forcément l’infrastructure réelle. Elles doivent être utilisées avec sauvegarde, revue et procédure.

Commandes state utiles
# Lister les ressources
                            terraform state list

                            # Inspecter une ressource
                            terraform state show aws_instance.web

                            # Sauvegarder localement le state
                            terraform state pull > state-backup.json

                            # Déplacer une ressource dans le state
                            terraform state mv aws_instance.web aws_instance.app

                            # Retirer une ressource du state sans la détruire
                            terraform state rm aws_instance.web
Renommer une ressource proprement
# Ancien nom dans le state
                            aws_security_group.web

                            # Nouveau nom dans le code
                            aws_security_group.api

                            # Déplacement state
                            terraform state mv aws_security_group.web aws_security_group.api

                            # Vérification
                            terraform plan
Quand utiliser state mv ?
CasBut
Renommage TerraformChanger l’adresse sans recréer la ressource.
Refactor moduleDéplacer une ressource vers un module.
Correction d’adresseAligner state avec le nouveau design.
Quand utiliser state rm ?
CasDanger
Ressource ne doit plus être gérée par TerraformTerraform l’oublie mais ne la détruit pas.
Migration vers autre stateRisque de double gestion si mal fait.
Correction import ratéRisque de perdre le mapping.
Règle : avant state mv ou state rm, faire un state pull, relire l’adresse exacte et prévoir un plan de retour.
Process sécurisé state operation
Avant opération state
                    │
                    ├── sauvegarder state
                    ├── vérifier backend/env
                    ├── écrire commande exacte
                    ├── faire relire
                    └── bloquer apply concurrent
                    │
                    ▼
                    Exécuter opération
                    │
                    ▼
                    terraform plan
                    │
                    ▼
                    Vérifier zéro destroy inattendu
                    │
                    ▼
                    Commit / documentation
Import & drift en production

En production, l’import et la correction de drift doivent être traités comme des changements sensibles. Même si l’import ne modifie pas la ressource cloud, il modifie le state et peut influencer les futurs plans.

Règles production
RèglePourquoi
Importer par petits lotsLimiter le risque et faciliter la revue.
Lire le plan après chaque importDétecter destroy/replace/diff inattendu.
Ne pas importer DB à la légèreRisque data et lifecycle critique.
Protéger le stateState modifié = impact futur.
Documenter chaque mappingAdresse Terraform ↔ ID provider.
Éviter apply concurrentRisque lock, drift ou plan obsolète.
Change request import prod
Title: Import existing production API security group

                            Scope:
                            - Resource: aws_security_group.api
                            - Provider ID: sg-0abc123456789def0
                            - Environment: production
                            - State: prod/network/terraform.tfstate

                            Risk:
                            - Bad code alignment could create unexpected diff.
                            - Future plans may modify existing SG.

                            Validation:
                            - terraform state show
                            - terraform plan
                            - no unexpected destroy or replace
                            - rules match current production

                            Rollback:
                            - state backup available
                            - terraform state rm if import mapping is wrong
Production import workflow
Inventaire validé
                            │
                            ▼
                            Bloc resource minimal
                            │
                            ▼
                            Import en staging si possible
                            │
                            ▼
                            Review MR
                            │
                            ├── adresse Terraform
                            ├── ID provider
                            ├── backend state
                            ├── lifecycle
                            └── plan attendu
                            │
                            ▼
                            Import production
                            │
                            ▼
                            terraform plan
                            │
                            ├── zéro destroy
                            ├── zéro replace inattendu
                            └── diff expliqué
                            │
                            ▼
                            Commit documentation
Ressources à traiter avec prudence
RessourceRisqueGarde-fou
DatabasePerte ou remplacement accidentel.prevent_destroy, backup, review senior.
Bucket dataSuppression ou policy dangereuse.Versioning, lifecycle prudent, audit policy.
IAM roleBlocage app ou escalade privilèges.Review sécurité.
Security groupCouper flux ou ouvrir trop large.Comparer règles actuelles.
DNSTrafic envoyé au mauvais endroit.TTL, dig, validation multi-réseau.
Attention : après un import production, le prochain terraform apply peut devenir dangereux si le code n’est pas parfaitement aligné.
Audit : comprendre qui a changé quoi

Le drift est souvent la conséquence d’un changement manuel. Pour le traiter sérieusement, il faut identifier qui a modifié quoi, quand, pourquoi, et si cette modification doit être codifiée ou annulée.

Sources d’audit
SourceCe qu’elle révèle
Cloud audit logsActions console/API, utilisateur, rôle, heure.
Git historyChangements Terraform, MR, commit, reviewer.
GitLab pipelineJob exécuté, variables, artifact plan, statut.
Terraform state versionsÉvolution du state distant.
Tickets / change requestsJustification métier ou opérationnelle.
Incident timelineHotfixs et actions d’urgence.
Questions d’audit drift
- Quelle ressource a changé ?
                            - Le code Terraform a-t-il changé ?
                            - Le state a-t-il changé ?
                            - Le cloud réel a-t-il changé ?
                            - Qui a fait l'action ?
                            - Était-ce un hotfix ?
                            - Y a-t-il un ticket ou incident associé ?
                            - Faut-il garder le changement ?
                            - Faut-il le reporter dans Terraform ?
                            - Faut-il renforcer un garde-fou ?
Décision après audit
Drift identifié
                            │
                            ▼
                            Audit
                            ├── action humaine ?
                            ├── action pipeline ?
                            ├── provider externe ?
                            ├── autoscaling normal ?
                            └── incident hotfix ?
                            │
                            ▼
                            Décision
                            ├── codifier dans Terraform
                            ├── restaurer état souhaité
                            ├── ignorer volontairement
                            ├── déplacer ownership
                            └── créer garde-fou
                            │
                            ▼
                            MR + documentation
Exemples de décisions
CasDécision
Security group ouvert en urgenceRefermer ou codifier règle minimale.
Desired capacity modifiée par autoscalingAccepter et éventuellement ignore_changes.
Tag ajouté par FinOpsAjouter tag dans locals communs.
DB modifiée manuellementAnalyser risque, codifier prudemment, backup.
Bonne pratique : chaque drift significatif doit produire une décision explicite, pas juste un apply réflexe.
Runbook : importer une ressource existante
Procédure import contrôlé
1. Identifier la ressource existante et son ID provider.
                            2. Confirmer environnement, compte cloud et state cible.
                            3. Sauvegarder le state si production.
                            4. Écrire un bloc resource minimal.
                            5. Ajouter lifecycle si ressource critique.
                            6. Lancer terraform import ou utiliser un bloc import.
                            7. Vérifier terraform state list.
                            8. Inspecter terraform state show.
                            9. Lancer terraform plan.
                            10. Ajuster le code jusqu'à diff maîtrisé.
                            11. Vérifier absence de destroy/replace inattendu.
                            12. Documenter mapping resource address ↔ provider ID.
                            13. Faire relire en MR.
                            14. Importer la ressource suivante seulement après validation.
Rythme conseillé : une ressource critique à la fois. Importer 50 ressources d’un coup rend la revue presque impossible.
Runbook : traiter un drift
1. Lancer terraform plan -refresh-only.
                            2. Identifier les ressources en drift.
                            3. Vérifier changements récents : Git, pipeline, audit cloud.
                            4. Classer le drift : légitime, accidentel, provider, autoscaling.
                            5. Décider : intégrer dans code ou restaurer état Terraform.
                            6. Créer une MR si changement durable.
                            7. Relire plan standard.
                            8. Appliquer uniquement après validation.
                            9. Documenter cause et action.
                            10. Ajouter garde-fou si nécessaire.
Commandes essentielles
terraform state list
                            terraform state show RESOURCE
                            terraform import RESOURCE PROVIDER_ID
                            terraform plan
                            terraform plan -refresh-only
                            terraform apply -refresh-only
                            terraform state mv OLD NEW
                            terraform state rm RESOURCE
                            terraform state pull > state-backup.json
Règle : ne jamais traiter un drift production comme un simple bruit. Il peut révéler un incident, un hotfix ou une faille de process.
Anti-patterns Import & drift
Anti-patternPourquoi c’est dangereuxAlternative professionnelle
Importer sans inventaireOn ne comprend pas dépendances ni criticité.Cartographie et ordre d’import.
Importer sans code alignéLe plan suivant peut modifier l’existant.Écrire resource block puis ajuster avec plan.
Importer trop de ressources d’un coupPlan illisible et risques non détectés.Importer par petits lots.
Ignorer le driftTerraform devient imprévisible.Analyse régulière et décision documentée.
Écraser le drift automatiquementPeut annuler un hotfix de production.Comprendre avant apply.
state rm pour cacher une erreurTerraform perd le contrôle réel.Corriger mapping ou code.
force-unlock réflexePeut casser un apply actif.Identifier le détenteur du lock.
Pas de lifecycle sur ressources dataRisque destroy/replace accidentel.prevent_destroy, backups, review senior.
Mauvais modèle
Import improvisé
                            ├── pas d'inventaire
                            ├── pas de state backup
                            ├── IDs copiés vite
                            ├── 30 ressources importées
                            ├── plan non relu
                            └── drift ignoré
Résultat : Terraform devient une nouvelle source de risque au lieu de sécuriser l’existant.
Bon modèle
Import contrôlé
                            ├── inventaire
                            ├── mapping resource ↔ ID
                            ├── state backup
                            ├── import par petits lots
                            ├── plan relu
                            ├── code aligné
                            ├── lifecycle critique
                            └── documentation
Résultat : reprise progressive du contrôle IaC avec risque maîtrisé.
Checklist Import & drift
Checklist avant import
PointValidation attendue
Ressource identifiéeType, nom, ID provider, région, compte.
Environnement confirméDev, staging ou production sans ambiguïté.
State cible confirméBackend et key corrects.
Dépendances comprisesRéseau, IAM, DNS, DB, app.
Code resource prêtBloc minimal écrit et relu.
Backup stateObligatoire en production.
Lifecycle critiqueAjouté si DB, bucket, volume, KMS.
Fenêtre adaptéeSi ressource critique ou production sensible.
Checklist après import
terraform state listRessource visible dans le state.
terraform state showAttributs réels inspectés.
terraform planDiff compris et maîtrisé.
Destroy/replaceAbsents ou explicitement justifiés.
DocumentationMapping ressource ↔ ID conservé.
Checklist drift
QuestionPourquoi
Quel attribut a changé ?Comprendre la nature du drift.
Qui a changé la ressource ?Audit et responsabilité opérationnelle.
Était-ce un hotfix ?Ne pas annuler une correction d’urgence.
Le changement est-il souhaité ?Décider codification ou restauration.
Le code doit-il être modifié ?Aligner état souhaité.
Un garde-fou manque-t-il ?Éviter récidive.
Le plan est-il sûr ?Éviter destroy/replace involontaire.
Définition d’une bonne reprise IaC : inventaire clair, import traçable, plan propre, drift expliqué, ressources critiques protégées et ClickOps réduit.
Mini-cheat-sheet
# Import classique
                            terraform import RESOURCE_ADDRESS PROVIDER_ID

                            # Inspecter
                            terraform state list
                            terraform state show RESOURCE_ADDRESS

                            # Détecter drift
                            terraform plan -refresh-only

                            # Plan standard
                            terraform plan -out=tfplan
                            terraform show -no-color tfplan

                            # State operations sensibles
                            terraform state pull > state-backup.json
                            terraform state mv OLD_ADDRESS NEW_ADDRESS
                            terraform state rm RESOURCE_ADDRESS

                            # Règle production
                            # Importer petit, planifier souvent, documenter toujours.
2.6 Templates GitLab CI : factoriser les jobs CI/CD pour éviter la duplication
Templates GitLab CI : industrialiser les pipelines

Les templates GitLab CI permettent de factoriser les jobs répétitifs : installation, lint, tests, scan sécurité, Terraform plan, Terraform apply, build d’image, publication d’artifacts, smoke tests et déploiements.

Sans templates, chaque projet finit avec son propre .gitlab-ci.yml, ses variantes, ses bugs, ses secrets mal déclarés et ses différences de comportement. Avec des templates bien conçus, les équipes gagnent en cohérence, sécurité, lisibilité et maintenabilité.

Objectif professionnel : construire une bibliothèque CI/CD réutilisable : jobs standards, variables claires, includes versionnés, règles de sécurité communes, et personnalisation contrôlée par projet.
Ce que l’on factorise
ZoneExemplesBénéfice
Lint / formatTerraform fmt, YAML lint, shellcheck.Qualité homogène.
ValidationTerraform validate, tests unitaires.Éviter erreurs basiques.
SécuritéCheckov, Trivy, tfsec, secret scan.Garde-fous communs.
Terraforminit, plan, show, artifacts, apply.Workflow infra standardisé.
Déploiementstaging, production, rollback, post-checks.Moins d’improvisation.
Artifactsplan.txt, plan.json, rapports sécurité.Review et audit facilités.
Architecture type
Projet applicatif / infra
    │
    └── .gitlab-ci.yml
          │
          ├── include:
          │     ├── templates/terraform.yml
          │     ├── templates/security.yml
          │     ├── templates/docker.yml
          │     └── templates/deploy.yml
          │
          ├── variables projet
          ├── jobs spécifiques
          └── extends templates communs
                    │
                    ▼
Bibliothèque CI centrale
    ├── jobs standards
    ├── règles communes
    ├── images validées
    ├── artifacts standards
    └── politiques sécurité
Principe clé
Mauvais modèleBon modèle
Copier-coller les jobs entre projets.Inclure un template versionné.
Chaque projet réinvente Terraform plan.Job .terraform_plan_template commun.
Secrets gérés différemment partout.Conventions de variables standardisées.
Pas de versioning des templates.Includes pinés sur tag ou ref stable.
Règle : un template CI doit être générique, lisible, documenté et personnalisable sans forcer les projets à le dupliquer.
Le problème : duplication, divergence et pipelines fragiles

La duplication CI/CD devient vite une dette technique. Une correction de sécurité doit être copiée dans dix projets, un bug Terraform reste dans certains pipelines, et les nouveaux DevOps ne savent plus quel fichier est la référence.

Symptômes d’un mauvais modèle CI
SymptômeCauseImpact
Jobs similaires mais différentsCopier-coller modifié localement.Comportements imprévisibles.
Scan sécurité absent sur certains projetsPas de template commun.Faille non détectée.
Terraform plan non publiéArtifacts non standardisés.Review difficile.
Variables incohérentesNaming non défini.Debug lent et erreurs prod.
Fix CI à répéter partoutAucune bibliothèque partagée.Maintenance coûteuse.
Pipeline incompréhensibleIncludes et overrides non documentés.Onboarding difficile.
Risque : un pipeline dupliqué peut être “presque identique” mais rater précisément le contrôle sécurité ou production le plus important.
Évolution typique de la dette CI
Projet A crée un pipeline
    │
    ▼
Projet B copie le pipeline
    │
    ▼
Projet C adapte une version ancienne
    │
    ▼
Un bug est corrigé dans A seulement
    │
    ▼
Projet B garde une faille
    │
    ▼
Projet C casse production
    │
    ▼
Décision : créer templates communs
Ce qu’un template doit éviter
ProblèmeSolution template
Répétition du before_scriptJob caché commun.
Versions d’images différentesImage centralisée et versionnée.
Artifacts incohérentsPaths standards.
Rules copiées partoutRules templates.
Secrets exposés par debugDebug sécurisé commun.
Bonne pratique : commencer par factoriser les jobs les plus répétitifs et les plus risqués : Terraform, sécurité, build et deploy.
include : importer des templates GitLab CI

include permet d’importer des fichiers CI depuis le même repository, un autre projet GitLab, un template distant ou une bibliothèque centrale. C’est la base de la mutualisation.

Include local
include:
  - local: ".gitlab/ci/terraform.yml"
  - local: ".gitlab/ci/security.yml"
  - local: ".gitlab/ci/deploy.yml"
Include depuis un projet central
include:
  - project: "platform/gitlab-ci-templates"
    ref: "v1.4.2"
    file:
      - "/templates/terraform.yml"
      - "/templates/security.yml"
      - "/templates/deploy.yml"
Include remote
include:
  - remote: "https://example.com/gitlab/templates/terraform.yml"
Attention : l’include remote doit être utilisé prudemment. Un fichier distant non maîtrisé peut modifier le comportement du pipeline.
Quel type d’include choisir ?
TypeUsageRisque
localTemplates dans le même repo.Peu mutualisé entre projets.
projectBibliothèque CI interne.Doit être versionné proprement.
remoteTemplate externe ou généré.Risque supply-chain.
templateTemplates GitLab prédéfinis.Moins adapté aux conventions internes.
Structure recommandée
platform/gitlab-ci-templates
    │
    ├── templates/
    │   ├── terraform.yml
    │   ├── security.yml
    │   ├── docker.yml
    │   ├── deploy.yml
    │   └── rules.yml
    │
    ├── examples/
    │   ├── terraform-project.yml
    │   ├── app-project.yml
    │   └── monorepo.yml
    │
    └── CHANGELOG.md
Bonne pratique : pin l’include sur un tag stable : ref: "v1.4.2", pas uniquement main.
extends : réutiliser un job modèle

extends permet à un job concret d’hériter d’un job template. On définit un comportement commun dans un job caché, puis chaque projet surcharge uniquement ce qui varie : variables, rules, environment, paths ou script additionnel.

Template caché
.terraform_base:
  image: hashicorp/terraform:1.6.6
  variables:
    TF_IN_AUTOMATION: "true"
    TF_INPUT: "false"
  before_script:
    - cd "$TF_ROOT"
    - terraform --version
    - terraform init -input=false
Job concret qui étend
terraform_validate:
  extends: .terraform_base
  stage: validate
  script:
    - terraform fmt -check -recursive
    - terraform validate
Job plan spécifique
terraform_plan_staging:
  extends: .terraform_base
  stage: plan
  variables:
    TF_ROOT: "infra/live/staging/app"
  script:
    - terraform plan -out=tfplan
    - terraform show -no-color tfplan > plan.txt
  artifacts:
    paths:
      - "$TF_ROOT/tfplan"
      - "$TF_ROOT/plan.txt"
    expire_in: 3 days
Ce que l’on met dans le template
ÉlémentDans template ?Pourquoi
Image Docker standardOuiCohérence des versions.
Variables génériquesOuiÉvite répétition.
Chemin projet TF_ROOTSouvent nonSpécifique à chaque repo.
Environment productionDans job concretContrôle explicite.
Rules sensiblesTemplate ou job dédiéSelon standard interne.
SecretsNonVariables GitLab protégées/scopées.
Héritage mental
.terraform_base
    ├── image
    ├── variables communes
    ├── before_script
    └── init

terraform_plan_prod
    ├── extends .terraform_base
    ├── stage plan
    ├── TF_ROOT prod
    ├── plan + artifacts
    └── rules main only
Attention : trop d’extends imbriqués rend le pipeline difficile à comprendre. Préférer peu de niveaux et des noms explicites.
Jobs cachés : construire des briques réutilisables

Un job qui commence par un point, comme .terraform_base, n’est pas exécuté directement. Il sert de brique de réutilisation pour d’autres jobs.

Exemple de bibliothèque de jobs cachés
.rules_merge_request:
  rules:
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'

.rules_main:
  rules:
    - if: '$CI_COMMIT_BRANCH == "main"'

.debug_context:
  before_script:
    - echo "Job=$CI_JOB_NAME"
    - echo "Branch=$CI_COMMIT_BRANCH"
    - echo "Source=$CI_PIPELINE_SOURCE"
    - echo "TF_ROOT=${TF_ROOT:-not-set}"

.terraform_base:
  image: hashicorp/terraform:1.6.6
  variables:
    TF_INPUT: "false"
    TF_IN_AUTOMATION: "true"
  before_script:
    - cd "$TF_ROOT"
    - terraform init -input=false
Job final
terraform_plan:
  extends:
    - .terraform_base
    - .rules_merge_request
  stage: plan
  script:
    - terraform plan -out=tfplan
    - terraform show -no-color tfplan > plan.txt
Naming recommandé
PréfixeUsage
.base_*Configuration commune.
.rules_*Conditions d’exécution.
.terraform_*Jobs Terraform.
.security_*Scans sécurité.
.docker_*Build/push image.
.deploy_*Déploiement.
Découpage propre
templates/
    ├── rules.yml
    │   ├── .rules_mr
    │   ├── .rules_main
    │   └── .rules_tag
    │
    ├── terraform.yml
    │   ├── .terraform_base
    │   ├── .terraform_validate
    │   ├── .terraform_plan
    │   └── .terraform_apply
    │
    └── security.yml
        ├── .checkov
        ├── .trivy_config
        └── .secret_scan
Bonne pratique : un job caché doit faire une chose claire. S’il devient trop générique, il devient difficile à utiliser.
Variables : personnaliser sans dupliquer

Les variables rendent les templates flexibles. Le projet définit ce qui change : chemin Terraform, environnement, image, nom de service, stratégie de déploiement, et le template garde la logique commune.

Variables communes recommandées
VariableUsageExemple
TF_ROOTDossier Terraform.infra/live/prod/app
TF_VAR_environmentVariable Terraform.production
APP_NAMENom service.api
DEPLOY_ENVEnvironnement cible.staging
DOCKER_IMAGEImage applicative.registry/app/api
SCAN_SEVERITYNiveau blocage sécurité.HIGH,CRITICAL
Variables au niveau projet
variables:
  APP_NAME: "api"
  TF_ROOT: "infra/live/staging/api"
  DEPLOY_ENV: "staging"
  TF_IN_AUTOMATION: "true"
  TF_INPUT: "false"
Override contrôlé par job
terraform_plan_prod:
  extends: .terraform_plan
  variables:
    TF_ROOT: "infra/live/prod/api"
    DEPLOY_ENV: "production"
  environment:
    name: production
  rules:
    - if: '$CI_COMMIT_BRANCH == "main"'
Variables sensibles
TypeOù les mettre ?Protection
Cloud credentialsGitLab variables ou OIDC.Masked, protected, scoped.
DB passwordVault / secret manager.Jamais dans YAML.
API tokenVariables protégées.Rotation régulière.
SSH keyFile variable ou secret manager.Scope environnement.
Debug sûr
echo "APP_NAME=$APP_NAME"
echo "DEPLOY_ENV=$DEPLOY_ENV"
echo "TF_ROOT=$TF_ROOT"

if [ -z "$AWS_ACCESS_KEY_ID" ]; then
  echo "AWS_ACCESS_KEY_ID is missing"
else
  echo "AWS_ACCESS_KEY_ID is present"
fi
Règle : un template ne doit jamais contenir un secret en dur. Il doit seulement consommer des variables protégées ou un mécanisme OIDC/Vault.
Template Terraform complet : validate, plan, apply

Terraform est l’un des meilleurs candidats à la factorisation : les commandes sont répétitives, les artifacts doivent être standards, et les garde-fous production doivent être cohérents partout.

Template Terraform central
.terraform_base:
  image: hashicorp/terraform:1.6.6
  variables:
    TF_INPUT: "false"
    TF_IN_AUTOMATION: "true"
  before_script:
    - echo "TF_ROOT=$TF_ROOT"
    - cd "$TF_ROOT"
    - terraform --version
    - terraform init -input=false

.terraform_validate:
  extends: .terraform_base
  stage: validate
  script:
    - terraform fmt -check -recursive
    - terraform validate

.terraform_plan:
  extends: .terraform_base
  stage: plan
  script:
    - terraform plan -input=false -out=tfplan
    - terraform show -no-color tfplan > plan.txt
    - terraform show -json tfplan > plan.json
  artifacts:
    paths:
      - "$TF_ROOT/tfplan"
      - "$TF_ROOT/plan.txt"
      - "$TF_ROOT/plan.json"
    expire_in: 3 days

.terraform_apply:
  extends: .terraform_base
  stage: apply
  script:
    - terraform apply -input=false tfplan
  when: manual
  allow_failure: false
Utilisation dans un projet
include:
  - project: "platform/gitlab-ci-templates"
    ref: "v1.4.2"
    file:
      - "/templates/terraform.yml"

stages:
  - validate
  - plan
  - apply

variables:
  TF_ROOT: "infra/live/staging/api"

terraform_validate:
  extends: .terraform_validate

terraform_plan:
  extends: .terraform_plan

terraform_apply:
  extends: .terraform_apply
  environment:
    name: staging
  dependencies:
    - terraform_plan
Production protégée
terraform_apply_prod:
  extends: .terraform_apply
  variables:
    TF_ROOT: "infra/live/prod/api"
  environment:
    name: production
  dependencies:
    - terraform_plan_prod
  rules:
    - if: '$CI_COMMIT_BRANCH == "main"'
  tags:
    - protected
    - terraform
    - prod
Bonne pratique : toujours publier plan.txt pour review humaine et plan.json pour contrôles automatiques.
Sécurité des templates CI/CD

Un template CI/CD est puissant : s’il est compromis ou mal conçu, tous les projets qui l’incluent peuvent hériter du problème. Il doit donc être versionné, relu, limité et testé.

Risques principaux
RisqueExemplePrévention
Supply-chain CITemplate central modifié malicieusement.MR review, protected branch, tags.
Secrets exposésenv ou set -x.Debug sécurisé.
Apply prod non protégéJob manuel accessible trop largement.Protected environment + runner.
Include sur mainChangement template impacte tout sans contrôle.Pin sur tag stable.
Remote include non maîtriséFichier externe change sans validation.Éviter ou contrôler strictement.
Template debug sécurisé
.safe_debug_context:
  script:
    - echo "Job=$CI_JOB_NAME"
    - echo "Branch=$CI_COMMIT_BRANCH"
    - echo "Source=$CI_PIPELINE_SOURCE"
    - echo "Environment=${CI_ENVIRONMENT_NAME:-not-set}"
    - echo "TF_ROOT=${TF_ROOT:-not-set}"
    - pwd
    - ls -la
Contrôles de sécurité à standardiser
ContrôleJob template
Secrets scan.secret_scan
IaC scan.checkov, .trivy_config
Container scan.trivy_image
Terraform fmt/validate.terraform_validate
Plan artifact.terraform_plan
Protected apply.terraform_apply + environment.
Règles de protection
Template repository
    ├── protected main
    ├── MR obligatoire
    ├── approvals DevOps/Security
    ├── tags de release
    ├── changelog
    └── tests d’exemples

Project repository
    ├── include ref tag stable
    ├── variables protected
    ├── environments protected
    └── runner protected for prod
Règle : ne jamais ajouter env, printenv ou set -x dans un template partagé.
Versioning des templates : stabilité et évolution contrôlée

Un template central doit évoluer comme un produit interne. Les projets doivent pouvoir choisir quand passer de v1.4.2 à v1.5.0, lire le changelog, tester la migration et éviter les ruptures surprises.

Bon include versionné
include:
  - project: "platform/gitlab-ci-templates"
    ref: "v1.5.0"
    file:
      - "/templates/terraform.yml"
      - "/templates/security.yml"
Mauvais include non maîtrisé
include:
  - project: "platform/gitlab-ci-templates"
    ref: "main"
    file: "/templates/terraform.yml"
Attention : inclure main peut modifier tous les pipelines consommateurs dès qu’un template change.
Stratégie de versions
Type de changementVersionExemple
Correction bug sans rupturePatchv1.4.2v1.4.3
Nouveau job optionnelMinorv1.4.2v1.5.0
Breaking changeMajorv1.5.0v2.0.0
Process release template
Modifier template
    │
    ▼
Tester exemples
    │
    ▼
MR review DevOps/Security
    │
    ▼
Merge main
    │
    ▼
Créer tag vX.Y.Z
    │
    ▼
Publier changelog
    │
    ▼
Projets consommateurs migrent volontairement
Changelog minimal
## v1.5.0
Added:
- New .terraform_plan_json job
- New .trivy_config template

Changed:
- Terraform image updated to 1.6.6

Fixed:
- Artifact path handling for nested TF_ROOT

Migration:
- No breaking change
Bonne pratique : fournir un dossier examples/ qui prouve que les templates fonctionnent dans des cas réalistes.
Anti-patterns Templates GitLab CI
Anti-patternPourquoi c’est dangereuxCorrection professionnelle
Copier-coller les pipelinesLes corrections ne se propagent pas.Templates centralisés.
Include sur mainRuptures surprises sur projets consommateurs.Pin sur tag versionné.
Templates trop magiquesLes DevOps ne comprennent plus le pipeline.Noms explicites, documentation, exemples.
Trop d’extends imbriquésDebug très difficile.Limiter les niveaux d’héritage.
Variables non documentéesErreur de configuration projet.Table des variables obligatoires.
Secrets dans YAMLFuite durable dans Git.Variables protégées, Vault, OIDC.
Remote include non contrôléRisque supply-chain.Templates internes versionnés.
Breaking changes silencieuxLes pipelines cassent sans explication.SemVer, changelog, migration guide.
Mauvais modèle
CI non industrialisée
    ├── copier-coller partout
    ├── variables différentes
    ├── pas de versioning
    ├── secrets mal protégés
    ├── jobs sécurité absents
    └── debug projet par projet
Résultat : dette CI/CD, sécurité incohérente, maintenance lente et risque production.
Bon modèle
CI industrialisée
    ├── templates centraux
    ├── includes versionnés
    ├── jobs cachés simples
    ├── extends lisibles
    ├── variables documentées
    ├── sécurité standardisée
    └── exemples testés
Résultat : pipelines cohérents, onboarding rapide, corrections mutualisées et meilleur contrôle production.
Checklist Templates GitLab CI
Checklist design template
PointValidation attendue
Templates centralisésRepo dédié ou dossier .gitlab/ci.
Jobs cachésTemplates préfixés par un point.
Noms explicites.terraform_plan, .security_checkov.
Variables documentéesObligatoires, optionnelles, sensibles.
Artifacts standardsPlans, rapports, logs utiles.
Exemples fournisProjet Terraform, app, monorepo.
Héritage limitéPas de chaîne obscure d’extends.
Sécurité intégréeScans, no secrets, protected apply.
Checklist projet consommateur
Include pinéref: vX.Y.Z, pas main.
Variables définiesTF_ROOT, env, app name.
Secrets protégésMasked, protected, scoped.
Production protégéeEnvironment, runner, apply manuel.
Pipeline lisibleLes jobs finaux sont compréhensibles.
Checklist release template
QuestionRéponse attendue
Le changement est-il breaking ?Oui/non documenté.
Les exemples passent-ils ?Pipeline test OK.
La sécurité a-t-elle relu ?Oui si secrets/IAM/prod concernés.
Le changelog est-il à jour ?Ajout, changement, fix, migration.
Un tag est-il créé ?vX.Y.Z.
Les projets critiques migrent-ils progressivement ?Pas de bascule massive non testée.
Définition d’un bon template GitLab CI : il supprime la duplication, impose les garde-fous essentiels, reste compréhensible, se versionne proprement et s’adapte aux projets sans copier-coller.
Mini-cheat-sheet
# Include central
include:
  - project: "platform/gitlab-ci-templates"
    ref: "v1.5.0"
    file:
      - "/templates/terraform.yml"

# Hidden job
.terraform_base:
  image: hashicorp/terraform:1.6.6
  before_script:
    - cd "$TF_ROOT"
    - terraform init

# Extends
terraform_plan:
  extends: .terraform_plan
  variables:
    TF_ROOT: "infra/live/staging/api"

# Must have
- include versionné
- jobs cachés simples
- variables documentées
- artifacts standards
- no secrets in YAML
- protected apply production
- changelog template
1.7 Tests Terraform : validation locale, sandbox, plans, Terratest et tests de modules
Tester Terraform : éviter que le premier vrai test soit la production

Tester Terraform ne signifie pas seulement lancer terraform validate. Il faut vérifier que le code est formaté, valide, sécurisé, que le plan est cohérent, que les modules créent bien les ressources attendues, et que les outputs permettent aux autres stacks de consommer proprement l’infrastructure.

Les tests Terraform doivent être proportionnés au risque. Un module réseau, IAM, base de données ou sécurité mérite beaucoup plus de contrôles qu’un simple log group ou une ressource non critique.

Objectif professionnel : détecter les erreurs avant l’apply, prouver que le module respecte son contrat, limiter les surprises de plan et sécuriser les changements production.
Ce que l’on teste vraiment
ZoneQuestionSignal attendu
SyntaxeLe code Terraform est-il valide ?terraform validate OK.
FormatLe code est-il standardisé ?terraform fmt -check OK.
PlanLe changement est-il celui attendu ?Pas de destroy/replace non prévu.
ModuleLe module crée-t-il les bonnes ressources ?Resources, tags, outputs et règles corrects.
SécuritéLe code ouvre-t-il un risque ?Scan IaC sans blocage critique.
RuntimeL’infra fonctionne-t-elle vraiment après apply ?Healthcheck, connectivité, logs et métriques OK.
Pipeline mental des tests Terraform
Code Terraform
                            │
                            ▼
                            Tests statiques
                            ├── fmt
                            ├── validate
                            ├── tflint
                            └── checkov / trivy / tfsec
                            │
                            ▼
                            Tests de plan
                            ├── plan lisible
                            ├── no destroy inattendu
                            ├── review humaine
                            └── policy-as-code éventuelle
                            │
                            ▼
                            Sandbox apply
                            ├── création réelle
                            ├── vérification outputs
                            ├── tests connectivité
                            └── destroy contrôlé
                            │
                            ▼
                            Promotion staging / prod
                            ├── approval
                            ├── apply contrôlé
                            └── post-checks
Pourquoi tester par niveaux ?
NiveauCoûtValeur
fmt / validateTrès faibleDétecte erreurs basiques immédiatement.
Scan sécuritéFaibleDétecte ports ouverts, IAM trop larges, secrets.
Plan reviewMoyenDétecte effets réels avant apply.
Sandbox applyMoyen à élevéValide comportement réel.
TerratestÉlevéAutomatise tests d’intégration sérieux.
Règle : plus une ressource est critique, plus elle mérite des tests proches du réel : réseau, IAM, DB, DNS, load balancer et sécurité.
Niveaux de tests Terraform

Un bon dispositif de tests Terraform combine plusieurs couches : tests statiques rapides, revue du plan, sandbox réelle, tests de modules et vérifications post-apply.

Pyramide de tests IaC
Tests post-apply / runtime
                            ├── healthcheck
                            ├── connectivité
                            ├── DNS/TLS
                            └── métriques

                            Tests d'intégration
                            ├── sandbox apply
                            ├── Terratest
                            ├── outputs
                            └── destroy

                            Tests de plan
                            ├── no destroy
                            ├── no public exposure
                            ├── diff attendu
                            └── review humaine

                            Tests statiques
                            ├── terraform fmt
                            ├── terraform validate
                            ├── tflint
                            ├── checkov
                            └── trivy config
Bonne approche : exécuter beaucoup de tests rapides à chaque MR, et réserver les tests coûteux aux modules critiques ou aux branches de validation.
Tableau des niveaux
NiveauOutilsQuandBloquant ?
Formatterraform fmtÀ chaque commit/MR.Oui
Validationterraform validateÀ chaque MR.Oui
LintTFLintÀ chaque MR.Selon maturité
SécuritéCheckov, tfsec, TrivyMR et main.Oui sur critique
Planterraform planMR, main, staging.Oui
IntégrationSandbox, TerratestModules critiques.Oui selon criticité
Runtimecurl, cloud CLI, tests métierAprès apply.Oui pour prod
Stratégie par criticité
Faiblefmt, validate, plan.
Moyennefmt, validate, scan, plan, review.
Élevée+ sandbox apply et post-checks.
Critique+ Terratest, policy-as-code, approval senior.
Validation locale : première barrière avant MR

Les validations locales doivent être rapides, répétables et faciles à lancer. Elles évitent de pousser du code Terraform cassé dans la CI/CD.

Commandes locales essentielles
# Initialisation
                            terraform init

                            # Formatage
                            terraform fmt -recursive
                            terraform fmt -check -recursive

                            # Validation syntaxe / providers / modules
                            terraform validate

                            # Voir providers utilisés
                            terraform providers

                            # Plan local avec variables
                            terraform plan -var-file="dev.tfvars"

                            # Plan sauvegardé
                            terraform plan -var-file="dev.tfvars" -out=tfplan
                            terraform show -no-color tfplan
Règle simple : avant toute MR, au minimum : fmt, validate et plan.
Script local de validation
#!/usr/bin/env bash
                            set -euo pipefail

                            echo "[1/4] terraform fmt"
                            terraform fmt -check -recursive

                            echo "[2/4] terraform init"
                            terraform init

                            echo "[3/4] terraform validate"
                            terraform validate

                            echo "[4/4] terraform plan"
                            terraform plan -var-file="dev.tfvars" -out=tfplan

                            echo "Validation completed."
Erreurs détectées localement
ErreurDétectionCorrection
HCL mal formatéterraform fmt -checkterraform fmt -recursive
Variable manquanteterraform planAjouter default ou tfvars.
Provider absentterraform initCorriger required providers.
Type invalideterraform validateCorriger variable/object/map.
Backend inaccessibleterraform initVérifier credentials et backend.
Attention : un plan local peut être différent du plan CI si les variables, versions providers ou credentials ne sont pas identiques.
Tests de plan : vérifier l’intention avant l’action

Le plan est le meilleur test avant apply. Il montre les créations, modifications, remplacements et suppressions. En production, il doit être relu comme un document de changement.

Commandes plan
# Plan standard
                            terraform plan -var-file="prod.tfvars"

                            # Plan sauvegardé
                            terraform plan -var-file="prod.tfvars" -out=tfplan

                            # Plan lisible
                            terraform show -no-color tfplan > plan.txt

                            # Plan JSON pour analyse automatisée
                            terraform show -json tfplan > plan.json
Ce que l’on cherche dans un plan
SignalInterprétationRéaction
+Création.Vérifier coût, tags, sécurité.
~Modification.Comprendre impact runtime.
-/+Remplacement.Analyse obligatoire.
-Suppression.Stop si non attendu.
Règle : tout destroy ou replace en production doit être explicitement justifié.
Tests automatisables sur plan JSON
ContrôleBut
No destroyBloquer suppressions non prévues.
No public DBInterdire base de données publique.
No open SSHInterdire 0.0.0.0/0 sur port 22.
Required tagsVérifier tags Owner, Environment, Project.
Allowed instance typesContrôler coûts et standards.
Backup enabledVérifier ressources data critiques.
Exemple de commentaire MR
Terraform plan summary:
                            - Environment: staging
                            - Resources to add: 2
                            - Resources to change: 1
                            - Resources to destroy: 0
                            - Replace: 0
                            - Security impact: no public ingress
                            - Data impact: none
                            - Rollback: revert MR and re-apply previous plan
Diagramme review du plan
Plan généré
                            │
                            ▼
                            Résumé humain
                            │
                            ├── add
                            ├── change
                            ├── replace
                            └── destroy
                            │
                            ▼
                            Contrôles risques
                            ├── réseau
                            ├── IAM
                            ├── DB
                            ├── DNS
                            └── coûts
                            │
                            ▼
                            Approval ou correction
Sandbox : tester sans mettre la production en danger

Une sandbox est un environnement isolé permettant d’appliquer réellement Terraform, de vérifier que les ressources se créent, que les outputs sont corrects et que la destruction contrôlée fonctionne.

Caractéristiques d’une bonne sandbox
CritèreAttendu
IsolationCompte/projet/région ou préfixe dédié.
Coût limitéQuotas, tailles petites, auto-destroy.
Données fictivesAucune donnée production réelle.
State séparéBackend sandbox distinct.
Credentials limitésImpossible d’agir sur production.
TTLNettoyage automatique ou planifié.
Workflow sandbox
terraform init
                            terraform plan -var-file="sandbox.tfvars" -out=tfplan
                            terraform apply tfplan

                            # Vérifications
                            terraform output
                            curl -fsS https://sandbox.example.com/health/

                            # Nettoyage
                            terraform destroy -var-file="sandbox.tfvars"
Bonne pratique : un module critique doit être testé au moins une fois en sandbox avant d’être promu en staging ou production.
Cycle apply / verify / destroy
Sandbox state
                            │
                            ▼
                            terraform apply
                            │
                            ├── ressources créées
                            ├── outputs produits
                            └── tags appliqués
                            │
                            ▼
                            Vérifications
                            ├── cloud resource exists
                            ├── security rules OK
                            ├── DNS/TLS si concerné
                            ├── healthcheck
                            └── logs clean
                            │
                            ▼
                            terraform destroy
                            │
                            ├── nettoyage réussi
                            └── aucun résidu coûteux
Risques sandbox
RisquePrévention
Oubli de ressourcesTTL, tags, rapport coût.
Credentials trop largesRôle sandbox isolé.
State confonduBackend key explicite.
Coût élevéTypes petits, quotas, budgets.
Tests non représentatifsReproduire au moins les dépendances critiques.
Attention : une sandbox doit être isolée par design. Un simple suffixe -test dans le nom ne suffit pas toujours.
Tests de modules Terraform

Un module Terraform est une API d’infrastructure. Il faut tester son contrat : inputs, validations, outputs, naming, tags, sécurité par défaut et comportement sur plusieurs environnements.

Contrat à tester
ÉlémentTest attendu
InputsTypes corrects, validations utiles, defaults sûrs.
OutputsValeurs nécessaires exposées, pas de secrets inutiles.
NamingRessources nommées avec convention projet/env/composant.
TagsTags obligatoires présents partout.
SécuritéPas de port dangereux ouvert par défaut.
LifecycleRessources critiques protégées si applicable.
IdempotenceDeuxième plan après apply ne doit pas montrer de diff inattendu.
Structure de test module
modules/
                            network/
                            main.tf
                            variables.tf
                            outputs.tf
                            README.md
                            examples/
                            basic/
                            main.tf
                            terraform.tfvars
                            multi_az/
                            main.tf
                            terraform.tfvars
                            tests/
                            README.md
Exemple d’example module
module "network" {
                            source = "../../"

                            project     = "demo"
                            environment = "sandbox"
                            vpc_cidr    = "10.50.0.0/16"

                            private_subnets = {
                            "a" = {
                            cidr_block        = "10.50.1.0/24"
                            availability_zone = "eu-west-3a"
                            }
                            "b" = {
                            cidr_block        = "10.50.2.0/24"
                            availability_zone = "eu-west-3b"
                            }
                            }
                            }
Tests simples sans Terratest
cd modules/network/examples/basic

                            terraform init
                            terraform fmt -check -recursive
                            terraform validate
                            terraform plan -out=tfplan
                            terraform apply tfplan
                            terraform output
                            terraform plan
                            terraform destroy
Bonne pratique : chaque module partagé doit avoir au moins un dossier examples/basic validable par CI.
Terratest : tests d’intégration automatisés

Terratest permet d’écrire des tests en Go qui lancent Terraform, appliquent l’infrastructure, vérifient des outputs ou comportements réels, puis détruisent les ressources. C’est puissant, mais plus coûteux que les tests statiques.

Quand utiliser Terratest ?
CasPourquoi
Module réseau critiqueVérifier subnets, routes, outputs, connectivité.
Module load balancerTester endpoint, healthcheck, listener.
Module databaseVérifier backup, deletion protection, private access.
Module sécuritéContrôler règles, ports, tags, IAM.
Module réutilisé par plusieurs équipesÉviter régression lors des évolutions.
Cycle Terratest
go test
                            │
                            ▼
                            terraform init
                            │
                            ▼
                            terraform apply
                            │
                            ▼
                            Assertions
                            ├── outputs
                            ├── cloud resources
                            ├── HTTP endpoint
                            ├── tags
                            └── security rules
                            │
                            ▼
                            terraform destroy
                            │
                            ▼
                            test result
Exemple Terratest simplifié
package test

                            import (
                            "testing"

                            "github.com/gruntwork-io/terratest/modules/terraform"
                            "github.com/stretchr/testify/assert"
                            )

                            func TestNetworkModule(t *testing.T) {
                            t.Parallel()

                            options := &terraform.Options{
                            TerraformDir: "../examples/basic",
                            Vars: map[string]interface{}{
                            "project":     "demo",
                            "environment": "test",
                            },
                            }

                            defer terraform.Destroy(t, options)

                            terraform.InitAndApply(t, options)

                            vpcId := terraform.Output(t, options, "vpc_id")
                            assert.NotEmpty(t, vpcId)
                            }
Précautions Terratest
RisquePrévention
Coût cloudSandbox dédiée, quotas, destroy systématique.
Tests lentsLimiter aux modules critiques.
Ressources résiduellesTags test, cleanup jobs, TTL.
Flaky testsTimeouts raisonnables, retry contrôlé.
CredentialsRôle dédié test, jamais prod.
Attention : Terratest est excellent pour les modules importants, mais trop lourd pour chaque petite ressource.
Tests sécurité IaC

Les tests sécurité IaC détectent les mauvaises pratiques avant l’apply : ports trop ouverts, stockage non chiffré, IAM trop permissif, logs désactivés, ressources publiques ou secrets potentiels.

Outils fréquents
OutilUsage
CheckovScan Terraform, cloud policies, Kubernetes, CI/CD.
tfsecScan sécurité Terraform simple et rapide.
Trivy configScan IaC, containers, dépendances.
TFLintLint Terraform et règles provider.
OPA / ConftestPolicy-as-code personnalisée.
SentinelPolicy-as-code dans Terraform Cloud/Enterprise.
Commandes scan
# Checkov
                            checkov -d .

                            # tfsec
                            tfsec .

                            # Trivy IaC
                            trivy config .

                            # TFLint
                            tflint --init
                            tflint
Contrôles sécurité à bloquer
RisqueExempleDécision
SSH public0.0.0.0/0:22Bloquant en prod.
DB publiquePublicly accessible true.Bloquant.
Bucket publicACL ou policy ouverte.Bloquant sauf exception validée.
IAM wildcardAction: "*"Review sécurité obligatoire.
Chiffrement absentStorage non chiffré.Bloquant selon données.
Logs désactivésAudit ou access logs off.À corriger.
Politique d’exception
Exception security scan:
                            - Rule:
                            - Resource:
                            - Environment:
                            - Reason:
                            - Risk accepted by:
                            - Expiration date:
                            - Compensating control:
                            - Ticket:
Règle : une exception sécurité sans owner ni date d’expiration devient une dette permanente.
CI/CD : automatiser les tests Terraform

La CI/CD doit exécuter automatiquement les contrôles de base à chaque MR : formatage, validation, scan, plan, publication du plan, puis éventuellement tests sandbox pour les modules critiques.

Pipeline GitLab Terraform tests
stages:
                            - lint
                            - validate
                            - security
                            - plan
                            - integration

                            variables:
                            TF_IN_AUTOMATION: "true"
                            TF_INPUT: "false"
                            TF_ROOT: "infra/live/staging/app"

                            default:
                            image: hashicorp/terraform:1.6.6
                            before_script:
                            - cd "$TF_ROOT"
                            - terraform init

                            terraform_fmt:
                            stage: lint
                            script:
                            - terraform fmt -check -recursive

                            terraform_validate:
                            stage: validate
                            script:
                            - terraform validate

                            terraform_security:
                            stage: security
                            image: bridgecrew/checkov:latest
                            before_script: []
                            script:
                            - checkov -d infra
                            allow_failure: false

                            terraform_plan:
                            stage: plan
                            script:
                            - terraform plan -out=tfplan
                            - terraform show -no-color tfplan > plan.txt
                            artifacts:
                            paths:
                            - "$TF_ROOT/tfplan"
                            - "$TF_ROOT/plan.txt"
                            expire_in: 3 days
Job Terratest optionnel
terratest_network:
                            stage: integration
                            image: golang:1.22
                            before_script:
                            - apt-get update && apt-get install -y unzip
                            - cd modules/network/tests
                            script:
                            - go test -v -timeout 45m
                            rules:
                            - changes:
                            - modules/network/**/*
                            when: manual
Stratégie CI recommandée
PipelineTests
Merge requestfmt, validate, scan, plan.
Mainplan final, security scan, artifact.
Nightlydrift detection, scans complets.
Module releaseexamples + Terratest + documentation.
Productionplan, approval, apply manuel, post-checks.
Bonne pratique : publier plan.txt comme artifact pour permettre une vraie revue humaine.
Anti-patterns des tests Terraform
Anti-patternPourquoi c’est dangereuxAlternative professionnelle
Se limiter à terraform validateNe détecte pas les erreurs de design ou sécurité.Ajouter plan, scans, review et sandbox si critique.
Tester directement en productionLe premier vrai test peut casser le service.Sandbox et staging.
Ne pas lire le planDestroy/replace peuvent passer inaperçus.Plan artifact + review humaine.
Pas de tests de modulesRégressions sur modules partagés.Examples validés + Terratest ciblé.
Terratest partoutPipeline lent, coûteux et fragile.Réserver aux modules critiques.
Sandbox sans destroyCoût et ressources orphelines.Destroy automatique, TTL, tags.
Scans sécurité en warning permanentLes alertes sont ignorées.Bloquer les risques critiques et gérer exceptions.
Variables différentes local/CIPlan local non représentatif.Standardiser tfvars, versions et provider lock.
Mauvais modèle
Tests faibles
                            ├── validate uniquement
                            ├── pas de scan sécurité
                            ├── pas de plan artifact
                            ├── pas de sandbox
                            ├── pas de tests modules
                            └── apply prod comme test final
Résultat : les erreurs apparaissent tard, souvent au moment le plus risqué.
Bon modèle
Tests professionnels
                            ├── fmt
                            ├── validate
                            ├── lint
                            ├── security scan
                            ├── plan artifact
                            ├── review humaine
                            ├── sandbox ciblée
                            ├── Terratest modules critiques
                            └── post-checks production
Résultat : meilleure confiance, moins d’incidents et plans plus faciles à relire.
Checklist Tests Terraform
Checklist avant MR
TestCommande / preuve
Formatterraform fmt -check -recursive
Initterraform init
Validateterraform validate
Planterraform plan -out=tfplan
Plan lisibleterraform show -no-color tfplan
Scan sécuritéCheckov, tfsec ou Trivy.
Destroy/replaceAbsents ou justifiés.
SecretsAucun secret dans code, plan, outputs, artifacts.
Checklist module
ExamplesAu moins examples/basic.
InputsTypes, descriptions, validations.
OutputsUtiles, non sensibles.
TagsTags obligatoires appliqués.
Security defaultsPas d’ouverture dangereuse par défaut.
LifecycleRessources critiques protégées.
Checklist sandbox / intégration
PointValidation attendue
Compte sandboxIsolé de production.
State sandboxBackend distinct.
CredentialsDroits limités.
ApplyRessources créées sans erreur.
OutputsValeurs cohérentes.
Post-checkConnectivité, healthcheck ou cloud checks OK.
DestroyNettoyage complet.
CoûtAucune ressource résiduelle coûteuse.
Définition de tests Terraform sérieux : le code est validé, le plan est relu, la sécurité est scannée, les modules critiques sont testés en sandbox et la production est vérifiée après apply.
Mini-cheat-sheet
# Local
                            terraform fmt -check -recursive
                            terraform init
                            terraform validate
                            terraform plan -out=tfplan
                            terraform show -no-color tfplan

                            # Security
                            checkov -d .
                            tfsec .
                            trivy config .
                            tflint --init
                            tflint

                            # Sandbox
                            terraform apply tfplan
                            terraform output
                            curl -fsS https://sandbox.example.com/health/
                            terraform destroy

                            # Terratest
                            go test -v -timeout 45m

                            # Plan JSON
                            terraform show -json tfplan > plan.json
1.8 Coûts & FinOps : comprendre l’impact financier avant apply
FinOps : relier infrastructure, usage et responsabilité financière

Un changement Terraform peut créer des coûts invisibles : instance trop grosse, stockage oublié, logs trop verbeux, NAT gateway inutile, load balancer permanent, retention excessive, snapshots jamais nettoyés ou ressources sandbox non détruites.

Le rôle DevOps ne se limite pas à déployer. Il faut aussi comprendre le coût, expliquer les compromis, taguer correctement, détecter les dérives et rendre les dépenses visibles par environnement, service, équipe et projet.

Objectif professionnel : avant chaque apply significatif, savoir expliquer ce qui change, pourquoi cela coûte plus ou moins cher, qui en est responsable et comment surveiller la dérive.
Les questions FinOps à poser avant apply
QuestionPourquoiSignal attendu
Quelle ressource est créée ?Chaque ressource a un modèle de coût.Instance, DB, LB, NAT, volume, logs, bucket.
Est-ce permanent ou temporaire ?Une sandbox oubliée coûte tous les mois.TTL, auto-destroy ou owner clair.
Quelle taille est choisie ?Le sizing impacte directement la facture.Instance type, storage, IOPS, replicas.
Les tags sont-ils présents ?Sans tags, impossible d’attribuer les coûts.Project, Environment, Owner, CostCenter.
Y a-t-il un coût réseau ?NAT, egress, inter-zone et LB peuvent coûter cher.Trafic estimé et architecture validée.
Une alerte budget existe-t-elle ?Détecter rapidement les dérives.Budget, seuils, notification.
Cycle FinOps appliqué à Terraform
Terraform change
    │
    ▼
Plan review
    ├── ressources ajoutées
    ├── ressources modifiées
    ├── tailles / volumes
    ├── logs / retention
    ├── réseau / egress
    └── tags
          │
          ▼
Cost estimation
    ├── coût mensuel estimé
    ├── delta vs existant
    ├── risque de dérive
    └── owner coût
          │
          ▼
Apply contrôlé
          │
          ▼
Suivi réel
    ├── budget alerts
    ├── dashboards coût
    ├── anomalie coût
    └── optimisation continue
FinOps en une phrase
Sans FinOpsAvec FinOps
“Ça marche, donc c’est bon.”“Ça marche, c’est dimensionné, tagué, surveillé et justifié.”
Coûts découverts en fin de mois.Coûts anticipés avant apply.
Ressources sans owner.Chaque ressource a projet, équipe et environnement.
Optimisation ponctuelle.Optimisation continue intégrée au cycle DevOps.
Règle : un plan Terraform qui crée des ressources coûteuses doit inclure une estimation, une justification et un owner.
Cost drivers : ce qui fait réellement monter la facture

Les coûts cloud ne viennent pas seulement des machines. Le réseau, les logs, le stockage, les backups, les bases managées et les ressources oubliées peuvent représenter une part importante.

Principales sources de coût
FamilleExemplesRisque FinOps
ComputeVM, autoscaling, containers, nodes Kubernetes.Surdimensionnement permanent.
DatabaseRDS, Cloud SQL, replicas, IOPS, stockage.Coût élevé, difficile à réduire sans risque.
NetworkNAT gateway, egress, inter-zone, load balancer.Coûts invisibles liés au trafic.
StorageVolumes, buckets, snapshots, backups.Accumulation silencieuse.
Logs / ObservabilitéIngestion logs, retention, métriques custom.Explosion si logs trop verbeux.
Environnements temporairesReview apps, sandbox, tests Terratest.Oubli de destruction.
Exemples de pièges coûteux
  • Une NAT gateway créée en dev alors qu’elle n’est pas nécessaire.
  • Des logs debug envoyés en continu vers une plateforme payante.
  • Une base de données staging dimensionnée comme la production.
  • Des snapshots conservés indéfiniment sans policy de rétention.
  • Des environnements de test créés par CI mais jamais détruits.
  • Un load balancer par petite application au lieu d’une mutualisation réfléchie.
Tableau coût / risque / contrôle
RessourceQuestion à poserContrôle
InstanceLa taille est-elle justifiée ?CPU/RAM réels, autoscaling, rightsizing.
DB managéeBackup, replicas et IOPS sont-ils adaptés ?Monitoring DB + politique prod/staging.
NATLe trafic sortant le justifie-t-il ?Architecture réseau et volumes egress.
LogsLe volume et la retention sont-ils maîtrisés ?Niveaux log, sampling, retention.
StorageLe cycle de vie supprime-t-il l’ancien ?Lifecycle policy, archive, cleanup.
SandboxExiste-t-il une date d’expiration ?TTL, auto-destroy, tag ExpireAt.
Diagramme des coûts invisibles
Terraform apply
    │
    ├── ressource principale visible
    │     └── instance / DB / LB
    │
    └── coûts associés parfois oubliés
          ├── stockage attaché
          ├── snapshots
          ├── logs
          ├── trafic sortant
          ├── NAT
          ├── monitoring
          ├── backups
          └── IP publiques
Attention : une architecture techniquement correcte peut être financièrement mauvaise si elle multiplie les ressources fixes et les coûts réseau.
Tags : base de l’attribution des coûts

Les tags permettent de savoir qui consomme quoi. Sans tags cohérents, impossible de répartir les coûts par équipe, service, environnement, produit ou client.

Tags obligatoires recommandés
TagExempleUsage
Projectideo-platformRegrouper les coûts par projet.
Environmentdev, staging, prodComparer non-prod vs prod.
Ownerplatform-teamResponsabilité opérationnelle.
CostCenterengineeringRefacturation ou budget interne.
ManagedByterraformDistinguer IaC vs manuel.
Criticalitylow, high, criticalPrioriser optimisation et support.
ExpireAt2026-05-31Nettoyage sandbox/review apps.
Locals Terraform pour tags
locals {
  common_tags = merge(
    {
      Project     = var.project
      Environment = var.environment
      Owner       = var.owner
      CostCenter  = var.cost_center
      ManagedBy   = "terraform"
    },
    var.extra_tags
  )
}
Application des tags
resource "aws_instance" "app" {
  ami           = var.ami_id
  instance_type = var.instance_type

  tags = merge(local.common_tags, {
    Name = "${local.name_prefix}-app"
  })
}
Politique de tags
RèglePourquoi
Tags obligatoiresEmpêcher ressources orphelines financièrement.
Valeurs normaliséesÉviter prod, production, prd.
Owner réelQuelqu’un doit répondre du coût.
CostCenter stablePermet reporting et refacturation.
ExpireAt pour temporaireNettoyage automatique ou revue régulière.
Contrôle CI possible
# Exemple principe :
# Bloquer si une ressource taggable n'a pas les tags obligatoires :
# - Project
# - Environment
# - Owner
# - CostCenter
# - ManagedBy
Bonne pratique : une ressource non taguée est une dette FinOps. Elle rend la facture opaque.
Revue du plan Terraform sous l’angle coût

La revue du plan ne doit pas seulement chercher les suppressions et les risques sécurité. Elle doit aussi identifier les ressources qui changent la facture.

Questions coût dans une review de plan
ChangementQuestion FinOps
Nouvelle instanceLe type est-il adapté ? Peut-elle dormir hors horaires ?
Nouvelle DBBackup, stockage, replicas et IOPS sont-ils justifiés ?
Nouveau load balancerPeut-il être mutualisé ? Est-il permanent ?
Nouvelle NAT gatewayLe besoin réseau justifie-t-il ce coût fixe ?
Retention logs augmentéeLe volume d’ingestion est-il connu ?
Storage augmentéY a-t-il une lifecycle policy ?
Résumé MR recommandé
Cost impact:
- Environment: staging
- New resources: 1 load balancer, 2 instances
- Removed resources: none
- Monthly cost impact: estimated +120 EUR/month
- Main cost drivers: load balancer + compute
- Tags: Project, Environment, Owner, CostCenter OK
- Budget alert: existing staging budget
- Cleanup: not temporary
Diagramme review coût
terraform plan
    │
    ▼
Identifier ressources coûteuses
    ├── compute
    ├── DB
    ├── NAT
    ├── LB
    ├── logs
    ├── storage
    └── egress
          │
          ▼
Évaluer
    ├── coût mensuel
    ├── coût variable
    ├── coût fixe
    ├── owner
    └── durée de vie
          │
          ▼
Décision
    ├── OK
    ├── réduire sizing
    ├── mutualiser
    ├── ajouter TTL
    └── refuser / revoir design
Diff Terraform à surveiller
DiffRisque coût
instance_type augmenteCoût compute permanent plus élevé.
allocated_storage augmenteCoût stockage récurrent.
backup_retention_period augmenteCoût backup/snapshot plus élevé.
log_retention augmenteCoût observabilité.
nat_gateway crééCoût fixe + trafic.
multi_az activéRésilience accrue mais coût supérieur.
Attention : un changement de coût peut être parfaitement justifié. Le problème n’est pas de payer, mais de payer sans comprendre.
Outils FinOps et estimation de coût

Plusieurs outils permettent d’estimer ou suivre les coûts liés à Terraform. Le bon choix dépend de la maturité équipe, du cloud utilisé et du niveau d’automatisation attendu.

Outils liés à Terraform
OutilUsageMoment
InfracostEstimation du coût depuis le plan Terraform.MR / CI.
Terraform plan JSONAnalyse automatisée du diff.MR / audit.
Policy-as-codeBloquer ressources trop coûteuses ou non taguées.CI/CD.
Cloud pricing calculatorEstimation manuelle d’architecture.Design.
Cloud cost explorerSuivi des dépenses réelles.Exploitation.
Exemple Infracost en CI
# Exemple conceptuel
terraform plan -out=tfplan
terraform show -json tfplan > plan.json

infracost breakdown \
  --path plan.json \
  --format table

infracost diff \
  --path plan.json \
  --format json \
  --out-file infracost.json
Bonne pratique : ajouter un commentaire de coût dans la merge request quand le changement crée ou modifie des ressources coûteuses.
Outils cloud natifs
CloudOutils typiques
AWSCost Explorer, Budgets, Cost Anomaly Detection, CUR.
AzureCost Management, Budgets, Advisor.
GCPBilling Reports, Budgets, Recommender, BigQuery export.
KubernetesKubecost, OpenCost, metrics par namespace.
Multi-cloudFinOps dashboards, BI, exports facturation.
Architecture FinOps
Terraform plan
    │
    ├── Infracost estimate
    ├── policy-as-code
    └── MR comment
          │
          ▼
Cloud billing
    ├── budgets
    ├── anomaly detection
    ├── cost explorer
    └── billing export
          │
          ▼
FinOps dashboard
    ├── coût par projet
    ├── coût par environnement
    ├── coût par équipe
    └── dérives mensuelles
Limite : une estimation de coût reste une estimation. Le coût réel dépend aussi du trafic, du stockage, de l’ingestion de logs et de l’usage.
Budgets, alertes et détection d’anomalies

Les budgets et alertes coût permettent de détecter une dérive avant la fin du mois. Ils doivent être définis par environnement, projet ou équipe, avec des seuils adaptés.

Seuils de budget recommandés
SeuilSignificationAction
50%Consommation normale à surveiller.Notification faible.
75%Risque de dépassement.Review projet/environnement.
90%Dépassement probable.Action corrective ou validation owner.
100%Budget atteint.Escalade owner / manager / FinOps.
Anomalie soudaineHausse anormale vs baseline.Investigation immédiate.
Exemple de politique budget
Budget policy:
- Project: ideo-platform
- Environment: staging
- Monthly budget: 300 EUR
- Warning: 75%
- Critical: 100%
- Owner: platform-team
- Notification: Slack #finops-alerts
- Review frequency: weekly
- Action: identify top cost drivers and cleanup unused resources
Détection d’anomalie coût
Facture quotidienne
    │
    ▼
Comparaison baseline
    │
    ├── coût normal
    ├── hausse progressive
    └── pic brutal
          │
          ▼
Analyse
    ├── nouvelle ressource Terraform
    ├── trafic réseau
    ├── logs volumineux
    ├── DB storage
    ├── sandbox oubliée
    └── incident applicatif
          │
          ▼
Action
    ├── cleanup
    ├── resize
    ├── retention
    ├── rollback
    └── validation owner
Actions après alerte budget
ObservationAction
Sandbox coûteuseDestroy, ajouter TTL, automatiser cleanup.
Logs en hausseRéduire debug, ajuster retention, filtrer bruit.
Compute surdimensionnéRightsizing, autoscaling, horaires d’arrêt.
Storage ancienLifecycle policy, archivage, suppression validée.
Trafic sortant élevéAnalyser architecture réseau et cache.
Bonne pratique : une alerte budget doit avoir un owner et une procédure d’analyse, pas seulement un email ignoré.
Design Terraform orienté coûts

Terraform peut intégrer des garde-fous FinOps : variables validées, tailles approuvées, tags obligatoires, rétention contrôlée, ressources temporaires avec expiration et protection contre certains choix coûteux.

Variables contrôlées
variable "instance_type" {
  description = "Approved instance type."
  type        = string

  validation {
    condition = contains([
      "t3.micro",
      "t3.small",
      "t3.medium"
    ], var.instance_type)

    error_message = "Instance type is not approved."
  }
}

variable "log_retention_days" {
  description = "Log retention in days."
  type        = number
  default     = 14

  validation {
    condition     = var.log_retention_days <= 30
    error_message = "Log retention must be lower than or equal to 30 days."
  }
}
Defaults selon environnement
locals {
  is_prod = var.environment == "prod"

  default_instance_type = local.is_prod ? "t3.medium" : "t3.micro"
  backup_retention_days = local.is_prod ? 14 : 3
  log_retention_days    = local.is_prod ? 30 : 7
}
Tags + TTL pour ressources temporaires
locals {
  common_tags = merge(
    {
      Project     = var.project
      Environment = var.environment
      Owner       = var.owner
      CostCenter  = var.cost_center
      ManagedBy   = "terraform"
    },
    var.temporary ? {
      Temporary = "true"
      ExpireAt  = var.expire_at
    } : {}
  )
}
Patterns FinOps Terraform
PatternBut
Approved sizesLimiter instances non standards.
Environment defaultsÉviter staging/dev trop gros.
Mandatory tagsAttribuer les coûts.
TTL temporaryNettoyer les ressources de test.
Retention by envLimiter logs/backups non-prod.
Lifecycle policiesArchiver ou supprimer stockage ancien.
Attention : réduire les coûts ne doit pas supprimer les protections critiques : backups, HA, monitoring, chiffrement ou sécurité.
FinOps dans la CI/CD Terraform

La CI/CD peut détecter les changements coûteux avant merge : estimation Infracost, contrôle des tags, blocage des tailles non approuvées, scan de ressources publiques, et commentaire automatique dans la merge request.

Pipeline FinOps type
Merge Request
    │
    ▼
terraform fmt / validate
    │
    ▼
terraform plan -out=tfplan
    │
    ▼
plan.json
    │
    ├── scan sécurité
    ├── contrôle tags
    ├── estimation coût
    └── policy-as-code
          │
          ▼
MR comment
    ├── delta coût
    ├── ressources coûteuses
    ├── tags manquants
    └── risques FinOps
          │
          ▼
Approval ou correction
Exemple job coût
terraform_cost_estimate:
  stage: plan
  image: infracost/infracost:ci-0.10
  script:
    - terraform show -json tfplan > plan.json
    - infracost breakdown --path plan.json --format table
  dependencies:
    - terraform_plan
  rules:
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
Contrôles CI FinOps
ContrôleDécision possible
Tags obligatoires manquantsBloquer la MR.
Instance type non approuvéBloquer ou demander approval.
Coût mensuel supérieur seuilApproval FinOps / lead.
NAT gateway en devWarning ou justification obligatoire.
Retention logs trop longueCorrection demandée.
Sandbox sans ExpireAtBloquer.
Exemple commentaire MR
FinOps review:
- Monthly cost delta: +85 EUR
- Main driver: new staging load balancer
- Required tags: OK
- Temporary resource: no
- Budget impact: within staging budget
- Recommendation: accepted if LB cannot be shared
Bonne pratique : rendre le coût visible dans la MR, au même niveau que le risque technique.
FinOps en production : optimiser sans fragiliser

En production, l’optimisation coût doit respecter la fiabilité. Réduire une instance, diminuer les backups ou supprimer une redondance peut être dangereux si l’impact n’est pas compris.

Optimisations production raisonnables
OptimisationConditionVérification
Rightsizing computeCPU/RAM faibles sur longue période.p95 ressources, latence, erreurs.
AutoscalingCharge variable.Cooldown, min/max, tests de charge.
Réduire retention logsConformité compatible.Besoin audit et investigation.
Lifecycle storageDonnées anciennes peu consultées.Politique archive/suppression validée.
Reserved / savings plansUsage stable et prévisible.Analyse historique.
Suppression ressources inutiliséesOwner confirme inutilité.Plan de rollback ou snapshot si data.
Règle : ne jamais optimiser une ressource critique sans métriques, owner et plan de retour.
Workflow optimisation prod
Coût élevé détecté
    │
    ▼
Identifier cost driver
    ├── compute
    ├── DB
    ├── network
    ├── storage
    └── logs
          │
          ▼
Analyser usage réel
    ├── 7 jours
    ├── 30 jours
    ├── pics
    └── saisonnalité
          │
          ▼
Proposer changement
    ├── gain attendu
    ├── risque
    ├── rollback
    └── owner
          │
          ▼
Apply contrôlé
          │
          ▼
Surveillance post-change
Post-check après optimisation
ZoneSignal
PerformanceLatence p95/p99 stable.
DisponibilitéHealth checks et 5xx OK.
CapacitéCPU/RAM/DB connexions non saturées.
CoûtDiminution visible après période d’observation.
AlertingAucune nouvelle alerte critique.
Bonne optimisation : elle réduit la dépense sans réduire aveuglément la résilience, la sécurité ou l’observabilité.
Anti-patterns Coûts & FinOps
Anti-patternPourquoi c’est dangereuxAlternative professionnelle
Créer sans estimerLe coût est découvert après facturation.Estimation coût avant apply.
Ressources non taguéesImpossible d’attribuer les dépenses.Tags obligatoires contrôlés en CI.
Sandbox permanenteCoût continu pour ressource temporaire.TTL, ExpireAt, cleanup automatique.
Staging identique prod sans besoinCoût élevé inutile.Parité fonctionnelle, sizing adapté.
Logs debug en continuExplosion ingestion observabilité.Niveaux log contrôlés et retention adaptée.
Surdimensionnement par peurGaspillage permanent.Metrics, autoscaling, rightsizing.
Optimiser sans métriquesRisque de panne ou dégradation.Analyse usage réel avant changement.
Supprimer sans ownerRisque de casser un service oublié.Validation owner + plan de rollback.
Mauvais modèle
Terraform apply
    ├── pas d'estimation coût
    ├── pas de tags
    ├── pas de budget
    ├── pas de TTL
    ├── logs illimités
    └── review uniquement technique
Résultat : la facture devient imprévisible et personne ne sait qui est responsable.
Bon modèle
Terraform + FinOps
    ├── estimation en MR
    ├── tags obligatoires
    ├── budgets par env
    ├── alertes anomalies
    ├── TTL sandbox
    ├── retention contrôlée
    └── owner coût identifié
Résultat : les coûts deviennent visibles, discutables, optimisables et responsables.
Checklist Coûts & FinOps avant apply
Checklist review Terraform
PointValidation attendue
Ressources ajoutéesListe claire des nouvelles ressources coûteuses.
Delta coûtEstimation mensuelle ou justification.
TagsProject, Environment, Owner, CostCenter, ManagedBy.
EnvironmentDev/staging/prod dimensionnés différemment.
TemporaryTTL ou ExpireAt si ressource temporaire.
StorageRetention, snapshots et lifecycle compris.
LogsVolume et retention maîtrisés.
NetworkNAT, egress, LB et inter-zone évalués.
BudgetAlerte ou suivi coût existant.
Checklist optimisation
Métriques usageCPU/RAM/DB/stockage analysés sur période suffisante.
Owner consultéL’équipe responsable valide le changement.
Risque identifiéPerformance, disponibilité, data, sécurité.
Rollback connuRetour arrière ou mitigation documenté.
Post-check prévuMétriques et alertes surveillées après apply.
Checklist CI/CD FinOps
ContrôleAction
Plan artifactConserver plan lisible.
Plan JSONPermettre analyse automatisée.
Cost estimatePublier delta coût en MR.
Tags policyBloquer ressources sans tags.
Allowed sizesContrôler instance types et storage.
Temporary policyForcer ExpireAt sur sandbox/review apps.
Approval seuilDemander validation si coût dépasse seuil.
Définition d’un bon geste FinOps : chaque ressource coûteuse est justifiée, taguée, surveillée, attribuée à un owner et revue avant production.
Mini-cheat-sheet
# Terraform plan cost flow
terraform plan -out=tfplan
terraform show -json tfplan > plan.json
terraform show -no-color tfplan > plan.txt

# Cost tools
infracost breakdown --path plan.json
checkov -d .
trivy config .

# Tags minimum
Project
Environment
Owner
CostCenter
ManagedBy

# Review questions
- What is the monthly delta?
- What is the main cost driver?
- Is the resource temporary?
- Are tags complete?
- Is a budget alert configured?
- Is the size justified by metrics?
2.5 Merge Request infra : documenter une MR Terraform lisible et validable
La Merge Request infra est un contrat de changement

Une MR Terraform ne doit pas seulement contenir du HCL. Elle doit expliquer pourquoi le changement existe, ce qu’il modifie, quel environnement est touché, quel risque opérationnel il introduit, comment le plan a été validé et comment revenir en arrière.

Le reviewer doit pouvoir lire la MR sans deviner l’intention. Une bonne MR infra réduit les incidents parce qu’elle force la réflexion avant l’apply : impact, sécurité, coût, state, rollback, monitoring et fenêtre de production.

Objectif professionnel : transformer une MR Terraform en document de décision : lisible, auditable, validable et exploitable en cas d’incident.
Ce qu’une MR infra doit répondre
QuestionRéponse attendue
Pourquoi ce changement ?Besoin métier, dette technique, sécurité, fiabilité, coût, standardisation.
Quel environnement ?Dev, staging, preprod, production, sandbox ou review app.
Quelles ressources ?Network, compute, DB, IAM, DNS, LB, logs, monitoring, storage.
Quel impact ?Disponibilité, sécurité, coût, performance, données, observabilité.
Quel plan Terraform ?Add/change/destroy/replace clairement résumés.
Quel rollback ?Revert, apply précédent, mitigation, feature flag, action manuelle contrôlée.
Flux d’une MR infra propre
Branche infra
    │
    ▼
Modification Terraform
    │
    ▼
Pipeline MR
    ├── fmt
    ├── validate
    ├── security scan
    ├── terraform plan
    ├── cost estimate
    └── plan artifact
          │
          ▼
Description MR
    ├── contexte
    ├── impact
    ├── risques
    ├── rollback
    ├── post-checks
    └── fenêtre prod si nécessaire
          │
          ▼
Review
    ├── DevOps
    ├── SRE
    ├── sécurité si IAM/réseau
    └── owner applicatif si impact métier
          │
          ▼
Approval + merge
          │
          ▼
Apply contrôlé
MR app vs MR infra
MR applicativeMR infrastructure
Change le comportement du code.Change la fondation d’exécution.
Rollback souvent image/version précédente.Rollback parfois plus complexe : réseau, state, DB, IAM.
Tests unitaires/fonctionnels.Plan, state, sécurité, coût, post-checks.
Risque bug métier.Risque downtime, sécurité, coût, perte data.
Règle : une MR infra sans résumé du plan et sans rollback documenté ne devrait pas être mergée vers production.
Template complet de Merge Request Terraform

Un template standard évite les oublis et donne aux nouveaux DevOps un cadre clair. Il doit être assez complet pour la production, mais pas au point de devenir bureaucratique pour les changements simples.

Template MR recommandé
## Context
Why is this change needed?
- Business / technical reason:
- Related ticket:
- Target environment:
- Affected service:

## Scope
What changes?
- Terraform root:
- Modules changed:
- Resources affected:
- Cloud account / region:

## Terraform plan summary
- To add:
- To change:
- To destroy:
- To replace:
- Sensitive resources touched:

## Risk analysis
- Availability impact:
- Security impact:
- Data impact:
- Cost impact:
- Operational complexity:

## Validation
- terraform fmt: OK
- terraform validate: OK
- security scan: OK
- terraform plan reviewed: OK
- staging tested: yes / no / not applicable

## Rollback / mitigation
- Rollback method:
- Mitigation if rollback is not immediate:
- Owner during deployment:

## Production window
- Required: yes / no
- Preferred window:
- People required:

## Post-checks
- Health checks:
- Logs:
- Metrics:
- Alerts:
- Business test:

## Notes for reviewers
- Specific lines or resources to review:
- Known limitations:
- Questions:
Version courte pour petits changements
## Summary
Short description of the infrastructure change.

## Environment
dev / staging / prod

## Plan
Add:
Change:
Destroy:
Replace:

## Risk
Low / Medium / High
Reason:

## Validation
- fmt OK
- validate OK
- plan reviewed
- no unexpected destroy

## Rollback
How to revert or mitigate.

## Post-check
What to verify after apply.
Quand utiliser quel template ?
Type de changementTemplate
Tags, dashboard, alarme non critiqueVersion courte.
Compute, autoscaling, logs, stockageTemplate complet conseillé.
Réseau, IAM, DB, DNS, load balancerTemplate complet obligatoire.
Production avec risque downtimeTemplate complet + approval + fenêtre.
Import ou state operationTemplate complet + mapping state/provider ID.
Bonne pratique : la description MR doit permettre à un reviewer absent du contexte de comprendre le changement en moins de 5 minutes.
Documenter le plan Terraform dans la MR

Le plan est le cœur de la validation. Le reviewer ne doit pas avoir à lire 800 lignes brutes pour comprendre le risque. La MR doit contenir un résumé humain du plan, avec les points sensibles.

Commandes de plan recommandées
terraform fmt -check -recursive
terraform validate

terraform plan -var-file="prod.tfvars" -out=tfplan
terraform show -no-color tfplan > plan.txt
terraform show -json tfplan > plan.json
Résumé de plan à mettre dans la MR
Terraform plan summary:
- Environment: production
- Terraform root: infra/live/prod/api
- Resources to add: 2
- Resources to change: 1
- Resources to destroy: 0
- Resources to replace: 0

Sensitive areas:
- Network: no public ingress added
- IAM: no wildcard permission
- Database: not touched
- DNS: not touched
- Cost impact: estimated +40 EUR/month

Plan artifact:
- plan.txt attached in pipeline artifacts
Règle : tout destroy ou replace doit être visible dans la description MR, pas caché dans l’artifact.
Lecture du plan : symboles
SymboleSignificationRéaction reviewer
+CréationVérifier tags, coût, sécurité, naming.
~ModificationComprendre impact runtime.
-/+RemplacementAnalyser downtime, identité, données.
-SuppressionValidation explicite obligatoire.
<=Data source lueVérifier dépendances et environnement.
Zones sensibles à extraire
RéseauSecurity groups, routes, NAT, public/private subnets.
IAMPolicies, roles, bindings, wildcards, trust relationships.
DonnéesDB, buckets, volumes, backups, snapshots.
DNS / TLSRecords, certificats, validation domain.
CoûtsInstances, DB, LB, NAT, logs, storage.
Bonne pratique : joindre le plan complet en artifact, mais écrire dans la MR un résumé lisible pour la décision.
Analyse de risque dans une MR infra

L’analyse de risque permet de décider du niveau de review, de l’approval nécessaire, de la fenêtre de production et de la stratégie de rollback.

Grille de risque
RisqueExemplesContrôle attendu
FaibleTags, description, dashboard, alarme non critique.Review simple.
MoyenCompute size, autoscaling, log retention, non-prod.Plan review + validation staging.
ÉlevéSecurity group, load balancer, DNS, IAM limité.Review senior + approval.
CritiqueDatabase, state, KMS, network core, suppression prod.Double approval + fenêtre + rollback documenté.
Bloc “Risk analysis” prêt à coller
Risk analysis:
- Availability impact: low / medium / high
- Security impact: low / medium / high
- Data impact: none / low / medium / high
- Cost impact: none / low / medium / high
- Rollback complexity: simple / moderate / complex
- Production window required: yes / no

Risk explanation:
This change modifies ...
The main risk is ...
The mitigation is ...
Diagramme de décision
MR Terraform
    │
    ▼
Touche production ?
    │
    ├── Non
    │     └── review standard
    │
    └── Oui
          │
          ▼
Touche DB, IAM, réseau, DNS ou state ?
          │
          ├── Oui
          │     ├── review senior
          │     ├── approval renforcé
          │     ├── rollback documenté
          │     └── fenêtre si nécessaire
          │
          └── Non
                ├── plan review
                └── post-checks
Questions de risque obligatoires
Peut-on provoquer un downtime ?LB, DNS, network, compute, DB.
Peut-on exposer un service ?Security group, firewall, public IP, IAM.
Peut-on perdre ou corrompre des données ?DB, bucket, volume, backup, lifecycle.
Peut-on augmenter fortement la facture ?Instance, DB, NAT, logs, storage.
Peut-on bloquer les prochains applies ?State, backend, provider, import, lock.
Attention : “faible risque” doit être justifié par le contenu du plan, pas par l’intuition de l’auteur.
Rollback et mitigation dans une MR Terraform

Une MR infra doit expliquer comment revenir en arrière ou réduire l’impact si le changement provoque un incident. Pour Terraform, un rollback n’est pas toujours un simple revert Git.

Rollback par type de changement
ChangementRollback typiqueAttention
Tag / metadataRevert commit puis apply.Faible risque.
Security groupRestaurer règle précédente.Ne pas ouvrir trop large en urgence.
DNSRestaurer ancien record.TTL et propagation.
Load balancerRestaurer listener/routing/target group.Health checks et trafic réel.
IAMRestaurer policy précédente.Propagation et blast radius.
DatabaseRollback souvent non trivial.Backup, snapshot, mitigation, DBA.
State operationRestaurer state backup ou state mv inverse.Très sensible, review obligatoire.
Bloc MR rollback
Rollback / mitigation:
- Preferred rollback:
  Revert this MR and apply the previous Terraform plan.

- If immediate rollback is unsafe:
  Apply a minimal mitigation:
  - restore previous security group rule
  - disable new listener rule
  - switch DNS back to previous target

- Validation after rollback:
  - health endpoint OK
  - 5xx rate stable
  - latency p95 stable
  - no new critical alert

- Owner during rollback:
  Platform team / on-call DevOps
Diagramme rollback
Incident après apply
    │
    ▼
Identifier changement responsable
    │
    ▼
Rollback simple possible ?
    │
    ├── Oui
    │     ├── revert commit
    │     ├── terraform plan
    │     ├── review du rollback plan
    │     └── terraform apply
    │
    └── Non
          ├── mitigation minimale
          ├── correction ciblée
          ├── backup / restore si data
          └── escalade expert
    │
    ▼
Post-checks
    ├── health
    ├── logs
    ├── metrics
    └── alerts
Commandes de rollback contrôlé
# Revenir au commit précédent par revert
git revert <commit_id>
git push origin main

# Générer un plan de rollback
terraform plan -var-file="prod.tfvars" -out=tfplan
terraform show -no-color tfplan > rollback-plan.txt

# Appliquer seulement après review
terraform apply tfplan
Règle : un rollback Terraform doit lui aussi être relu. Il peut contenir des suppressions ou remplacements inattendus.
Comment reviewer une MR Terraform

Le reviewer ne doit pas seulement regarder la syntaxe. Il doit vérifier le plan, le state, les dépendances, les risques, les tags, les coûts, les secrets, la sécurité et la capacité de rollback.

Checklist reviewer
ZoneÀ vérifier
ContexteLa raison du changement est claire.
PlanAdd/change/destroy/replace cohérents.
EnvironmentBon root, bon backend, bons tfvars.
StatePas de confusion dev/staging/prod.
RéseauPas d’ouverture large non justifiée.
IAMPas de wildcard ou privilège excessif.
DonnéesDB, buckets, volumes protégés.
CoûtsRessources coûteuses justifiées et taguées.
RollbackRéellement faisable et documenté.
Commentaires reviewer utiles
Good review comments:

- The plan shows a replacement of the load balancer.
  Is this expected? What is the downtime risk?

- This security group opens port 5432 to a broad CIDR.
  Can we restrict it to the application security group?

- The new database has deletion protection disabled.
  Is this intentional for production?

- This resource is missing CostCenter and Owner tags.

- Rollback mentions revert only.
  Can you add the exact validation steps after rollback?
Questions à poser
“Pourquoi ce changement maintenant ?”Valider le besoin.
“Que dit le plan exactement ?”Éviter les surprises.
“Qu’est-ce qui peut casser ?”Identifier le risque réel.
“Comment voit-on que c’est OK ?”Définir les post-checks.
“Comment revient-on en arrière ?”Valider la mitigation.
Bonne review : elle réduit le risque opérationnel sans bloquer inutilement la livraison.
Approval : qui doit valider quoi ?

Toutes les MR Terraform ne nécessitent pas le même niveau d’approbation. L’approval doit dépendre de l’environnement, du type de ressource et du risque.

Matrice d’approbation
ChangementReviewer requisApproval
Dev non critiqueDevOps ou pair technique.1 approval.
Staging compute/logsDevOps + owner service si impact.1 approval.
Prod compute/autoscalingDevOps senior ou SRE.1 à 2 approvals.
Prod réseau / LB / DNSDevOps senior + owner applicatif.Approval renforcé.
Prod IAM / sécuritéDevOps senior + sécurité.Approval sécurité.
Prod DB / stateDevOps senior + DBA/SRE + owner.Double approval + fenêtre.
Critères Go / No-Go
CritèreGoNo-Go
PlanCompris et attendu.Destroy/replace inexpliqué.
RollbackClair et réalisable.Absent ou irréaliste.
SécuritéRisque accepté ou absent.Secret exposé, IAM trop large.
MonitoringPost-checks définis.Impact invisible.
Flux approval production
MR ouverte
    │
    ▼
Pipeline vert
    │
    ├── fmt
    ├── validate
    ├── security scan
    ├── plan
    └── cost estimate
          │
          ▼
Review technique
          │
          ▼
Review risque
    ├── réseau
    ├── IAM
    ├── data
    ├── state
    └── coût
          │
          ▼
Approval
          │
          ▼
Merge
          │
          ▼
Apply manuel protégé
GitLab protections utiles
Protected branchesEmpêcher merge non autorisé vers main.
Merge request approvalsForcer review selon règles.
CODEOWNERSAssigner reviewers par dossier infra.
Protected environmentsLimiter qui peut déployer production.
Required pipeline successInterdire merge si tests échouent.
Attention : approval ne veut pas dire “j’ai vu passer”. Cela veut dire “j’ai compris et j’accepte le risque”.
CI/CD attendue pour une MR Terraform

La CI/CD doit produire les preuves nécessaires à la review : format, validation, scan sécurité, plan lisible, estimation coût et artifacts.

Pipeline MR recommandé
stages:
  - lint
  - validate
  - security
  - plan
  - cost

variables:
  TF_IN_AUTOMATION: "true"
  TF_INPUT: "false"
  TF_ROOT: "infra/live/staging/app"

default:
  image: hashicorp/terraform:1.6.6
  before_script:
    - cd "$TF_ROOT"
    - terraform init

terraform_fmt:
  stage: lint
  script:
    - terraform fmt -check -recursive

terraform_validate:
  stage: validate
  script:
    - terraform validate

terraform_plan:
  stage: plan
  script:
    - terraform plan -out=tfplan
    - terraform show -no-color tfplan > plan.txt
    - terraform show -json tfplan > plan.json
  artifacts:
    paths:
      - "$TF_ROOT/tfplan"
      - "$TF_ROOT/plan.txt"
      - "$TF_ROOT/plan.json"
    expire_in: 3 days
Contrôles CI à inclure
ContrôleBut
fmtCode standardisé.
validateSyntaxe et configuration valides.
tflintQualité Terraform et règles provider.
checkov / trivy / tfsecRisques sécurité IaC.
plan artifactReview humaine complète.
plan JSONContrôles automatiques et coût.
infracostImpact financier avant merge.
Debug CI sécurisé
echo "Branch: $CI_COMMIT_BRANCH"
echo "Environment: $CI_ENVIRONMENT_NAME"
echo "Terraform root: $TF_ROOT"
terraform --version

# Vérifier présence sans exposer
if [ -z "$AWS_ACCESS_KEY_ID" ]; then
  echo "AWS_ACCESS_KEY_ID is missing"
  exit 1
else
  echo "AWS_ACCESS_KEY_ID is present"
fi
Règle : ne jamais utiliser env, printenv ou echo $SECRET pour déboguer une MR infra.
Exemples de MR infra bien documentées
Exemple 1 : ajout d’une alarme CloudWatch / monitoring
Summary:
Add CPU and HTTP 5xx alerts for production API.

Environment:
production

Plan:
- Add: 2 monitoring alarms
- Change: 0
- Destroy: 0
- Replace: 0

Risk:
Low. No runtime resource is modified.
Only monitoring resources are added.

Validation:
- terraform fmt OK
- terraform validate OK
- terraform plan reviewed
- no destroy
- alert names and thresholds checked

Rollback:
Revert MR and apply previous plan.

Post-check:
- Alarms visible in monitoring console
- Notification channel receives test event
Exemple 2 : modification security group DB
Summary:
Allow API service security group to reach PostgreSQL on port 5432.

Environment:
production

Plan:
- Add: 1 ingress rule
- Change: 1 security group
- Destroy: 0
- Replace: 0

Risk:
Medium/high. Network access to DB is modified.
No public CIDR is introduced.
Source is restricted to API security group.

Validation:
- plan reviewed
- no 0.0.0.0/0
- staging connectivity tested
- DB logs monitored

Rollback:
Remove the ingress rule by reverting this MR.
If urgent, apply minimal SG rule rollback.

Post-check:
- API can connect to DB
- no new DB connection errors
- 5xx stable
Exemple 3 : changement de taille instance
Summary:
Increase staging worker instance type from t3.micro to t3.small.

Environment:
staging

Reason:
Current workers show sustained CPU saturation during batch tests.

Plan:
- Change: worker launch template instance_type
- Replace: rolling replacement through autoscaling
- Destroy: 0 direct unmanaged destroy

Risk:
Medium. Temporary capacity fluctuation during rollout.

Cost impact:
Estimated +25 EUR/month in staging.

Rollback:
Revert instance_type to t3.micro and apply.
If saturation returns, reduce batch concurrency.

Post-check:
- workers healthy
- queue backlog decreasing
- CPU below 70%
- no failed jobs
Exemple 4 : import ressource existante
Summary:
Import existing production API security group into Terraform state.

Environment:
production

Resource:
- Terraform address: aws_security_group.api
- Provider ID: sg-0abc123456789def0
- State key: prod/network/terraform.tfstate

Plan:
- Import only
- Expected diff: tags normalization
- Destroy: 0
- Replace: 0

Risk:
Medium. Future plans may modify this SG if code is not aligned.

Validation:
- state backup created
- terraform state show reviewed
- plan reviewed
- no unexpected rule deletion

Rollback:
terraform state rm aws_security_group.api if mapping is wrong,
using state backup if needed.
Modèle à suivre : résumé clair, plan clair, risque clair, rollback clair, post-check clair.
Anti-patterns des Merge Requests infra
Anti-patternPourquoi c’est dangereuxCorrection professionnelle
Description videLe reviewer doit deviner l’intention.Template MR obligatoire.
“Juste un petit changement”Minimise sans preuve.Résumer le plan et le risque.
Plan non jointImpossible de valider l’impact réel.Artifact plan.txt obligatoire.
Destroy caché dans le planSuppression non relue.Afficher destroy/replace dans la MR.
Rollback absentImprovisation pendant incident.Rollback ou mitigation documenté.
Pas de post-checkApply réussi mais prod non vérifiée.Health, logs, metrics, alertes.
Secrets dans logs MRFuite durable.Variables protégées et debug sans valeurs.
Review purement syntaxiqueRisque opérationnel ignoré.Review plan, state, sécurité, coût.
Mauvais modèle
MR infra faible
    ├── description vide
    ├── pas de plan résumé
    ├── pas de risk analysis
    ├── pas de rollback
    ├── pas de post-check
    └── merge rapide
Résultat : le risque est découvert au moment de l’apply ou de l’incident.
Bon modèle
MR infra professionnelle
    ├── contexte clair
    ├── plan résumé
    ├── risques explicités
    ├── rollback documenté
    ├── coût visible
    ├── checks CI
    ├── approval adapté
    └── post-checks définis
Résultat : le changement est compréhensible, validable et récupérable.
Checklist Merge Request infra
Checklist auteur de MR
PointValidation attendue
ContextePourquoi le changement est nécessaire.
PérimètreEnvironnement, root Terraform, ressources touchées.
PlanAdd/change/destroy/replace résumés.
Pipelinefmt, validate, scan, plan OK.
RisqueDisponibilité, sécurité, data, coût, state.
RollbackProcédure ou mitigation réaliste.
Post-checksHealth, logs, métriques, alertes, test métier.
SecretsAucun secret dans code, logs, plan, artifacts.
CostImpact coût mentionné si ressource coûteuse.
Checklist reviewer
Je comprends l’objectif.Pas de contexte flou.
Je comprends le plan.Aucun diff important ignoré.
Je vois le risque.Réseau, IAM, DB, DNS, state, coût.
Je peux valider le rollback.Pas de promesse vague.
Je sais quoi vérifier après apply.Post-checks précis.
Checklist production
QuestionRéponse attendue
La MR touche-t-elle production ?Oui/non clairement indiqué.
Y a-t-il un destroy ?Non ou explicitement justifié.
Y a-t-il un replace ?Non ou downtime analysé.
La DB est-elle touchée ?Si oui, backup/protection/review senior.
IAM ou réseau est-il modifié ?Review sécurité ou senior.
Une fenêtre est-elle nécessaire ?Oui si changement à risque.
L’apply sera-t-il manuel ?Oui pour production.
Les dashboards sont-ils prêts ?Oui si impact runtime.
Définition d’une MR infra professionnelle : le reviewer comprend le besoin, le plan, le risque, le rollback, les checks et le niveau d’approbation nécessaire.
Mini-cheat-sheet MR infra
MR Terraform must include:
- Context
- Environment
- Terraform root
- Plan summary
- Risk analysis
- Security impact
- Cost impact
- Rollback / mitigation
- Post-checks
- Reviewers / approvals

Commands:
terraform fmt -check -recursive
terraform validate
terraform plan -out=tfplan
terraform show -no-color tfplan > plan.txt
terraform show -json tfplan > plan.json
2.7 Approvals & protections : branches, environnements, droits et production
Approvals & protections : empêcher l’erreur humaine en production

Les protections GitLab ne sont pas de la bureaucratie. Elles servent à éviter qu’un changement non relu, non testé, mal ciblé ou exécuté par la mauvaise personne modifie la production.

Pour l’infrastructure, le risque est plus élevé qu’une simple MR applicative : un mauvais apply Terraform peut modifier un security group, casser un DNS, supprimer une ressource, changer une policy IAM, exposer un service ou bloquer une base de données.

Objectif professionnel : faire en sorte que la production ne puisse être modifiée que depuis un chemin contrôlé : branche protégée, MR relue, pipeline vert, approval adapté, environnement protégé et apply manuel traçable.
Les protections essentielles
ProtectionButExemple
Protected branchesEmpêcher push direct ou merge non autorisé.main, release/*.
Merge request approvalsForcer une revue humaine avant merge.1 ou 2 approvals selon risque.
Protected environmentsLimiter qui peut déployer vers production.Seuls Maintainers/SRE peuvent lancer apply prod.
Protected variablesLimiter les secrets aux branches/tags protégés.Credentials prod indisponibles en feature branch.
CODEOWNERSAssigner automatiquement les bons reviewers.Sécurité relit IAM, DBA relit DB.
Required pipeline successBloquer merge si CI échoue.fmt, validate, scan, plan obligatoires.
Chaîne de protection recommandée
Developer branch
    │
    ▼
Merge Request
    │
    ├── terraform fmt
    ├── terraform validate
    ├── security scan
    ├── terraform plan
    └── cost estimate
          │
          ▼
Approval rules
    ├── DevOps reviewer
    ├── Security reviewer if IAM/network
    ├── DBA reviewer if database
    └── SRE reviewer if prod risk
          │
          ▼
Merge to protected branch
          │
          ▼
Production pipeline
    ├── protected variables
    ├── protected runner
    ├── protected environment
    └── manual apply
          │
          ▼
Audited production change
Principe de défense en profondeur
CoucheProtection
GitBranches protégées, MR obligatoire.
CIPipeline obligatoire, tests et scans.
ReviewApprovals et CODEOWNERS.
SecretsVariables protected/scoped, OIDC, IAM minimal.
DeployEnvironment protégé, apply manuel.
AuditTrace MR, pipeline, approver, job, plan.
Règle : aucun utilisateur seul ne devrait pouvoir modifier la production sans trace, sans revue et sans pipeline validé.
Branches protégées : contrôler le chemin vers production

Les branches protégées empêchent les push directs, limitent qui peut merger et garantissent que les changements passent par une MR, une CI et une review.

Politique de branches recommandée
BrancheUsageProtection
feature/*Travail individuel.Pas de secrets prod, pas d’apply prod.
developIntégration dev.Pipeline requis selon équipe.
release/*Préparation staging/preprod.Review + pipeline vert.
mainSource officielle production.Protected, MR only, approvals, pipeline success.
hotfix/*Correction urgente encadrée.Review rapide mais obligatoire si prod.
Règles à appliquer sur main
  • Interdire le push direct.
  • Autoriser le merge seulement aux Maintainers ou Owners.
  • Exiger pipeline vert avant merge.
  • Exiger une ou plusieurs approvals.
  • Empêcher la suppression de la branche.
  • Limiter les variables production aux branches protégées.
Bonne pratique : main doit représenter l’état validé, relu et déployable de l’infrastructure.
Flux Git attendu
feature/infra-change
    │
    ▼
Merge Request
    │
    ├── pipeline MR
    ├── plan artifact
    ├── review
    └── approval
          │
          ▼
main protected
    │
    ▼
Pipeline production
    │
    ├── plan final
    ├── apply manual
    └── protected environment
Erreurs fréquentes
ErreurRisqueCorrection
Push direct sur mainPas de review, pas de discussion, risque prod.Protected branch + MR obligatoire.
Merge malgré CI rougeCode infra non validé.Require pipeline success.
Secrets prod disponibles sur feature branchFuite ou usage non autorisé.Protected variables.
Maintainers trop nombreuxTrop de personnes peuvent merger prod.Limiter rôles et auditer régulièrement.
Règle : une branche protégée mal configurée donne une fausse impression de sécurité. Il faut vérifier les droits réels.
Environnements protégés : limiter qui peut déployer

Une branche protégée contrôle le code. Un environnement protégé contrôle le déploiement. Pour Terraform, cela signifie limiter qui peut lancer un apply sur staging ou production.

Modèle d’environnements
EnvironnementDéploiement autorisé parNiveau de contrôle
developmentDevelopers / DevOps selon équipe.Souple, mais secrets limités.
stagingDevOps, Maintainers.Contrôle intermédiaire.
preproductionDevOps senior / SRE.Proche production.
productionSRE, Maintainers autorisés, release managers.Strict, approval + manual apply.
Job apply production
terraform_apply_prod:
  stage: apply
  environment:
    name: production
  script:
    - terraform apply tfplan
  when: manual
  allow_failure: false
  rules:
    - if: '$CI_COMMIT_BRANCH == "main"'
  tags:
    - protected
    - terraform
    - prod
Bonne pratique : le job production doit être manuel, sur environnement protégé, avec runner protégé et variables protégées.
Chaîne environment protection
main protected
    │
    ▼
pipeline production
    │
    ▼
manual job apply_prod
    │
    ├── environment: production
    ├── protected environment
    ├── protected variables
    ├── protected runner
    └── authorized deployers only
          │
          ▼
terraform apply production
À protéger explicitement
ÉlémentPourquoi
Environment productionEmpêcher n’importe qui de lancer apply.
Runner productionÉviter exécution sur runner partagé non maîtrisé.
Variables productionSecrets accessibles seulement au contexte autorisé.
Artifacts de planÉviter manipulation ou plan obsolète.
State backendAccès IAM limité et audité.
Attention : protéger la branche ne suffit pas si l’environnement production reste déployable par trop de personnes.
Approval rules : adapter la validation au risque

Les règles d’approval doivent refléter la criticité du changement. Un tag non critique ne nécessite pas le même niveau de validation qu’un changement IAM, database, DNS ou network core.

Matrice d’approbation infra
Type de MRApproval minimumReviewer recommandé
Docs, tags, dashboard non critique1DevOps pair.
Compute non-prod1DevOps ou service owner.
Staging proche prod1 à 2DevOps + owner applicatif.
Production compute/autoscaling2DevOps senior + SRE.
Production network/DNS/LB2DevOps senior + service owner.
Production IAM/security2 + sécuritéSecurity reviewer obligatoire.
Production DB/state2 + expertDBA/SRE + DevOps senior.
Règle simple
Low risk:
  1 reviewer

Medium risk:
  1 DevOps reviewer + plan artifact

High risk:
  2 reviewers + rollback documented

Critical:
  2 reviewers + expert approval + production window + post-checks
Décision approval par impact
MR Terraform
    │
    ▼
Environment = production ?
    │
    ├── No
    │     └── standard approval
    │
    └── Yes
          │
          ▼
Touches sensitive area ?
    ├── IAM
    ├── network
    ├── DNS
    ├── database
    ├── state
    └── secrets
          │
          ▼
Yes: expert reviewer required
No: standard prod reviewer
          │
          ▼
Pipeline green + approval
          │
          ▼
Merge / apply manual
Approval ne doit pas être automatique
Mauvaise validationBonne validation
“LGTM” sans lire le plan.“Plan reviewed, no destroy, SG source restricted.”
Approval par habitude.Approval avec risque compris.
Reviewer non compétent sur la zone.Reviewer adapté : IAM, DB, réseau, SRE.
Approval malgré pipeline rouge.Pipeline vert requis.
Règle : approuver une MR infra, c’est accepter la responsabilité technique du changement, pas seulement cliquer sur un bouton.
Séparation des droits : éviter le super-pouvoir permanent

La séparation des droits réduit le risque d’erreur, de compromission et d’action non autorisée. Un développeur peut contribuer au code Terraform sans avoir le droit d’appliquer en production.

Modèle de rôles recommandé
RôleDroits GitLabDroits infra
DeveloperCréer branches/MR.Aucun apply prod.
DevOpsReviewer, maintenir pipelines.Apply dev/staging selon règles.
MaintainerMerge sur branches protégées.Apply prod si autorisé.
SRE / Release managerValider et déclencher prod.Accès prod contrôlé et audité.
SecurityReview IAM/secrets/network.Pas forcément apply, mais approval sécurité.
Break-glassAccès urgence temporaire.Très contrôlé, journalisé, révocable.
Séparer contribution et exécution
Developer
    ├── écrit Terraform
    ├── ouvre MR
    └── lit le plan

Reviewer
    ├── relit code
    ├── relit plan
    └── approuve

Authorized deployer
    ├── déclenche apply
    ├── surveille production
    └── documente résultat
Least privilege GitLab + cloud
ZonePrincipeExemple
GitLab projectAccès minimum nécessaire.Pas Maintainer pour tout le monde.
Protected branchMerge limité.Maintainers uniquement.
Protected environmentDeploy limité.SRE / release managers.
Cloud IAMRôle CI limité.Plan role ≠ apply role.
SecretsDisponibles uniquement au contexte utile.Prod variables sur main + prod env.
Exemple de séparation plan/apply
terraform_plan_prod:
  stage: plan
  environment:
    name: production
  script:
    - terraform plan -out=tfplan
  rules:
    - if: '$CI_COMMIT_BRANCH == "main"'

terraform_apply_prod:
  stage: apply
  environment:
    name: production
  script:
    - terraform apply tfplan
  when: manual
  rules:
    - if: '$CI_COMMIT_BRANCH == "main"'
Bonne pratique : celui qui écrit le changement ne devrait pas toujours être le seul à pouvoir le valider et le déployer.
Production : apply manuel, fenêtre et traçabilité

En production, l’apply Terraform doit être traité comme une opération contrôlée. Le pipeline doit empêcher l’exécution automatique non maîtrisée et fournir une trace complète.

Règles production
RèglePourquoi
Apply manuelÉviter modification prod automatique sans décision.
Pipeline vertfmt, validate, plan et scans validés.
Approval avant mergeReview du plan et du risque.
Environment protégéSeules personnes autorisées peuvent déployer.
Fenêtre si risqueÉquipe disponible pour surveiller et rollback.
Post-checksVérifier que la prod fonctionne réellement.
Runbook apply production
Before apply:
- MR approved
- pipeline green
- plan reviewed
- no unexpected destroy/replace
- rollback documented
- dashboards open
- production window confirmed if needed

During apply:
- trigger manual job
- monitor job logs
- do not run concurrent apply

After apply:
- run health checks
- check logs
- check metrics
- check alerts
- document result
Timeline production
T-30 min
    ├── confirm approval
    ├── review latest plan
    ├── open dashboards
    └── announce change

T0
    ├── trigger manual apply
    └── monitor pipeline

T+5 min
    ├── verify cloud resources
    ├── healthcheck
    └── logs

T+15 min
    ├── metrics
    ├── alerts
    └── business smoke test

T+30 min
    ├── close change
    └── document outcome
Post-checks à exiger
ZoneValidation
ApplicationHealth endpoint OK.
HTTP5xx stables, latence p95/p99 stable.
InfrastructureResources healthy, no unexpected drift.
DatabaseConnexions, locks, slow queries OK.
AlertingAucune nouvelle alerte critique.
SecurityPas d’ouverture ou permission inattendue.
Règle : un apply production déclenché automatiquement après merge est dangereux si l’équipe n’a pas une maturité très élevée et des garde-fous solides.
CODEOWNERS : router les reviews aux bonnes personnes

CODEOWNERS permet d’assigner automatiquement des reviewers selon les fichiers modifiés. Pour l’infra, c’est très utile : les changements IAM, réseau, DB ou production doivent être relus par les bonnes personnes.

Exemple CODEOWNERS infra
# Global infrastructure owners
/infra/ @platform-team

# Production requires SRE review
/infra/live/prod/ @sre-team @platform-leads

# IAM and security-sensitive files
/infra/modules/iam/ @security-team @platform-team
/infra/**/iam*.tf @security-team

# Network
/infra/modules/network/ @network-team @platform-team
/infra/**/security_group*.tf @platform-team

# Databases
/infra/modules/database/ @dba-team @sre-team
/infra/**/rds*.tf @dba-team

# CI templates
/.gitlab/ci/ @devops-team
/.gitlab-ci.yml @devops-team
Bonne pratique : utiliser CODEOWNERS pour forcer la bonne compétence, pas seulement pour ajouter des noms automatiquement.
Mapping fichiers → reviewers
Fichiers modifiésReviewer attenduPourquoi
infra/live/prod/**SRE / platform leadImpact production.
modules/iam/**SecurityRisque privilèges.
modules/network/**Network / DevOps seniorRisque connectivité.
modules/database/**DBA / SRERisque data.
.gitlab-ci.ymlDevOpsRisque pipeline/secrets.
Pièges CODEOWNERS
Trop de owners globauxLes reviews deviennent symboliques.
Owners absents ou anciensBlocage ou validation par mauvaises personnes.
Pas de règles par zone sensibleIAM/DB/réseau relus par personnes non expertes.
CODEOWNERS non obligatoireSuggestion sans enforcement.
Attention : CODEOWNERS doit être maintenu. Un fichier obsolète donne une fausse sécurité.
Secrets, variables protégées et scopes

Les protections GitLab doivent empêcher qu’une branche non protégée, une MR externe, un runner partagé ou un job non prévu accède aux secrets production.

Variables GitLab à protéger
OptionUsageExemple
MaskedMasquer dans les logs.Tokens, passwords, cloud keys.
ProtectedDisponible uniquement branches/tags protégés.Credentials production.
Environment scopeLimiter à un environnement.production, staging.
File variableStocker clé/certificat/kubeconfig en fichier.Kubeconfig, private key.
Mapping recommandé
DEV credentials:
  protected: false or limited
  environment scope: development

STAGING credentials:
  protected: true if release branches are protected
  environment scope: staging

PROD credentials:
  protected: true
  environment scope: production
  available only from main / protected tags
OIDC et credentials courts
GitLab protected job
    │
    ▼
OIDC token
    │
    ▼
Cloud IAM trust policy
    ├── project allowed
    ├── branch allowed
    ├── environment allowed
    └── audience checked
          │
          ▼
Temporary credentials
    │
    ▼
Terraform plan/apply
Debug sécurisé
# Good: check presence only
if [ -z "$AWS_ACCESS_KEY_ID" ]; then
  echo "AWS_ACCESS_KEY_ID is missing"
  exit 1
else
  echo "AWS_ACCESS_KEY_ID is present"
fi

# Bad: exposes secrets
env
printenv
echo "$AWS_SECRET_ACCESS_KEY"
set -x
Règle : un secret production ne doit jamais être disponible sur une branche non protégée ni sur un job non lié à production.
Audit : prouver qui a validé et qui a déployé

Une protection utile doit laisser une trace : qui a ouvert la MR, qui l’a approuvée, quel plan a été relu, qui a lancé l’apply, avec quels credentials, et quel résultat a été observé.

Éléments à auditer
ÉlémentPreuve attendue
MRDescription, discussions, reviewers, approvals.
PipelineJobs, logs, artifacts, statut, durée.
Plan Terraformplan.txt, résumé add/change/destroy/replace.
ApplyJob manuel, déclencheur, environnement, heure.
VariablesProtected/scoped, pas de secret exposé.
Cloud auditRôle utilisé, API calls, ressources modifiées.
Post-checksHealth, logs, metrics, alertes, notes de changement.
Questions d’audit post-change
- Who approved the MR?
- Was the pipeline green before merge?
- Which plan artifact was reviewed?
- Who triggered production apply?
- Which protected environment was used?
- Which cloud role executed the change?
- Were there unexpected destroy/replace actions?
- Were post-checks completed?
- Was rollback documented?
Audit trail idéal
MR approved
    │
    ├── approver identity
    ├── plan artifact
    ├── discussion history
    └── risk acceptance
          │
          ▼
Pipeline apply
    │
    ├── manual trigger user
    ├── protected environment
    ├── protected runner
    └── job logs
          │
          ▼
Cloud audit
    │
    ├── assumed role
    ├── API calls
    ├── resources changed
    └── timestamp
          │
          ▼
Post-change evidence
    ├── health checks
    ├── metrics
    ├── logs
    └── incident/change ticket
À conserver
Plan artifactPreuve du changement prévu.
Pipeline logsPreuve d’exécution.
MR discussionPreuve de décision et review.
Cloud audit logsPreuve des actions réelles.
Change ticketContexte métier et opérationnel.
Bonne pratique : après un incident, on doit pouvoir reconstruire la séquence depuis GitLab et les logs cloud sans dépendre de la mémoire humaine.
Anti-patterns approvals & protections
Anti-patternPourquoi c’est dangereuxAlternative professionnelle
Tout le monde MaintainerTrop de personnes peuvent merger ou déployer.Rôles minimaux et revue périodique.
Push direct sur mainContourne MR, CI et review.Protected branch + MR obligatoire.
Approval symboliquePersonne ne lit réellement le plan.Approval avec checklist et responsabilité.
Apply prod automatiqueChange prod sans décision humaine immédiate.Manual apply + environment protégé.
Secrets prod sur branches non protégéesFuite ou usage non autorisé.Protected + environment scoped variables.
Runner partagé pour productionSurface d’attaque plus large.Runner protégé dédié infra/prod.
CODEOWNERS obsolèteMauvais reviewers ou blocages.Maintenance régulière.
Pas d’audit des permissionsDroits accumulés avec le temps.Review trimestrielle des accès.
Mauvais modèle
GitLab non protégé
    ├── push direct main
    ├── variables prod globales
    ├── apply automatique
    ├── runner partagé
    ├── approval symbolique
    └── pas de CODEOWNERS
Résultat : un changement production peut passer sans contrôle réel.
Bon modèle
GitLab protégé
    ├── protected branches
    ├── MR obligatoire
    ├── pipeline vert requis
    ├── approval rules
    ├── CODEOWNERS
    ├── protected variables
    ├── protected environment
    └── manual apply prod
Résultat : le chemin vers production devient contrôlé, auditable et réversible.
Checklist Approvals & protections
Checklist GitLab project
ContrôleValidation attendue
Protected branch mainPush direct interdit, merge limité.
Pipeline success requiredPas de merge si CI rouge.
Approval rulesNombre d’approvals adapté au risque.
CODEOWNERSReviewers par zone sensible.
Protected environmentProduction déployable seulement par autorisés.
Protected variablesSecrets prod limités aux contextes protégés.
Protected runnersJobs prod sur runners maîtrisés.
Audit accèsMaintainers et deployers revus régulièrement.
Checklist MR production
Description claireContexte, scope, risque, rollback.
Plan artifactplan.txt disponible.
Destroy/replaceAbsents ou justifiés explicitement.
Approval expertPrésent si IAM, réseau, DB, state.
Post-checksHealth, logs, metrics, alertes.
Checklist sécurité des droits
QuestionRéponse attendue
Qui peut merger sur main ?Liste courte et justifiée.
Qui peut lancer apply prod ?Personnes explicitement autorisées.
Les secrets prod sont-ils protégés ?Masked, protected, scoped production.
Le runner prod est-il dédié ?Oui, ou risque accepté et documenté.
Les rôles cloud sont-ils minimaux ?Least privilege, pas admin permanent.
Les accès sont-ils revus ?Revue périodique et suppression des anciens accès.
Définition d’un GitLab infra protégé : personne ne peut modifier la production sans MR, pipeline vert, approval adapté, droits limités, environnement protégé et trace d’audit.
Mini-cheat-sheet
Must have:
- Protected branch main
- No direct push to main
- Required pipeline success
- MR approvals
- CODEOWNERS for sensitive paths
- Protected production environment
- Manual apply for production
- Protected and scoped variables
- Protected runner for production
- Regular access review

Sensitive paths:
infra/live/prod/**
infra/modules/iam/**
infra/modules/network/**
infra/modules/database/**
.gitlab-ci.yml