RousselTMLEARNING

Conteneurisation

Kubernetes : fiabilité et mise à l'échelle (probes, ressources, HPA, PDB)

Rendre une application résiliente dans Kubernetes : liveness, readiness et startup probes, requests/limits, QoS, HPA, VPA, Cluster Autoscaler, PodDisruptionBudget et arrêt propre.

1. Les probes #

Dire à Kubernetes si l'application va bien.

Les trois sondes #

ProbeQuestion poséeSi elle échoue
startupProbeL'application a-t-elle fini de démarrer ?Redémarrage du conteneur (après un long délai autorisé)
readinessProbePeut-elle recevoir du trafic ?Retirée du Service (pas redémarrée)
livenessProbeEst-elle toujours vivante ?Redémarrage du conteneur
containers:
  - name: api
    image: exemple/api:1.4.2
    startupProbe:
      httpGet: { path: /healthz, port: 8080 }
      failureThreshold: 30
      periodSeconds: 5                  # jusqu'à 150 s pour démarrer
    readinessProbe:
      httpGet: { path: /ready, port: 8080 }
      periodSeconds: 5
      failureThreshold: 3
    livenessProbe:
      httpGet: { path: /healthz, port: 8080 }
      periodSeconds: 10
      timeoutSeconds: 2
Erreur Courante : Une liveness probe qui vérifie une dépendance externe (base de données) provoque des redémarrages en cascade quand cette dépendance tombe. Gardez-la simple : « mon processus répond ».

2. Ressources et qualité de service #

requests, limits et QoS.

Dimensionner correctement #

resources:
  requests: { cpu: 250m, memory: 256Mi }      # base du scheduling et du HPA
  limits:   { memory: 512Mi }                 # limite mémoire ; CPU sans limite pour éviter le throttling

kubectl top pods --containers
kubectl describe pod <pod> | grep -E 'QoS|Last State|OOMKilled'
kubectl get pods -o custom-columns=NOM:.metadata.name,QOS:.status.qosClass
Classe QoSConditionEn cas de pression sur le nœud
Guaranteedrequests = limits (CPU et mémoire) pour tous les conteneursÉvincé en dernier
Burstableni Guaranteed ni BestEffort : au moins un conteneur a une request ou une limitIntermédiaire
BestEffortaucune request ni limitÉvincé en premier
À savoir : En cas de pression sur le nœud, le kubelet choisit les pods à évincer d'abord selon leur consommation au-delà de leurs requests, puis selon leur priorité (PriorityClass), puis leur consommation relative. La classe QoS en découle en pratique (un pod BestEffort dépasse toujours ses requests nulles), mais ce n'est pas le critère direct.

3. Autoscaling #

HPA, VPA et Cluster Autoscaler.

Horizontal Pod Autoscaler #

Boucle de l'HPA
metrics-server suffit pour les métriques CPU et mémoire ; une métrique personnalisée (type Pods ou External) exige un adaptateur : Prometheus Adapter ou KEDA.
kubectl autoscale deployment web --cpu-percent=70 --min=2 --max=10
kubectl get hpa -w

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata: { name: web }
spec:
  scaleTargetRef: { apiVersion: apps/v1, kind: Deployment, name: web }
  minReplicas: 2
  maxReplicas: 10
  metrics:
    - type: Resource
      resource: { name: cpu, target: { type: Utilization, averageUtilization: 70 } }
    - type: Pods                    # métrique personnalisée : nécessite Prometheus Adapter ou KEDA
      pods: { metric: { name: http_requests_per_second }, target: { type: AverageValue, averageValue: "100" } }
  behavior:
    scaleDown: { stabilizationWindowSeconds: 300 }
# Générer de la charge pour observer le scaling
kubectl run load --rm -it --image=busybox --restart=Never -- sh -c "while true; do wget -q -O- http://web; done"
kubectl get hpa web -w

VPA, Cluster Autoscaler et KEDA #

  • VPA : recommande ou ajuste requests/limits selon la consommation réelle (mode Off pour les recommandations).
  • Cluster Autoscaler / Karpenter : ajoute ou retire des nœuds quand des pods restent en Pending.
  • KEDA : autoscaling piloté par événements (longueur de file Kafka/RabbitMQ, cron, métriques Prometheus), jusqu'à zéro réplica.

4. Disponibilité pendant les opérations #

PDB et arrêt propre.

PodDisruptionBudget et graceful shutdown #

apiVersion: policy/v1
kind: PodDisruptionBudget
metadata: { name: web }
spec:
  minAvailable: 2                  # ou maxUnavailable: 1
  selector: { matchLabels: { app: web } }
kubectl drain <noeud> --ignore-daemonsets --delete-emptydir-data     # respecte les PDB
kubectl cordon <noeud> && kubectl uncordon <noeud>

# Arrêt propre : laisser le temps de terminer les requêtes
terminationGracePeriodSeconds: 45
lifecycle:
  preStop: { exec: { command: ["sh", "-c", "sleep 10"] } }       # laisse l'Ingress retirer le pod avant SIGTERM
Bonne Pratique : Combinez au moins 2 réplicas, une readinessProbe, un PodDisruptionBudget et des topologySpreadConstraints pour survivre à une panne de nœud ou de zone.

Articles liés

Sécurité réseau des conteneurs (container network security) et networking Kubernetes

Sécuriser le réseau des conteneurs : fonctionnement du networking Docker et Kubernetes, CNI, NetworkPolicies …

Container registry : choisir et sécuriser son registre d'images (Docker Hub, Harbor, GHCR, ECR)

Comprendre les registres de conteneurs : Docker Hub, GitHub Container Registry, registres cloud (ECR, ACR, Ar…

Kubernetes : architecture et composants (control plane, nœuds, objets)

Comprendre l'architecture de Kubernetes : API server, etcd, scheduler, controller manager, kubelet, kube-prox…

Pour aller plus loin

Soutenir

♥ SOUTENIR

Soutenez RousselTM Learning

Les formations, articles, TP et attestations restent gratuits et sans publicité intrusive. Une contribution libre, du montant de votre choix, finance l’hébergement, les environnements de TP et l’écriture de nouveaux contenus.

Contribuer avec PayPal Montant libre · carte bancaire ou compte PayPalEn savoir plus
QR code PayPal
Ou scannez ce QR code avec votre téléphone

Merci, chaque contribution compte !