06

☸️ Kubernetes Avancé

L'OS du Cloud

"Quand vous passez de 3 à 3000 conteneurs, les scripts manuels ne suffisent plus. Kubernetes est le pilote automatique implacable qui décide qui vit, qui meurt, et qui scale parmi vos flottes de microservices."

🚢 Analogie : Le Gestionnaire de Port de Fret

Docker fabrique des conteneurs standardisés, parfaits pour isoler la marchandise.
Kubernetes est le Directeur du Port. Il ne construit pas les conteneurs, mais il décide sur quel navire (Node) les poser pour équilibrer la charge (Load Balancing). Si un navire coule, il ordonne de redéployer ces mêmes conteneurs sur un autre cargo disponible sans aucune intervention humaine (Self-healing).

⚠️ Rappel : Quand NE PAS utiliser Kubernetes

K8s est extraordinairement puissant mais complexe. Si vous hébergez une petite application monolithique avec un trafic faible, utiliser Kubernetes c'est comme affréter un porte-conteneurs pour livrer une pizza. Un simple Docker Compose ou un hébergement PaaS sera bien plus adapté.

📖 Kubernetes : L'OS du Cloud

Kubernetes (ou K8s) est devenu le standard de fait pour faire tourner des conteneurs en production à grande échelle. Il résout le problème du Cycle de Vie : comment je déploie, comment je scale, comment je répare et comment je connecte mes applications.

K8s ne s'occupe pas de "comment" l'app tourne (c'est le rôle de Docker/Containerd), mais de "où" et "combien" elle tourne pour garantir le service aux utilisateurs.

💡 Le saviez-vous ? De Borg à Kubernetes

Kubernetes a été créé par Google en 2014, basé sur leur système interne secret appelé Borg. Google lançait déjà des milliards de conteneurs par semaine avant même que Docker n'existe !

Étymologie : Kubernetes vient du grec signifiant "timonier" ou "pilote" (celui qui tient le gouvernail). C'est pour ça que le logo a 7 branches (référence au nom de code original "Project Seven" de Star Trek).

❓ A. Pourquoi Kubernetes ?

Docker seul ne suffit pas pour...

  • Lancer 100 containers sur 10 serveurs
  • Remplacer automatiquement un container crashé
  • Mettre à jour sans downtime (Rolling Update)
  • Répartir le trafic entre les instances (Load Balancing)

K8s apporte...

  • Self-Healing : Recréation automatique
  • Auto-Scaling : HPA, VPA
  • Rolling Updates : Zero-downtime
  • Déclaratif : YAML = État souhaité

🏗️ B. Architecture K8s

Control Plane (Cerveau) API Server etcd (K/V Store) Scheduler Controller Mgr Worker Node (Muscles) Kubelet Kube-Proxy Container Runtime Pod 1 Pod 2 Worker Node 2 ...

📦 C. Objets Fondamentaux

Objet Rôle Durée de vie
Pod Exécute 1+ containers (IP partagée) Éphémère (peut être recréé)
Deployment Gère les Pods (répliques, updates) Permanent
Service Expose les Pods (Load Balancing) Permanent
Ingress Routage HTTP externe Permanent
ConfigMap Configuration (non-sensible) Permanent
Secret Données sensibles (base64) Permanent

📝 D. Exemple YAML Complet

deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
      - name: app
        image: myregistry/my-app:v1.0
        ports:
        - containerPort: 3000
        resources:
          limits:
            memory: "256Mi"
            cpu: "500m"
service.yaml
apiVersion: v1
kind: Service
metadata:
  name: my-app-svc
spec:
  type: ClusterIP
  selector:
    app: my-app
  ports:
  - port: 80
    targetPort: 3000
Flow :
User → Ingress → Service → Pod

⌨️ E. Kubectl Essentiel

Commande Action
kubectl get pods Lister les pods (ajouter -A pour tous namespaces)
kubectl describe pod <name> Détails complets (events, status, volumes)
kubectl logs -f <pod> Suivre les logs en temps réel
kubectl exec -it <pod> -- sh Shell dans le pod
kubectl apply -f manifest.yaml Créer/Mettre à jour les ressources
kubectl delete -f manifest.yaml Supprimer les ressources
kubectl scale deploy <name> --replicas=5 Scaler manuellement
kubectl port-forward svc/my-svc 8080:80 Accès local sans Ingress

🛑 Troubleshooting : Le Pod est en "CrashLoopBackOff"

  • Symptôme : kubectl get pods montre un statut "CrashLoopBackOff" et le nombre de "RESTARTS" augmente sans cesse.
  • Diagnostic : Le container démarre, mais l'application crash immédiatement (erreur de code, port déjà utilisé, variables d'environnement manquantes). K8s recrée le container, qui re-crash, etc. Le "BackOff" indique que K8s attend de plus en plus longtemps entre chaque tentative.
  • Remède : 1. Regardez les logs : kubectl logs <nom-du-pod> --previous (le flag --previous montre les logs du process qui vient de crasher).
    2. Regardez les événements K8s : kubectl describe pod <nom-du-pod> (recherchez les erreurs en bas dans la section "Events", typiquement des fautes de liveness probe ou d'image Pull).

🎩 Helm (Package Manager)

  • Chart = Package d'app K8s (templates + values)
  • helm install myrelease bitnami/nginx
  • helm upgrade myrelease . -f values-prod.yaml
  • Gère les releases, rollbacks, et templating

🚀 Stratégies de Déploiement

  • RollingUpdate : Remplace progressivement (défaut)
  • Recreate : Kill all, then create new
  • Blue/Green : Via 2 Deployments + switch Service
  • Canary : Via Ingress weights ou Service Mesh

🔍 Networking & Storage : Sous le capot

🌐 CNI (Container Network Interface)
K8s ne gère pas le réseau lui-même. Il délègue à un plugin CNI (Calico, Flannel, Cilium). C'est lui qui donne une IP unique à chaque Pod et gère les "Network Policies" (Pare-feu interne).
💾 PV vs PVC (Le stockage persistant)
- PV (Persistent Volume) : La ressource physique (le disque dur). Géré par l'admin.
- PVC (Persistent Volume Claim) : La requête de l'utilisateur ("Je veux 10Go").
K8s fait le "match" entre les deux.

📊 Cas d'étude : Pokémon GO - Le crash test de Kubernetes

50x Trafic vs prévisions
1000+ Nodes GKE (GCP)
0.1s Latency max tolérée

Contexte : Lors du lancement en 2016, Pokémon GO a reçu 50 fois le trafic prévu en quelques heures. Aucun système traditionnel n'aurait survécu.

Transformation :

  1. Google Kubernetes Engine (GKE) : Niantic utilisait K8s pour scaler leur backend massivement de manière transparente.
  2. Custom Autoscaler : Utilisation de métriques métier pour rajouter des milliers de containers en quelques minutes.
  3. Global Load Balancing : Utilisation de l'architecture K8s pour router le trafic mondial vers les clusters les plus proches.

Résultat : Malgré quelques lenteurs au début, le jeu est resté debout. C'est la preuve ultime que K8s est prêt pour le "Hyper-Scale".

🔄 À Retenir - Kubernetes Mastery

  • Abstraction : K8s masque l'infrastructure. On déploie sur le cluster, pas sur des VM.
  • Déclaratif : On décrit l'état final, K8s se charge de la convergence.
  • Haute Disponibilité : Pods répartis, Liveness/Readiness probes.
  • Écosystème : C'est devenu l'OS du Cloud (Inbound de CNCF).

🏗️ F. Advanced Workloads

💾

StatefulSet

Pour les bases de données (Redis, Postgres). Garantit l'ordre (db-0, db-1), l'unicité réseau et le stockage stable.

👻

DaemonSet

Assure qu'une copie du Pod tourne sur chaque nœud. Idéal pour Logs (Fluentd) et Monitoring (Node Exporter).

⏱️

Job / CronJob

Tâches éphémères qui doivent se terminer (Batch processing, Backups). CronJob = Job planifié.

🧩 G. Extending Kubernetes (Operators)

La puissance de K8s, c'est son extensibilité. Vous pouvez créer vos propres types de ressources via les CRD (Custom Resource Definitions) et les piloter avec un Operator.

prometheus.yaml (CRD Example)
apiVersion: monitoring.coreos.com/v1
kind: Prometheus
metadata:
  name: k8s
spec:
  replicas: 2
  version: v2.26.0
  serviceAccountName: prometheus
# Ce n'est pas natif K8s !
# L'Opérateur Prometheus va lire ça
# et créer StatefulSets, Services, Configs...
🤖 Le Pattern Operator
C'est coder l'intelligence d'un humain dans un logiciel.

Exemple : Postgres Operator
Au lieu de configurer manuellement la réplication, le backup et le failover, vous créez un objet PostgresCluster. L'Opérateur détecte si le primaire tombe et promeut automatiquement un replica, met à jour le DNS, etc.

🛡️ H. Security & RBAC

role-binding.yaml
kind: Role
metadata:
  name: pod-reader
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "list", "watch"]
---
kind: RoleBinding
metadata:
  name: read-pods
subjects:
- kind: User
  name: "jane@example.com"
roleRef:
  kind: Role
  name: pod-reader

🔐 Concepts Clés Access Control

  • ServiceAccount : L'identité d'un Pod (pour parler à l'API K8s).
  • Role / ClusterRole : Un ensemble de permissions (Quoi ?). Role = Namespace, ClusterRole = Global.
  • Binding : L'association "Qui" (User/SA) a le droit "Quoi" (Role).
  • Admission Controller : Intercepte les requêtes avant persistence (ex: OPA Gatekeeper pour interdire les images :latest).

📈 I. Autoscaling Deep Dive

HPA (Horizontal)

Ajoute des Pods quand CPU > 80%.

  • Rapide (secondes)
  • Stateless apps

VPA (Vertical)

Agrandit les Pods (plus de CPU/RAM). Redémarre le Pod.

  • Pour Java/DBs lourdes
  • Lent (restart requis)

Cluster Autoscaler

Ajoute des Nœuds (VMs) quand il n'y a plus de place pour les Pods.

Nouveau : Karpenter (AWS) provisionne des nœuds "Just-in-time" en quelques secondes.

📊 Cas d'étude : OpenAI - K8s à l'échelle de l'Humanité

7,500+ Nodes
100k+ GPUs (A100/H100)
IPfix Problème réseau majeur

Contexte : Pour entraîner GPT-4, OpenAI a dû pousser Kubernetes dans ses derniers retranchements sur Azure.

Défis & Solutions :

  • Etcd Latency : Avec 7500 nœuds, etcd saturait. Solution : Sharding d'events et tuning agressif des timeouts.
  • IP Table Overflow : Le réseau classique (iptables) ne tenait pas la charge. Passage complet à IPVS ou eBPF.
  • Job Scheduling : Besoin de lancer des Jobs MPI (Message Passing Interface) massivement parallèles. Utilisation de Cosmos (scheduler custom) sur K8s.