🏗️ Projet : Migration K8s "Orion"
Cas d'étude : Migration d'un Monolithe E-commerce vers des Microservices sur AWS EKS.
Contexte & Objectifs
Le "Pourquoi". (Monolithe sur VM -> Microservices sur K8s). Scalabilité, HA, Vélocité.
Monolithe MicroservicesArchitecture Cible
AWS EKS (Managed K8s), VPC (Réseau), Nœuds (ASG), ALB Ingress Controller.
AWS EKS VPCDiagramme (Avant/Après)
VM (Monolithe) vs K8s (Deployments, Services, Ingress).
Diagramme Avant/AprèsObjets K8s Clés
Deployments (Stateless), StatefulSets (DB), Services (Interne), Ingress (Externe).
Stockage (Stateful)
StorageClass (aws-ebs-gp3), PV/PVC (RWO) pour Postgres/Redis.
Sécurité (DevSecOps)
RBAC (Least Privilege), NetworkPolicy (Isolation), Vault (Secrets).
Observabilité (Monitoring)
Stack Prometheus (Scraping) + Grafana (Dashboards). kube-state-metrics.
CI/CD (GitOps)
CI (GitLab CI) -> Build. CD (ArgoCD) -> Deploy (Pull).
Résultats & Métriques
Uptime (99.99%), Temps de déploiement (< 5min), Scalabilité (HPA).
Résultats KPIsSituation Initiale (Le Problème)
- Architecture : Monolithe E-commerce (Python/Django) tournant sur 2 grosses VMs (EC2) derrière un Load Balancer (ALB).
- Base de données : Une instance RDS (Postgres) unique.
- Déploiement : Manuel (via SSH/Ansible), 1 fois par semaine (avec 15min de downtime).
- Points de douleur :
- Scalabilité impossible (scaler tout le monolithe pour un pic sur le "Panier").
- Faible résilience (une panne de l'app = tout tombe).
- Déploiements lents et risqués ("Big Bang").
Objectifs (La Solution)
Migrer l'application vers une architecture Microservices (API-Users, API-Produits, API-Payment, Frontend-React) orchestrée par Kubernetes (EKS).
- Scalabilité : Scaler chaque microservice indépendamment (ex:
HPAsurapi-produitspendant le Black Friday). - Haute Disponibilité (HA) : Tolérance aux pannes (Rolling Updates, auto-réparation des Pods).
- Vélocité (CI/CD) : Permettre aux équipes de déployer leur service (ex:
api-payment) plusieurs fois par jour, sans impacter les autres (via GitOps).
Composants d'Infrastructure (AWS)
| Composant | Technologie AWS | Rôle |
|---|---|---|
| Cluster (Control Plane) | AWS EKS (Elastic Kubernetes Service) | Control Plane managé par AWS (API Server, etcd...). |
| Nœuds (Workers) | EC2 (ASG + Managed Node Groups) | VMs (ex: m5.xlarge) où tournent les Pods (kubelet). Géré par un Auto Scaling Group (ASG). |
| Réseau | VPC (Amazon VPC CNI) | Le CNI d'AWS, qui donne à chaque Pod une IP "réelle" du VPC (simplifie le routage). |
| Exposition (L7) | ALB (Application Load Balancer) | Provisionné automatiquement par l'AWS Load Balancer Controller (installé dans K8s) en réponse à un objet Ingress. |
| Images Docker | ECR (Elastic Container Registry) | Registre Docker privé. |
Le cluster a été provisionné via Terraform et l'EKS Blueprints module pour standardiser les environnements (dev, staging, prod).
Avant (Monolithe sur VM)
(Internet)
|
▼
+-----------+
| AWS ALB |
+-----------+
|
▼
+-----------+ +-----------+
| VM 1 (EC2)| | VM 2 (EC2)|
| [Monolithe] | | [Monolithe] |
+-----------+ +-----------+
| |
+-------+-------+
|
▼
+-----------+
| RDS (Postgres)|
+-----------+
Après (Microservices sur EKS)
(Internet)
|
▼
+-----------------------+
| AWS ALB (Géré par K8s Ingress) |
+-----------------------+
|
▼ (Routage L7: /api/users, /api/payments, /)
+-------------------------------------------------------+
| Cluster EKS (Nodes) |
| |
| + (Svc: Ingress-Controller) + |
| |
| + (Svc: Frontend) + + (Svc: API-Users) + |
| | [Pod] [Pod] [Pod] | | [Pod] [Pod] | |
| +-------------------+ +----------------+ |
| |
| + (Svc: API-Payments) + + (Svc: StatefulSet-DB) + |
| | [Pod] [Pod] | | [Pod-DB (avec PV/EBS)]| |
| +---------------------+ +-----------------------+ |
+-------------------------------------------------------+
L'application "E-Shop" a été découpée en objets K8s (gérés via Helm/ArgoCD).
| Objet K8s | Rôle dans le Projet |
|---|---|
Namespace | Isolation (prod, staging, dev) + Isolation (monitoring, cicd). |
Deployment | Pour les microservices Stateless (Frontend, API-Users, API-Payments). Gère replicas et RollingUpdate. |
StatefulSet | Pour les bases de données Stateful (Postgres, Redis). Garantit une identité (pod-0) et un stockage (pvc-0) stables. |
Service (ClusterIP) | Réseau interne (DNS stable, ex: http://api-users.prod) pour la communication Pod <-> Pod. |
Ingress | Routage externe (L7). Expose le Service (frontend) sur eshop.com/ et Service (api-users) sur eshop.com/api/users. |
La gestion des données persistantes (DBs) est critique.
1. StorageClass (Le "Template" de Disque)
Nous avons défini un StorageClass (SC) pour le "Provisioning Dynamique" (automatique) des disques AWS EBS (Elastic Block Store).
apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: ebs-gp3-fast provisioner: ebs.csi.aws.com # (Le "driver" CSI d'AWS) volumeBindingMode: WaitForFirstConsumer # (Attend que le Pod soit schedulé) parameters: type: gp3 # (Type de SSD) fsType: ext4 reclaimPolicy: Retain # (Garde le disque si le PVC est supprimé)
2. StatefulSet + volumeClaimTemplates (La "Demande")
Le StatefulSet (pour Postgres) utilise ce SC pour créer automatiquement un PVC (et donc un PV/Disque) unique pour *chaque* réplique (pod-0 -> pvc-0, pod-1 -> pvc-1).
# (Extrait de postgres-statefulset.yaml)
spec:
serviceName: "postgres-svc"
replicas: 1
# (Template de PVC: K8s va créer "data-postgres-0")
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: [ "ReadWriteOnce" ] # (RWO)
storageClassName: "ebs-gp3-fast" # (Nom du SC)
resources:
requests:
storage: 50Gi # (Demande 50Go)
Mise en place d'une sécurité "Zero Trust" (zéro-confiance) à plusieurs niveaux.
| Composant | Mise en œuvre | Objectif |
|---|---|---|
| RBAC (Autorisation) | Roles (par Namespace) et RoleBindings. ServiceAccounts dédiés (non-default) pour chaque application. | (Moindre Privilège) L'API "Produits" (Pod) ne peut que "lire" (get) les ConfigMaps. L'API "Paiement" ne peut pas lister les Pods. |
| NetworkPolicy (Firewall) | Déploiement de Calico (CNI). Politiques "Deny All" par défaut sur le namespace prod. | (Isolation) Le "Frontend" peut parler à "API-Users". L'"API-Users" peut parler à "DB-Postgres". Le "Frontend" ne peut **PAS** parler à "DB-Postgres". |
| Secrets (Données sensibles) | External Secrets Operator (ESO). | Les secrets (DB_PASSWORD) sont stockés dans AWS Secrets Manager. ESO les synchronise (en lecture) dans des objets Secret K8s natifs (visibles uniquement par le Pod autorisé). |
Mise en place de la stack "Prometheus-Stack" (via Helm Chart) dans le namespace monitoring.
Diagramme (Stack Monitoring)
(K8s API) <--+
| |
(Kubelet) | (kube-state-metrics)
| |
▼ ▼
+--------------------------+
| Prometheus (Server) | (Modèle "Pull")
| (Scrape /metrics) | (Stocke les métriques)
| (Gère les alertes) |
+--------------------------+
| (Data Source)
▼
+--------------------------+
| Grafana (UI) | (Dashboards)
| (Interroge Prometheus) | (PromQL)
+--------------------------+
- Prometheus : "Scrape" (pull) automatiquement les endpoints
/metrics(cAdvisor, Kubelet, et nos Pods applicatifs (viaServiceMonitorCRD)). - Grafana : UI pour visualiser les Dashboards (ex: "Node Exporter Full" (CPU/Mem Nœuds), "Kube-State-Metrics" (Déploiements)).
- Alertmanager : Gère les alertes (définies dans Prometheus) vers Slack/PagerDuty.
- DataDog : (Partiel) L'Agent DataDog (DaemonSet) est aussi déployé pour la centralisation des Logs et Traces APM (que Prometheus ne gère pas nativement).
Nous avons implémenté une CI/CD basée sur GitOps (Modèle "Pull") via ArgoCD.
Diagramme du Workflow de Déploiement
(Développeur)
|
| 1. "git push" (sur le code de l'API)
▼
+------------------+
| GitLab (Repo Code) |
+------------------+
| (Webhook)
▼
+------------------+
| GitLab CI (Runner)| (Tourne dans K8s)
+------------------+
| 2. Build, Test, Push Image
▼
+------------------+
| ECR (Registre AWS) | (ex: api-users:1.2.1)
+------------------+
|
| 3. "git push" (Met à jour le tag
| de l'image dans le *Repo Config*)
▼
+------------------+
| GitHub (Repo Config)| (Contient les YAMLs/Helm K8s)
| (Source de Vérité) | (imageTag: 1.2.1)
+------------------+
|
| 4. "Pull" (ArgoCD détecte le changement)
▲
+------------------+
| Cluster EKS |
| +--------------+ |
| | ArgoCD | |
| +--------------+ |
| (5. `kubectl apply`)|
+------------------+
- CI (GitLab CI) : Rôle = Tester le code, builder l'image Docker, pusher l'image sur ECR.
- CD (ArgoCD) : Rôle = S'assurer que le cluster (État Actuel) correspond au dépôt Git de configuration (État Désiré).
La migration (réalisée sur 6 mois) a permis d'atteindre les objectifs fixés.
| KPI (Indicateur) | Avant (Monolithe VM) | Après (K8s Microservices) |
|---|---|---|
| Temps de Déploiement | 45-60 minutes (Manuel, risqué) | < 5 minutes (Automatisé, GitOps) |
| Fréquence de Déploiement | 1x / semaine (Big Bang) | 5-10x / jour (par service) |
| Uptime (Disponibilité) | 99.5% (Pannes lors des déploiements) | 99.99% (Rolling updates, auto-réparation) |
| Scalabilité (Black Friday) | Manuelle (Scaler 2 grosses VMs -> 4). Lent et coûteux. | Automatique (HPA). (Ex: api-produits scale de 3 à 50 Pods). |
| Coûts (Infra) | Provisionné pour le pic (sur-provisionné). | Optimisé (Bin-packing). (Réduction de 20% des coûts de compute grâce à l'HPA/Cluster Autoscaler). |
