Skip to content

Sprint 6 Report — Multi-environnements

PĂ©riode : 2026-07-07 Ă  2026-08-17 Release : aucune — main reste une archive (#57), la promotion se fait par overlay Équipe : 1 ingĂ©nieur DevOps (Youssef Kadi) Repo : gitlab.com/yk-devops/fastapi-eks-project


Executive Summary

À l'entrĂ©e du Sprint 6, la plateforme Ă©tait complĂšte mais mono-environnement : une seule instance de l'API, une seule base, un seul jeu de secrets, et aucune façon de valider un changement ailleurs qu'en production. Ce sprint a livrĂ© la sĂ©paration dev / staging / prod sur un cluster unique, par isolation de namespace et overlays Kustomize (ADR 029), avec deux ApplicationSet ArgoCD et une promotion d'image par merge request dĂ©libĂ©rĂ©e.

Le socle est en place et prouvé en conditions réelles : trois bases de données, trois rÎles IRSA aux permissions cloisonnées, un DNS à plat, une isolation inter-environnements vérifiée à trois niveaux (réseau, quota, identité cloud) et une rétention d'images par environnement. Le Gateway reste partagé, un seul NLB pour les trois environnements, fastapi devenant un namespace de plateforme pendant que les charges vivent dans fastapi-<env>.

Mais la signature du sprint est ailleurs. Le multi-environnements a servi de rĂ©vĂ©lateur. En mettant trois environnements sous le mĂȘme cluster, il a rendu visibles des dĂ©fauts qui existaient dĂ©jĂ  et que l'instance unique masquait : deux environnements exposĂ©s publiquement en clair et branchĂ©s sur la base de production, aucune redirection HTTP vers HTTPS, un plafond d'autoscaling rĂ©el de 3 replicas lĂ  oĂč le tableau de bord en annonçait 5, des 503 servis sous charge par deux causes distinctes, et la rĂ©tention du registre qui a supprimĂ© l'image servie par la production. Deux incidents de sĂ©curitĂ© et sept incidents techniques ont Ă©tĂ© capitalisĂ©s.

Conséquence directe sur le pilotage : 77 % du scope est né en cours de sprint (33 issues sur 43), contre 55 % au Sprint 5. Le sprint a duré six semaines pour un timebox de deux, et se clÎt à 36 issues sur 43, les 7 restantes partant en Sprint 7.


Bilan des actions de la rétrospective Sprint 5

On rend compte des 3 actions que la rétro du Sprint 5 s'était engagée à mener. Une rétro dont personne ne vérifie les actions est un rituel vide.

Action Sprint 5 Verdict Détail
resource_group sur les jobs infra start/stop ⚠ Fait sur le papier, sans effet prouvĂ© LivrĂ© et mergĂ© le 2026-07-25 (#132). Mais le critĂšre de vĂ©rification annoncĂ©, deux pipelines infra qui se sĂ©rialisent, n'a jamais Ă©tĂ© exercĂ© en live. Pire, le diagnostic du 2026-08-16 a montrĂ© que le schedule de teardown du soir Ă©choue Ă  zĂ©ro job depuis au moins le 06/08 et ne dĂ©truit donc rien. Le garde-fou existe, la protection non. Repart en #174.
Cadrer le multi-environnements par un ADR stratĂ©gie AVANT tout code ✅ Fait ADR 029 livrĂ© (#133), 23 Ko, qui a effectivement tenu le sprint : isolation par namespace, promotion overlay-driven, rĂŽle de main, une seule instance RDS multi-bases. Aucune de ces quatre dĂ©cisions n'a Ă©tĂ© rouverte ensuite.
Alerter sur les pannes silencieuses (PrometheusRule metrics.k8s.io Unavailable) ❌ Non fait #141 n'a pas Ă©tĂ© ouverte une seule fois du sprint. DeuxiĂšme report consĂ©cutif. Elle repart en Sprint 7, et le sprint qui vient de s'Ă©couler a donnĂ© trois nouveaux exemples de panne silencieuse (mĂ©triques perdues, plafond d'autoscaling, image expirĂ©e du registre).

Stories livrées

36 issues fermĂ©es sur 43, portĂ©es par 73 merge requests mergĂ©es (!242 → !316).

Socle multi-environnements

Issue Livré
#133 ADR 029, stratégie multi-environnements
#134 Overlays Kustomize dev/staging/prod + 2 ApplicationSet
#136 ResourceQuota, LimitRange, RBAC et Pod Security Admission par environnement
#137 Une base de données par environnement, trois jeux de droits cloisonnés
#138 Sous-domaines DNS et secrets AWS Secrets Manager par environnement, IRSA scopé
#139 Write-back GitOps reciblé sur dev seul, promotion par merge request
#144 Script promote.sh et page pédagogique sur la promotion multi-env
#151 Correction de promote.sh, qui reformatait les overlays Ă  chaque promotion

Sécurité

Issue Livré
#146 SEC-006 : dev et staging étaient exposés publiquement en clair et branchés sur la base de production
#147 SEC-007 : aucune redirection HTTP vers HTTPS, identifiants transmis en clair, production comprise
#135 NetworkPolicy inter-environnements, default-deny puis autorisation intra-env. Isolation prouvée à trois niveaux
#156 L'URL de l'API n'est plus figée dans l'image du frontend : les trois environnements tapaient la production

Capacité et comportement sous charge

Issue Livré
#158 Le plafond réel de l'autoscaling était 3 replicas, pas les 5 affichés
#164 Le HPA sur la mémoire interdisait tout scale-down, effet cliquet
#149 Le quota de production saturait pendant un rollout Ă  pleine charge
#162 Sous charge, la liveness probe redémarrait les pods de production
#169 INC-066 : la readiness expire sous throttling CPU, Envoy sert des 503
#172 INC-067 : le keep-alive d'uvicorn plus court que le pool d'Envoy, un 503 sur 5 700
#148 cilium-envoy, plan de données L7, tournait en BestEffort et serait évincé le premier

ChaĂźne de livraison et registre

Issue Livré
#150 INC-062 et INC-065 : la rétention ECR expirait l'image servie par la production
#157 Le pĂ©rimĂštre des pipelines : un merge documentaire reconstruisait l'image. 17 jobs et ~8 min → 5 jobs et 2 min 24
#161 Backend déplacé sous backend/, le contexte de build ne contient plus que de l'applicatif (ADR 030)
#176 Sources pip-compile restées à la racine aprÚs #161
#173 Le chart metrics-server n'était pas épinglé, sa version changeait à chaque montage
#168 Aucun contrÎle terraform fmt en CI, un bloc mal aligné vivait dans le dépÎt
#132 resource_group sur les jobs infra start/stop

Observabilité

Issue Livré
#152 INC-063 : plus aucune métrique de l'API collectée depuis le passage au multi-env
#153 Le dashboard RED agrégeait les trois environnements sans les distinguer

Documentation et process

Issue Livré
#166 Radiateur d'information : page d'état du projet générée depuis l'API
#170 Rien ne rappelait le mot-clé Closes #N à l'ouverture d'une MR, corrigé par un template
#171 Gabarit, sommaire et identité visuelle pour les pages comprendre/
#167 La section 2 du runbook validait l'autoscaling par le mauvais chemin
#175 Le CLAUDE.md du dépÎt affirmait que le schedule du soir lançait registry-scan
#177 Page expliquant la refonte du périmÚtre de pipeline
#142, #143 Nettoyage des sauvegardes résiduelles, CLAUDE.md public à la racine

Stories non livrées, reportées en Sprint 7

Issue Pourquoi
#140 Tests E2E API et frontend. Issue du cadrage initial. Porte le gate de production dur, donc structurante
#141 Blackbox Exporter et alerte APIService Unavailable. Issue du cadrage initial, deuxiĂšme report
#163 Karpenter. N'était plus bloqué depuis la levée du cliquet HPA le 12/08, mais n'a pas trouvé de place
#165 Dimensionnement du runner : 2 vCPU pour un config.toml qui en promet 4
#174 Cadrage du garde-fou de teardown, non tranché : détruire ou seulement prévenir ?
#178 Couverture de sécurité imaginaire : dependency_scanning n'apparaßt dans aucun pipeline
#179 Découpage du .gitlab-ci.yml, 819 lignes et 12 ancres YAML utilisées 35 fois

Aucune de ces 7 issues n'est en priority::high. Deux d'entre elles, #140 et #141, viennent pourtant du cadrage initial : ce sont les seules des 10 issues de départ à ne pas avoir été livrées.


Vélocité

Baseline Sprint 5 = 20 Ă©lĂ©ments livrĂ©s. Sprint 6 = 36 Ă©lĂ©ments, portĂ©s par 73 merge requests (!242 → !316).

Type Nb
type::infra 10
type::docs 9
type::bug 5
type::ci-cd 5
type::security 4
type::fix 2
type::feature 1
Total 36

Scope ajouté en cours de sprint : 33 issues sur 43, soit 77 %. Le cadrage du 2026-07-07 comptait 10 issues (#132 à #141). Tout le reste est né pendant le sprint, en trois vagues nettes : le cutover multi-env de fin juillet (11 issues), la campagne de charge du 11 au 12 août (9 issues), et la journée du 16 août consacrée au coût et au périmÚtre des pipelines (8 issues).

Lecture honnĂȘte de ce chiffre. Au Sprint 5, les 55 % d'ajout Ă©taient revendiquĂ©s comme une force : des findings de validation live tracĂ©s et livrĂ©s le jour mĂȘme. À 77 % sur six semaines, l'interprĂ©tation change. Le cadrage initial de 10 issues sous-estimait le sujet d'un facteur quatre, et un sprint qui absorbe quatre fois son scope n'est plus un sprint time-boxĂ©, c'est une file d'attente. C'est le principal enseignement de pilotage de ce sprint.


Incidents majeurs et résolutions

Le sprint a capitalisé 9 incidents : 2 de sécurité (SEC-006, SEC-007) et 7 techniques (INC-062 à INC-068). Détail complet dans sprint6.md.

Les deux incidents de sécurité

SEC-006 et SEC-007 partagent la mĂȘme nature : la protection Ă©tait Ă©crite quelque part, mais rien ne l'appliquait. Dev et staging exposĂ©s publiquement en clair et branchĂ©s sur la base de production, alors qu'une consigne Ă©crite disait le contraire. Aucune redirection HTTP vers HTTPS, donc des identifiants transmis en clair sur la production elle-mĂȘme.

Leçon commune, et sans doute la plus importante du sprint : une rÚgle écrite dans une documentation n'est pas un contrÎle. Seul un test négatif, tenter l'action interdite et vérifier qu'elle échoue, distingue les deux.

Les incidents techniques

Incident Sujet Leçon retenue
INC-062, INC-065 La rĂ©tention ECR a supprimĂ© l'image servie par staging puis par la production Élargir la fenĂȘtre de 5 Ă  30 puis 100 ne fait que retarder l'Ă©chĂ©ance. Il faut marquer ce qui est en service. Le premier correctif portait lui-mĂȘme le dĂ©faut symĂ©trique
INC-063 Plus aucune mĂ©trique de l'API aprĂšs le passage au multi-env Un namespaceSelector figĂ© sur un namespace devenu vide. Une supervision muette ne se signale pas elle-mĂȘme
INC-064 trivy-image-scan rouge sur deux CVE d'outillage jamais installé Un scanner rapporte ce qu'il sait lire, pas ce qui est installé
INC-066 Sous charge, la readiness expire et Envoy sert des 503 Le throttling CPU retire la capacité exactement au pire moment
INC-067 Un 503 sur 5 700 servi aux clients, keep-alive uvicorn plus court que le pool Envoy Deux délais qui ne se parlent pas finissent par se croiser. Corriger la premiÚre panne en a révélé une seconde, qu'elle masquait
INC-068 Une CVE systĂšme bloque tous les builds Épingler par digest fige aussi les failles : un rebuild ne rĂ©cupĂšre aucun correctif amont

Décisions d'architecture (ADR)

ADR Décision
029 Stratégie multi-environnements : isolation par namespace et overlays Kustomize sur un cluster unique, promotion par merge request, main conservé en archive, une seule instance RDS portant trois bases
030 Layout du dépÎt et contexte de build : backend déplacé sous backend/, le contexte de build ne contient plus que de l'applicatif

L'ADR 029 est le document structurant du sprint. Ses quatre dĂ©cisions ont tenu six semaines sans ĂȘtre rouvertes, ce qui valide l'action de la rĂ©tro Sprint 5 : cadrer par un ADR avant de coder.


Rétrospective

Ce qui a bien fonctionné

  • L'ADR avant le code. Quatre dĂ©cisions posĂ©es en dĂ©but de sprint, aucune rouverte ensuite. Le contraste avec les sprints prĂ©cĂ©dents est net.
  • Les campagnes de charge comme mĂ©thode. Les 503 n'ont pas Ă©tĂ© trouvĂ©s par lecture de code mais par tir de charge mesurĂ©, puis sĂ©parĂ©s en deux causes distinctes grĂące aux response_flags d'Envoy. Chiffres Ă  l'appui : 87 578 requĂȘtes Ă  729 req/s, zĂ©ro 503 aprĂšs correctif.
  • Le coĂ»t de la CI traitĂ© comme un sujet d'ingĂ©nierie. #157 divise par plus de trois le coĂ»t d'un merge documentaire, avec un job pipeline-scope qui garantit qu'aucun pipeline ne part Ă  vide.
  • Chaque finding tracĂ© le jour mĂȘme. 33 issues nĂ©es en cours de sprint, toutes avec leur milestone. Le scope a bougĂ©, la traçabilitĂ© non.
  • L'outillage d'observabilitĂ© enfin utilisĂ© pour diagnostiquer. Les logs d'accĂšs Envoy introuvables par kubectl logs ont Ă©tĂ© retrouvĂ©s en une requĂȘte LogQL dans Loki, dĂ©ployĂ© depuis le Sprint 4.

Ce qui a bloqué ou coûté du temps

  • Le timebox n'a pas Ă©tĂ© tenu, et de loin. Six semaines pour deux annoncĂ©es. Aucun point d'arrĂȘt intermĂ©diaire n'a Ă©tĂ© posĂ© pour constater la dĂ©rive pendant qu'elle se produisait.
  • Le cadrage a sous-estimĂ© le sujet d'un facteur quatre. 10 issues prĂ©vues, 43 rĂ©elles. Le multi-environnements n'Ă©tait pas une story, c'Ă©tait un chantier.
  • Trois dĂ©fauts dĂ©couverts aprĂšs plusieurs jours ou semaines d'existence : les mĂ©triques perdues, le plafond d'autoscaling Ă  3, les environnements exposĂ©s en clair. Aucun ne s'est signalĂ© de lui-mĂȘme, ce qui renvoie exactement Ă  l'action #141 reportĂ©e deux fois.
  • Les correctifs qui portaient leur propre dĂ©faut. La rĂ©tention ECR a demandĂ© deux passes, la seconde ayant introduit un dĂ©faut symĂ©trique de la premiĂšre.
  • Les indicateurs verts qui ne prouvaient rien. Quatre formes distinctes ont Ă©tĂ© identifiĂ©es et documentĂ©es pendant le sprint, dont un pipeline vide qui sort failed sans erreur et des jobs de sĂ©curitĂ© qui ne tournent jamais sur une merge request.

3 actions concrĂštes pour Sprint 7

  1. Clore le Sprint 7 Ă  sa date, avec un point d'Ă©tape Ă  mi-parcours. VĂ©rifiable : une revue de mi-sprint datĂ©e, et une clĂŽture qui sort le reliquat au lieu de prolonger la fenĂȘtre. C'est la rĂ©ponse directe aux six semaines pour deux.

  2. Solder les gardes-fous qui n'en sont pas : #174, le teardown du soir qui ne détruit rien, et #178, dependency_scanning absent de tous les pipelines. Vérifiable par test négatif dans les deux cas : provoquer la situation que le garde-fou est censé attraper, et constater qu'il attrape. Un vert ne suffit pas.

  3. Livrer #141, l'alerte sur les pannes silencieuses. TroisiÚme inscription. Vérifiable : couper volontairement le composant surveillé et recevoir l'alerte. Le sprint qui s'achÚve a fourni trois exemples de plus, la dette n'est plus théorique.


Validation end-to-end

DerniÚre validation complÚte en conditions réelles : 2026-08-16, avant le teardown du cluster.

  • Isolation inter-environnements prouvĂ©e Ă  trois niveaux (#135) : rĂ©seau par NetworkPolicy, ressources par quota, identitĂ© cloud par rĂŽle IRSA scopĂ©
  • Trois bases de donnĂ©es avec droits cloisonnĂ©s, un seul Gateway et donc un seul NLB pour les trois environnements
  • Charge validĂ©e : 87 578 requĂȘtes en 120 s Ă  729,2 req/s, zĂ©ro 503, confirmĂ© par l'absence de response_flags: UC dans Loki sur la route fastapi
  • RĂ©tention ECR par environnement validĂ©e aprĂšs deux passes, marquage inuse- de ce qui est en service
  • CoĂ»t d'un merge documentaire : 5 jobs et 2 min 24, contre 17 jobs et environ 8 min avant #157

Restant à vérifier au prochain montage from-scratch (#148, #173) : cilium-envoy et cilium-operator en Burstable, Hubble en BestEffort, et metrics-server épinglé en 3.13.1 visible dans helm list -n kube-system. Ces trois points sont livrés dans le dépÎt mais n'ont pas encore été observés sur un cluster monté de zéro.

Documentation publique : doc.devopsyouss.com


Sprint 6 clÎturé le 2026-08-17. Aucune release vers main : la promotion se fait par overlay, main reste une archive (#57). Les 7 issues restantes sont reportées en Sprint 7.