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_flagsd'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-scopequi 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 logsont Ă©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
failedsans erreur et des jobs de sécurité qui ne tournent jamais sur une merge request.
3 actions concrĂštes pour Sprint 7¶
-
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.
-
Solder les gardes-fous qui n'en sont pas : #174, le teardown du soir qui ne détruit rien, et #178,
dependency_scanningabsent 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. -
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: UCdans Loki sur la routefastapi - 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.