- ProblèmeConcevoir un pipeline de livraison de production avec isolation, observabilité et sécurité.
- RôleSimulation de stage en platform engineering
- StackGitHub Actions (CI) • Docker + GHCR • FastAPI • Kubernetes
- FocusCI/CD • GitOps • Kubernetes
- RésultatsCe projet démontre une boucle de livraison de type production avec auditabilité, isolation par locataire et signaux runtime observables.
Problème
Risque de release : les déploiements manuels sont fragiles, incohérents et difficiles à rollbacker sous pression. Manque de traçabilité : il est difficile de prouver quelle version tourne où et pourquoi. Dérive (drift) : l’état du cluster s’éloigne de Git, créant des incidents « ça marche chez moi » impossibles à reproduire. Risque multi-tenant : effets de voisin bruyant et blast radius élargi sans frontières d’isolation claires. Gap d’observabilité : sans métriques/logs reliés aux déploiements, le debugging reste lent et réactif. Ligne de base sécurité : les secrets ne doivent jamais finir dans Git et l’accès doit rester au moindre privilège avec auditabilité.
Pourquoi c’est critique : releases plus rapides et plus sûres, MTTR réduit, blast radius contrôlé par locataire, et préparation audit/compliance.
- Livraisons reproductibles : commit → image testée → PR GitOps → réconciliation Argo CD
- Exécution traçable : dashboards + logs reliés au tag d’image réellement déployé
- Isolation multi-locataire : values par tenant, namespaces et frontières RBAC
Contexte
Architecture en bref — Un push développeur déclenche GitHub Actions ; le CI exécute ruff/pytest, build l’image FastAPI et la pousse sur GHCR. Une PR GitOps met à jour les valeurs par locataire ; Argo CD réconcilie l’état désiré dans le cluster. Les métriques/logs remontent vers Prometheus/Loki et sont visualisées dans Grafana.
Cette étude de cas se concentre sur la chaîne de livraison et les contrôles opérationnels ; l’application est volontairement minimale pour valider le pipeline et le comportement plateforme.
Note d’implémentation : le système tourne sur un cluster k3d local ; étapes cloud-ready : migration EKS, HPA/VPA pour l’autoscaling, et options d’observabilité managée (CloudWatch ou Amazon Managed Prometheus/Grafana).
- Workloads par locataire
kubectl get pods -n tenant-a && kubectl get pods -n tenant-b - Sync/health Argo CD
kubectl -n argocd get applications - API + /metrics (tenant-a)
kubectl -n tenant-a port-forward svc/demo-api 8080:8000 curl http://localhost:8080/metrics - Cibles Prometheus
kubectl -n observability port-forward svc/prometheus 9090:9090 curl http://localhost:9090/api/v1/targets - Loki + Promtail
kubectl -n observability get svc loki kubectl -n observability get pods -l app=promtail - Liste des datasources Grafana
kubectl -n observability port-forward svc/grafana 3000:3000 curl -u <user>:<pass> http://localhost:3000/api/datasources
GitOps CI/CD multi‑tenant pour SaaS Kubernetes
Cette étude de cas modélise une delivery SaaS où chaque tenant est isolé par namespace et déployé via PR GitOps.
L’état désiré dans Git rend les releases auditables et les rollbacks déterministes.
Argo CD + Helm avec observabilité Prometheus/Grafana/Loki
Argo CD réconcilie les releases Helm, tandis que Prometheus, Grafana et Loki exposent métriques et logs pour le triage.
Le pipeline reste observable et explicable de bout en bout.
Architecture
- Analyse du pipeline CI (GitHub Actions)
- Déclenché sur push main et sur PR ; le job test exécute `ruff check .` (règles E/F/I uniquement, pas d’auto-format) et `pytest -q` (découvre les tests et échoue en cas de code de sortie non nul).
- Ruff applique le lint ; Black formate (optionnel), donc les changements de format restent explicites.
- Le job build crée l’image FastAPI, tague `sha-<short>` et `latest`, puis pousse sur GHCR (registry de conteneurs, pas un stockage de fichiers).
- Les tags SHA sont immuables pour rollback ; `latest` sert seulement aux smoke checks.
- Une PR GitOps met à jour `image.tag` dans les values (ex. `gitops/tenants/*-values.yaml`) pour l’auditabilité.
- GitOps + Argo CD (modèle CD)
- L’état désiré vit dans Git ; Argo CD réconcilie le cluster et expose sync/health.
- Par défaut, c’est de la Continuous Delivery : validation humaine de la PR GitOps.
- Cela devient Continuous Deployment si la fusion des PR est automatisée ou si Argo suit une branche auto-mise à jour.
- Rollback = revert du commit Git vers un tag précédent, puis Argo CD resynchronise.
- Multi-tenance & modèle d’isolation
- Un chart Helm, des values par locataire, et des releases par namespace (`tenant-a`, `tenant-b`).
- Les namespaces offrent scoping des ressources, frontières RBAC et point d’accroche pour NetworkPolicies.
- Pas d’isolation "hard" : sans policies réseau ou séparation de nœuds, les locataires partagent le control plane.
- Les locataires représentent des clients ; on ne crée pas un namespace par utilisateur final.
- Observabilité (Prometheus + Grafana + Loki)
- Prometheus scrappe `/metrics` via Service/PodMonitor ou scrape config ; signaux clés : latence, taux d’erreur, saturation.
- Grafana dashboards + alerting ; provisioning des datasources pour éviter le conflit de "default datasource".
- Promtail expédie les logs pods vers Loki ; exemple LogQL : `{namespace="tenant-a"} |= "error"`.
- Les commandes de vérification sont listées sous Architecture en bref.
Sécurité / Modèle de menace
- Les secrets ne vivent jamais dans Git ; le CI utilise le GITHUB_TOKEN éphémère et scoped au repo.
- L’auth registry passe par docker/login-action et ce token — pas de credentials longue durée.
- Les credentials runtime vivent dans Kubernetes Secrets (Argo CD, Grafana, app env) et sont montés au déploiement.
- Le secret admin Argo CD est généré à l’installation, stocké en Secret K8s, et peut être rotaté.
- Le RBAC applique le moindre privilège entre namespaces et service accounts.
| Contrôle | Outil | Statut |
|---|---|---|
| Lint + tests unitaires | ruff (E/F/I) + pytest -q | Implemented |
| SAST | CodeQL | Extension |
| Scan dépendances | Dependabot + pip-audit | Extension |
| Scan secrets | gitleaks | Extension |
| Scan conteneurs | Trivy/Grype | Extension |
| Scan IaC | Checkov | Extension |
| DAST | OWASP ZAP baseline | Extension |
Compromis & retours d’expérience
Scaling (HPA/VPA) & fiabilité — HPA ajoute des réplicas via CPU/mémoire/métriques custom ; VPA ajuste requests/limits. Ces mécanismes ne sont volontairement pas activés dans cette démo pour garder la pression ressources visible ; en production j’ajouterais Metrics Server + Prometheus Adapter et un Cluster Autoscaler cloud.
Design de déploiement cloud (AWS) — Control plane → EKS, workers → managed node groups (ou Fargate), ingress → contrôleur ALB/NLB, registry → GHCR ou ECR, secrets → AWS Secrets Manager + External Secrets Operator, observabilité → CloudWatch ou Amazon Managed Prometheus/Grafana. Coûts principaux : fee EKS, nœuds EC2, EBS, NAT gateway, egress, rétention Loki ; leviers : right-sizing, autoscaling, spot, sampling et rétention des logs.
Compromis & limites — Les PR GitOps ralentissent mais apportent l’auditabilité ; l’isolation par namespace réduit le blast radius sans offrir une isolation hard ; le stack observabilité OSS demande du tuning ; plus de composants = plus d’ops.
Extensions que je peux implémenter ensuite — merge automatique des PR avec policy gates, secrets externes (Vault/ASM), admission control (OPA/Gatekeeper) et isolation multi-cluster pour les locataires à risque.
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: demo-api
namespace: tenant-a
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: demo-api
minReplicas: 2
maxReplicas: 6
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
name: demo-api
namespace: tenant-a
spec:
targetRef:
apiVersion: "apps/v1"
kind: Deployment
name: demo-api
updatePolicy:
updateMode: "Auto"Résultats
Ce projet démontre une boucle de livraison de type production avec auditabilité, isolation par locataire et signaux runtime observables. Il valide la préparation cloud et les fondamentaux de platform engineering : CI, réconciliation GitOps, déploiement multi-locataire et télémétrie utilisable en incident.
- Montrer les apps Argo CD Synced/Healthy
kubectl -n argocd get applications - Prouver la séparation des locataires
kubectl get pods -n tenant-a && kubectl get pods -n tenant-b - Tester /metrics pour un signal live
kubectl -n tenant-a port-forward svc/demo-api 8080:8000 curl http://localhost:8080/metrics - Vérification Grafana + Loki rapide
kubectl -n observability port-forward svc/grafana 3000:3000 # Explore > Loki: {namespace="tenant-a"} |= "error"
Stack technique
FAQ
C’est du continuous deployment ou delivery ?
Par défaut c’est du continuous delivery car les PR GitOps exigent une validation humaine. Cela devient du deployment si la fusion est automatisée.
Pourquoi des namespaces plutôt que des clusters séparés ?
Les namespaces réduisent coût et overhead tout en offrant des frontières RBAC et un blast radius réduit. Des politiques réseau ou des clusters dédiés peuvent renforcer l’isolation.
Comment vérifier un déploiement ?
Valider le sync/health Argo CD, vérifier les pods par namespace et confirmer /metrics + logs dans Grafana/Loki.