Architecture de bout en bout
Ce guide raconte l'architecture complète du projet : comment le code arrive en prod, comment une requête atteint l'app, comment les secrets circulent, comment on observe. Pour chaque brique : son rôle, et surtout le pourquoi du choix (c'est le « pourquoi » qui se défend en entretien, pas la liste des outils).
Le schéma d'ensemble : Architecture DevSecOps EKS.
ADR liés : GitOps ArgoCD, Exposition ownership, NLB vs CLB, ESO + IRSA, Observabilité.
La clé : deux flux qui se croisent sur le schéma
Le piège d'un schéma d'archi, c'est de vouloir tout lire d'un coup. En réalité, il y a deux récits distincts qui ne se rencontrent qu'au niveau du pod :
- Le flux de livraison : comment ton code passe d'un commit à un pod qui tourne (CI/CD puis GitOps).
- Le flux de trafic : comment la requête d'un utilisateur atteint ton app (DNS → load balancer → Gateway → pod).
En entretien, commence toujours par cette séparation. Elle montre une vision d'architecte (des flux, des responsabilités) plutôt qu'un empilement d'outils.
LIVRAISON : commit ─► CI ─► ECR + Git ─► ArgoCD ─► cluster
│
pod FastAPI
▲
TRAFIC : utilisateur ─► DNS ─► NLB ─► Envoy Gateway ─► Service ─┘
Récit 1 : comment le code arrive en prod (livraison)
commit ─► GitLab CI ─► build (kaniko) ─► scan (Trivy) ─► promote ECR (par digest)
│
write-back du tag dans Git (kustomization.yaml)
│
ArgoCD voit le commit ─► reconcile ─► cluster
Les concepts à maîtriser
| Concept | Ce que c'est | Le pourquoi |
|---|---|---|
| Promote par digest | l'image est identifiée par son SHA256, pas un tag mutable | l'image scannée est exactement l'image déployée ; un tag comme latest peut bouger sous tes pieds (cf. INC-050) |
| GitOps pull-based (#72) | la CI n'applique plus rien sur le cluster ; elle écrit le tag dans Git, ArgoCD tire (pull) depuis Git | Git = source de vérité unique ; pas de credentials cluster dans la CI ; reconciliation continue (anti-dérive) |
| App-of-apps | une Application racine ArgoCD découvre les autres Applications dans un dossier | pour ajouter une brique, on dépose un fichier ; ArgoCD le déploie seul |
| Découplage CI / ArgoCD | ArgoCD ne regarde ni le pipeline ni les MR, seulement la branche develop |
un fix peut partir en live par simple merge, même pipeline app à l'arrêt (vécu : fix Grafana #88) |
Question d'entretien classique : « comment garantis-tu que ce qui tourne en prod est ce que tu as testé ? » → promote par digest + Git comme source de vérité. La réponse tient en deux maillons.
Voir le détail dans Comprendre ArgoCD.
Récit 2 : comment une requête atteint l'app (trafic)
Utilisateur
│ https://api.devopsyouss.com
▼
Cloudflare DNS ─► NLB ─► Envoy Gateway ─► HTTPRoute ─► Service (ClusterIP) ─► Pod FastAPI
(TLS terminé ici : cert wildcard)
Les concepts à maîtriser
| Brique | Rôle | Le pourquoi du choix |
|---|---|---|
| Gateway API (pas Ingress) | Gateway = point d'entrée + listeners 80/443 ; HTTPRoute = quelle URL va vers quel service |
standard plus expressif et portable que l'Ingress historique ; sépare le « point d'entrée » (plateforme) de « la route » (app), cf. ADR 010 |
| NLB (#70) | load balancer L4 devant Envoy | Envoy fait déjà tout le L7 (routing, TLS) ; un ALB serait redondant, le CLB est déprécié AWS |
| cert-manager + wildcard (#76) | certificat *.devopsyouss.com (Let's Encrypt, challenge DNS-01 Cloudflare) |
un seul cert couvre api + grafana + doc et tout futur sous-domaine ; DNS-01 obligatoire pour un wildcard |
| ExternalDNS (#66) | crée le CNAME automatiquement depuis le hostname de la HTTPRoute |
zéro DNS à la main ; la route est la source de vérité du nom |
Le Gateway est un ingress partagé (#76) :
allowedRoutes: from: Allautorise des routes d'autres namespaces (Grafana en nsmonitoring) à s'y attacher. Un seul point d'entrée, plusieurs apps.
Voir La démarche d'exposition.
Récit 3 : comment l'app obtient ses secrets (rien en clair dans Git)
AWS Secrets Manager ─► External Secrets Operator (auth IRSA) ─► Secret K8s ─► Pod
Les concepts à maîtriser
- ESO (External Secrets Operator) : va chercher le secret dans AWS Secrets Manager et le matérialise en Secret Kubernetes. L'app lit un Secret K8s normal, jamais un secret versionné dans Git.
- IRSA (IAM Roles for Service Accounts) : le ServiceAccount du contrôleur ESO assume un rôle IAM via le provider OIDC du cluster. Aucune clé d'accès AWS n'est stockée nulle part. C'est la réponse propre à « comment t'authentifies-tu à AWS depuis un pod ? ».
- Moindre privilège : le rôle IAM est restreint aux ARN précis des secrets utilisés (base de données, Grafana, webhook Slack), pas un accès large.
Même pattern pour tous les secrets du projet : mot de passe DB, mot de passe admin Grafana (#76), webhook Slack de l'alerting (#77). Une seule mécanique à expliquer.
Voir ESO + IRSA.
Récit 4 : comment on observe (#74 / #75 / #77)
Pod FastAPI ─/metrics─► Prometheus ─┐
│ ├─► Grafana (lit les deux) ─► toi
└─stdout─► Alloy ─► Loki ────┘
Prometheus ─► PrometheusRule ─► Alertmanager ─► Slack
Les concepts à maîtriser
| Pilier | Comment ça circule | Le pourquoi |
|---|---|---|
| Métriques | Prometheus va chercher (pull) /metrics en interne via le ClusterIP |
/metrics n'est pas public (#81, ADR 018) : il fuiterait routes/latences ; le scrape est interne |
| Logs | Alloy (DaemonSet) ramasse les logs des pods et les envoie (push) à Loki | Alloy remplace Promtail (déprécié) ; labels low-cardinality pour ne pas exploser la mémoire |
| Visualisation | Grafana lit Prometheus + Loki via des datasources | la vitrine, c'est Grafana, pas /metrics brut |
| Alerting | une PrometheusRule passe Pending puis Firing, Alertmanager route vers Slack |
Alertmanager groupe / route / inhibe ; une alerte se déclenche dans Prometheus, Alertmanager décide quoi en faire |
Le sens des flèches est un vrai concept : Prometheus tire les métriques (pull), Alloy pousse les logs (push). C'est une différence de conception entre métriques et logs, pas un détail.
Voir Observabilité et Alerting.
Transverse : l'infra (Terraform) et la sécurité
Terraform : persistent vs ephemeral
| Couche | Contient | Durée de vie |
|---|---|---|
| persistent | RDS PostgreSQL, ECR, secrets (Secrets Manager) | dure dans le temps |
| ephemeral | le cluster EKS et son réseau | monté/détruit chaque jour (coût) |
C'est pour ça que « l'infra est éteinte » n'empêche pas de livrer : on écrit la recette dans Git, ArgoCD l'applique au prochain démarrage du cluster. Le séparé persistent/ephemeral est un choix de coût (un cluster allumé H24 coûte cher, une base et un registre, non).
La sécurité en couches (defense in depth)
- Réseau : NetworkPolicy
default-deny+ règles ciblées (#55), enforced par le VPC CNI. - Namespace : Pod Security Admission en mode
restricted. - Image : multi-stage Python 3.12-slim, scannée Trivy (0 HIGH), pinnée par digest (ADR 011).
- IaC :
tfsecsur le Terraform (0 HIGH en CI). - Accès : RBAC least-privilege pour le user CI (il ne peut pas patcher un objet cluster-scoped), IRSA scopé aux bons ARN.
« Defense in depth » : aucune couche n'est censée tout arrêter seule. Si une cède, la suivante limite la casse. C'est l'angle à donner, pas une liste d'outils.
Refaire le schéma (cahier des charges du drawio)
Quand tu reprendras le drawio (docs/architecture.drawio, encore au snapshot
Sprint 3), voici ce qu'il doit représenter pour être à jour. À cocher :
Flux de livraison (à corriger) :
- [ ] Retirer le
kubectl apply -k k8s/base/(push-based, périmé depuis #72). - [ ] Ajouter le nœud ArgoCD dans le cluster.
- [ ] Tracer : CI ─(
write-back tag)─► Git ─(watch/sync)─► ArgoCD ─(reconcile)─► pod. Plus aucune flèche CI ─► cluster directe. - [ ] Garder : build (kaniko) ─► scan (Trivy) ─► push image vers ECR.
Observabilité (à ajouter en nœuds réels, plus en encart « planned ») :
- [ ] Prometheus ◄─(
scrape /metricsinterne)─ FastAPI. - [ ] Alloy (DaemonSet) ◄─ stdout FastAPI, ─(
push)─► Loki. - [ ] Grafana ─(
datasource)─► Prometheus + Loki, exposé via le Gateway. - [ ] (optionnel) Alertmanager ─► Slack.
Trafic (déjà globalement bon, à vérifier) :
- [ ] NLB (pas Classic ELB) devant Envoy Gateway.
- [ ] Cert wildcard
*.devopsyouss.comau listener HTTPS.
Forme :
- [ ] Titre « DevSecOps EKS — Sprint 4 ».
- [ ] Export PNG via la skill
diagram-exportune fois le.drawioà jour.
Le diagram-as-code (
docs/diagrams/architecture.py) est déjà à jour avec tout ça : tu peux t'en servir de référence visuelle pour repositionner les nœuds du drawio.