TP Kubernetes : mise à l'échelle automatique avec le HorizontalPodAutoscaler (HPA)

Durée estimée : 2 h à 2 h 30 Niveau : débutant à intermédiaire, suite des TP Kubernetes et Helm Prérequis : minikube, kubectl et Helm installés, notions de Deployment, Service, requests et limits

Objectifs

À la fin de ce TP, vous saurez :

  1. installer et utiliser metrics-server (kubectl top) ;
  2. expliquer comment le HPA calcule le nombre de réplicas ;
  3. créer un HPA en mode impératif puis déclaratif (autoscaling/v2) ;
  4. observer une montée en charge et une descente en direct ;
  5. régler la vitesse de réaction du HPA avec behavior ;
  6. éviter les trois pièges classiques : pas de requests, conflit avec replicas, cluster plein ;
  7. activer un HPA depuis un chart Helm.

Sommaire


Partie 0 : Préparation

0.1 Créer le cluster

On a besoin d'un peu de CPU pour que l'application ait de la place pour grandir :

minikube start -p hpa --driver=docker --cpus=4 --memory=4096
kubectl create namespace hpa
kubectl config set-context --current --namespace=hpa
mkdir -p ~/tp-hpa && cd ~/tp-hpa

0.2 Installer metrics-server

Le HPA a besoin de connaître la consommation CPU et mémoire des Pods. Cette information est fournie par metrics-server, qui interroge régulièrement le kubelet de chaque nœud.

minikube addons enable metrics-server -p hpa
kubectl get pods -n kube-system -l k8s-app=metrics-server

Attendez que le Pod soit Running, puis patientez une à deux minutes : metrics-server doit collecter une première série de mesures.

kubectl top nodes
kubectl top pods -n kube-system
Si vous obtenez error: Metrics API not available, c'est que les premières mesures ne sont pas encore prêtes. Réessayez un peu plus tard.

Sur un vrai cluster (hors minikube), on installe metrics-server avec son chart Helm ou son manifeste officiel. Chez la plupart des fournisseurs cloud, il est déjà présent.

Partie 1 : Comment fonctionne le HPA

1.1 Le principe

Le HorizontalPodAutoscaler est un contrôleur qui ajuste automatiquement le champ replicas d'un Deployment (ou d'un StatefulSet) selon une métrique, le plus souvent la consommation CPU.

« Horizontal » signifie qu'on ajoute ou retire des Pods. L'approche « verticale » consisterait à donner plus de CPU ou de mémoire à chaque Pod (c'est le rôle d'un autre outil, le VPA).

          ┌──────────────┐   mesure CPU/mémoire    ┌─────────────┐
          │ metrics-server│◄───────────────────────│ kubelet      │
          └──────┬───────┘                         │ (chaque nœud)│
                 │ toutes les 15 s environ          └─────────────┘
                 ▼
          ┌──────────────┐   calcule le nombre de réplicas souhaité
          │     HPA      │
          └──────┬───────┘
                 │ modifie spec.replicas
                 ▼
          ┌──────────────┐        ┌──────┐┌──────┐┌──────┐
          │  Deployment  │──────► │ Pod  ││ Pod  ││ Pod  │ ...
          └──────────────┘        └──────┘└──────┘└──────┘

1.2 Le calcul

La consommation est exprimée en pourcentage de la request CPU du conteneur. Si un Pod demande 200m (0,2 CPU) et consomme 100m, son utilisation est de 50 %.

Le HPA applique la formule :

réplicas souhaités = arrondi supérieur ( réplicas actuels × utilisation actuelle / utilisation cible )

Exemple avec une cible de 50 % :

Réplicas actuels Utilisation moyenne Calcul Réplicas souhaités
1 250 % 1 × 250 / 50 = 5 5
5 80 % 5 × 80 / 50 = 8 8
8 20 % 8 × 20 / 50 = 3,2 4
4 53 % écart inférieur à 10 % 4 (inchangé)
Tolérance : si le rapport entre utilisation actuelle et cible est compris entre 0,9 et 1,1, le HPA ne fait rien. Cela évite d'ajouter et de retirer des Pods en permanence pour quelques pourcents.

Le résultat est toujours borné par minReplicas et maxReplicas.

1.3 Les deux conditions indispensables

  1. metrics-server doit fonctionner.
  2. Les conteneurs doivent déclarer une requests.cpu (ou requests.memory pour une cible en mémoire). Sans request, impossible de calculer un pourcentage : le HPA ne fait rien. On le vérifiera en partie 7.

Partie 2 : L'application à faire grandir

On utilise hpa-example, l'image officielle de la documentation Kubernetes : un serveur PHP qui effectue un calcul coûteux en CPU à chaque requête.

Créez php-apache.yaml :

apiVersion: apps/v1
kind: Deployment
metadata:
  name: php-apache
spec:
  replicas: 1
  selector:
    matchLabels:
      app: php-apache
  template:
    metadata:
      labels:
        app: php-apache
    spec:
      containers:
        - name: php-apache
          image: registry.k8s.io/hpa-example
          ports:
            - containerPort: 80
          resources:
            requests:
              cpu: 200m          # base de calcul du pourcentage d'utilisation
            limits:
              cpu: 500m          # plafond : un Pod ne peut pas dépasser 0,5 CPU
---
apiVersion: v1
kind: Service
metadata:
  name: php-apache
spec:
  selector:
    app: php-apache
  ports:
    - port: 80
      targetPort: 80
kubectl apply -f php-apache.yaml
kubectl rollout status deployment php-apache

Testez l'application depuis un Pod temporaire :

kubectl run test --rm -it --image=busybox:1.36 --restart=Never -- wget -q -O- http://php-apache

Réponse attendue : OK!.

Observez la consommation au repos (patientez une minute si la ligne n'apparaît pas encore) :

kubectl top pods
Question : avec une limit de 500m et une request de 200m, quelle est l'utilisation maximale qu'un seul Pod peut atteindre, exprimée en pourcentage de sa request ? (réponse en annexe)

Partie 3 : Un premier HPA en une commande

kubectl autoscale deployment php-apache --cpu-percent=50 --min=1 --max=10
kubectl get hpa

Résultat attendu, au bout d'une minute environ :

NAME         REFERENCE               TARGETS       MINPODS   MAXPODS   REPLICAS   AGE
php-apache   Deployment/php-apache   cpu: 0%/50%   1         10        1          1m

La colonne TARGETS affiche l'utilisation actuelle et la cible. Tant qu'elle affiche <unknown>, les métriques ne sont pas encore disponibles.

Regardez ce que la commande a réellement créé :

kubectl get hpa php-apache -o yaml

On retrouve un objet autoscaling/v2 complet. Comme pour les Deployments, on préfère l'écrire soi-même dans un fichier versionné. Supprimez-le :

kubectl delete hpa php-apache
Dans les versions récentes de kubectl, --cpu-percent est remplacé par --cpu=50%. Les deux syntaxes peuvent coexister selon votre version.

Partie 4 : Le HPA en YAML

Créez hpa.yaml :

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: php-apache
spec:
  scaleTargetRef:                 # l'objet dont le HPA pilote les réplicas
    apiVersion: apps/v1
    kind: Deployment
    name: php-apache
  minReplicas: 1
  maxReplicas: 10
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization       # en pourcentage de la request
          averageUtilization: 50  # cible : 50 % en moyenne sur tous les Pods
kubectl apply -f hpa.yaml
kubectl get hpa
kubectl describe hpa php-apache
Types de cible possibles :

Partie 5 : Montée en charge

5.1 Préparer l'observation

Ouvrez deux terminaux supplémentaires et laissez-les tourner pendant toute la partie.

Terminal 2, l'état du HPA :

kubectl get hpa php-apache -w

Terminal 3, les Pods :

kubectl get pods -l app=php-apache -w

5.2 Générer de la charge

On crée un générateur de charge sous forme de Deployment. Son nombre de réplicas sert de « bouton de volume » : plus il y a de générateurs, plus la charge est forte.

Créez load-generator.yaml :

apiVersion: apps/v1
kind: Deployment
metadata:
  name: load-generator
spec:
  replicas: 1
  selector:
    matchLabels:
      app: load-generator
  template:
    metadata:
      labels:
        app: load-generator
    spec:
      containers:
        - name: busybox
          image: busybox:1.36
          command: ["/bin/sh", "-c", "while true; do wget -q -O- http://php-apache > /dev/null; done"]
          resources:
            requests:
              cpu: 10m
            limits:
              cpu: 100m
kubectl apply -f load-generator.yaml

5.3 Observer

Dans les minutes qui suivent, regardez les terminaux :

  1. l'utilisation dans TARGETS dépasse largement 50 % (par exemple cpu: 240%/50%) ;
  2. REPLICAS augmente, en une ou plusieurs étapes ;
  3. de nouveaux Pods php-apache apparaissent ;
  4. l'utilisation moyenne redescend vers la cible, puis se stabilise.

Consultez les décisions prises par le HPA :

kubectl describe hpa php-apache | tail -n 15

La section Events contient des lignes du type :

New size: 4; reason: cpu resource utilization (percentage of request) above target

Vérifiez la formule de la partie 1.2 avec les valeurs observées : réplicas avant, utilisation mesurée, réplicas après.

5.4 Augmenter la charge

kubectl scale deployment load-generator --replicas=4

Le HPA ajoute des Pods jusqu'à atteindre maxReplicas: 10. Si la charge est encore trop forte, l'utilisation reste au-dessus de la cible : le HPA ne peut pas aller plus loin.

kubectl top pods
kubectl describe hpa php-apache | grep -A3 Conditions

La condition ScalingLimited indique que le HPA voudrait plus de réplicas mais que maxReplicas l'en empêche.

✅ Point de contrôle 5

  1. Avec 3 réplicas à 120 % d'utilisation moyenne et une cible de 50 %, combien de réplicas le HPA demande-t-il ?
  2. Pourquoi l'utilisation moyenne redescend-elle quand de nouveaux Pods arrivent ?
  3. Que signifie la condition ScalingLimited ?

Partie 6 : Descente et réglage du comportement

6.1 Couper la charge

kubectl scale deployment load-generator --replicas=0

Dans le terminal du HPA, l'utilisation tombe rapidement à 0 %... mais le nombre de réplicas ne bouge pas. Patientez et chronométrez : la descente commence au bout d'environ 5 minutes.

Pourquoi ? Par défaut, le HPA applique une fenêtre de stabilisation de 300 secondes à la descente : il retient la recommandation la plus haute des 5 dernières minutes. Cela évite de supprimer des Pods pendant un creux passager, puis de devoir les recréer quelques secondes plus tard. La montée, elle, est immédiate.

6.2 Les valeurs par défaut, écrites explicitement

Le comportement du HPA se règle dans la section behavior. Voici l'équivalent des valeurs par défaut. Ajoutez ce bloc dans hpa.yaml, au niveau de spec (à côté de metrics) :

  behavior:
    scaleUp:
      stabilizationWindowSeconds: 0     # montée immédiate
      policies:
        - type: Percent
          value: 100                    # au plus doubler...
          periodSeconds: 15             # ...toutes les 15 secondes
        - type: Pods
          value: 4                      # ou ajouter 4 Pods toutes les 15 secondes
          periodSeconds: 15
      selectPolicy: Max                 # retenir la politique qui autorise le plus
    scaleDown:
      stabilizationWindowSeconds: 300   # 5 minutes de recul avant de descendre
      policies:
        - type: Percent
          value: 100                    # peut tout retirer d'un coup
          periodSeconds: 15
Lecture des politiques : chaque politique fixe un maximum de changement par période. selectPolicy: Max choisit la politique la plus permissive, Min la plus restrictive, Disabled interdit le changement dans ce sens.

6.3 Une descente rapide et progressive

Pour le TP, on veut une descente qui commence au bout de 30 secondes et retire un Pod toutes les 15 secondes. Modifiez le bloc scaleDown :

    scaleDown:
      stabilizationWindowSeconds: 30
      policies:
        - type: Pods
          value: 1
          periodSeconds: 15
kubectl apply -f hpa.yaml
kubectl scale deployment load-generator --replicas=3

Attendez que le HPA soit monté (plusieurs réplicas), puis coupez la charge :

kubectl scale deployment load-generator --replicas=0

Cette fois, la descente démarre rapidement et se fait Pod par Pod.

En production : une descente trop rapide provoque des oscillations (on retire des Pods, la charge par Pod remonte, on en rajoute). On garde généralement une fenêtre de plusieurs minutes. La vitesse se règle selon le coût d'un Pod et son temps de démarrage.

✅ Point de contrôle 6

  1. Pourquoi la descente par défaut attend-elle 5 minutes, alors que la montée est immédiate ?
  2. Que fait la politique type: Pods, value: 1, periodSeconds: 15 en scaleDown ?
  3. Comment interdire complètement la descente automatique ?

Partie 7 : Les pièges classiques

7.1 Piège n° 1 : pas de requests

Créez sans-requests.yaml :

apiVersion: apps/v1
kind: Deployment
metadata:
  name: sans-requests
spec:
  replicas: 1
  selector:
    matchLabels:
      app: sans-requests
  template:
    metadata:
      labels:
        app: sans-requests
    spec:
      containers:
        - name: nginx
          image: nginx:1.27-alpine
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: sans-requests
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: sans-requests
  minReplicas: 1
  maxReplicas: 5
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 50
kubectl apply -f sans-requests.yaml
sleep 60
kubectl get hpa sans-requests
kubectl describe hpa sans-requests | tail -n 6

TARGETS reste à <unknown> et les événements indiquent un message du type :

failed to get cpu utilization: missing request for cpu in container nginx

Sans request, pas de pourcentage, donc pas de mise à l'échelle, et aucune erreur visible tant qu'on ne regarde pas le HPA. C'est l'erreur la plus fréquente.

kubectl delete -f sans-requests.yaml

7.2 Piège n° 2 : le HPA et le champ replicas se disputent

Relancez la charge pour que le HPA monte à plusieurs réplicas :

kubectl scale deployment load-generator --replicas=3
kubectl get hpa php-apache -w       # attendez 4 réplicas ou plus, puis Ctrl+C

Réappliquez maintenant le manifeste de l'application, comme le ferait une pipeline de déploiement :

kubectl apply -f php-apache.yaml
kubectl get deployment php-apache

Le Deployment retombe à 1 réplica (valeur écrite dans le fichier), des Pods sont supprimés en pleine charge, puis le HPA les recrée quelques secondes plus tard. À chaque déploiement, l'application subit une perte de capacité.

Correction : quand un HPA pilote un Deployment, on retire le champ replicas du manifeste. Supprimez la ligne replicas: 1 de php-apache.yaml, puis :

kubectl apply -f php-apache.yaml
kubectl get deployment php-apache

Le nombre de réplicas choisi par le HPA est conservé.

Même logique avec Helm : de nombreux charts n'écrivent pas replicas dans le Deployment quand leur HPA est activé ({{- if not .Values.autoscaling.enabled }}). C'est le cas du chart généré par helm create.

7.3 Piège n° 3 : le cluster est plein

Le HPA crée des Pods, mais il ne crée pas de nœuds. Augmentez fortement le maximum et la charge :

kubectl patch hpa php-apache -p '{"spec":{"maxReplicas":40}}'
kubectl scale deployment load-generator --replicas=10
kubectl get pods -l app=php-apache | grep -c Pending

Au bout de quelques minutes, des Pods php-apache restent en Pending :

kubectl describe pod $(kubectl get pods -l app=php-apache --field-selector=status.phase=Pending -o name | head -n 1) | tail -n 3

Message du type Insufficient cpu. Le nœud n'a plus assez de CPU disponible pour honorer les requests des nouveaux Pods.

Pour ajouter des nœuds automatiquement, il faut un autre composant : le Cluster Autoscaler ou Karpenter, fournis par la plupart des offres Kubernetes managées. Ils surveillent les Pods Pending et commandent de nouvelles machines au fournisseur d'infrastructure.

Remettez la situation en ordre :

kubectl scale deployment load-generator --replicas=0
kubectl patch hpa php-apache -p '{"spec":{"maxReplicas":10}}'

✅ Point de contrôle 7

  1. Que signifie <unknown> dans la colonne TARGETS ?
  2. Pourquoi faut-il retirer replicas d'un Deployment piloté par un HPA ?
  3. Le HPA demande 15 réplicas mais seuls 9 tournent. Où chercher ?

Partie 8 : Exercices

Exercice 1 : deux métriques à la fois

Ajoutez au HPA php-apache une seconde métrique sur la mémoire, avec une cible de 50Mi par Pod en moyenne (type: AverageValue). Ajoutez aussi une requests.memory: 64Mi au conteneur.

  1. Écrivez le bloc metrics complet.
  2. Relancez la charge et observez la colonne TARGETS.
  3. Question : quand deux métriques donnent des recommandations différentes, laquelle le HPA retient-il ?

Exercice 2 : un HPA fourni par un chart Helm

Le chart podinfo (TP Helm précédent) contient un HPA désactivé par défaut.

helm repo add podinfo https://stefanprodan.github.io/podinfo
helm repo update
helm show values podinfo/podinfo --version 6.15.0 | grep -n -A8 "^hpa:"
helm show values podinfo/podinfo --version 6.15.0 | grep -n -A5 "^resources:"
  1. Sans générer aucune charge, observez kubectl get hpa web-podinfo -w pendant deux minutes. Que se passe-t-il ?
  2. Expliquez ce comportement en regardant la request CPU définie par défaut dans le chart.
  3. Corrigez avec helm upgrade et une valeur plus réaliste.

Installez podinfo avec le HPA activé et une cible CPU de 80 % :

helm install web podinfo/podinfo --version 6.15.0 -n hpa \  --set hpa.enabled=true --set hpa.cpu=80 --set hpa.maxReplicas=5

Exercice 3 : questions de synthèse

  1. Une application met 90 secondes à démarrer. Quels réglages du HPA et de l'application adapteriez-vous ?
  2. Pourquoi un HPA sur la CPU est-il peu adapté à une application qui passe son temps à attendre une base de données ?
  3. Un collègue fixe minReplicas: 1 pour une API en production. Quel risque voyez-vous ?

Partie 9 : Nettoyage

helm uninstall web -n hpa 2>/dev/null
kubectl delete namespace hpa
kubectl config set-context --current --namespace=default
minikube delete -p hpa
kubectl config use-context minikube

Annexe A : Aide-mémoire

Action Commande
Activer metrics-server (minikube) minikube addons enable metrics-server
Consommation des nœuds / des Pods kubectl top nodes / kubectl top pods
Consommation par conteneur kubectl top pods --containers
Créer un HPA rapidement kubectl autoscale deployment <nom> --cpu-percent=50 --min=1 --max=10
Lister les HPA kubectl get hpa
Suivre un HPA en direct kubectl get hpa <nom> -w
Voir les décisions et conditions kubectl describe hpa <nom>
Modifier le maximum kubectl patch hpa <nom> -p '{"spec":{"maxReplicas":20}}'
Documentation kubectl explain hpa.spec.behavior.scaleDown

Structure d'un HPA autoscaling/v2

spec:
  scaleTargetRef: { apiVersion, kind, name }
  minReplicas: N
  maxReplicas: M
  metrics:
    - type: Resource            # cpu ou memory, fournis par metrics-server
    - type: Pods                # métrique applicative par Pod (adaptateur Prometheus)
    - type: Object              # métrique d'un autre objet (ex. un Ingress)
    - type: External            # métrique extérieure au cluster (ex. file de messages)
  behavior:
    scaleUp:   { stabilizationWindowSeconds, policies, selectPolicy }
    scaleDown: { stabilizationWindowSeconds, policies, selectPolicy }

Annexe B : Dépannage

Symptôme Cause probable Vérification / solution
error: Metrics API not available metrics-server absent ou pas encore prêt kubectl get pods -n kube-system -l k8s-app=metrics-server, attendre 1 à 2 minutes
TARGETS à <unknown> pas de requests sur le conteneur, ou métriques pas encore disponibles kubectl describe hpa, section Events
Le HPA ne descend pas fenêtre de stabilisation de 300 s par défaut attendre ou régler behavior.scaleDown
Le nombre de réplicas retombe à chaque déploiement champ replicas présent dans le manifeste retirer replicas du Deployment
Pods Pending avec Insufficient cpu cluster plein réduire maxReplicas ou les requests, ajouter des nœuds
Le HPA monte au maximum sans charge request CPU très faible : la moindre consommation dépasse la cible fixer une request réaliste
Condition ScalingLimited maxReplicas ou minReplicas atteint augmenter maxReplicas si les nœuds le permettent
Utilisation plafonnée vers 250 % la limit bride le conteneur c'est attendu : 500m / 200m = 250 %

Annexe C : Corrigés

Question de la partie 2

500m / 200m = 250 %. Un Pod ne peut jamais dépasser 250 % d'utilisation, car la limit le bride. C'est pourquoi TARGETS plafonne autour de cette valeur au début de la montée en charge.

Point de contrôle 5

  1. 3 × 120 / 50 = 7,2, arrondi supérieur : 8 réplicas.
  2. La même charge totale est répartie par le Service entre davantage de Pods : chacun en reçoit moins.
  3. Le HPA voudrait sortir de l'intervalle minReplicas / maxReplicas mais en est empêché.

Point de contrôle 6

  1. Retirer des Pods trop vite après un pic risque de les supprimer pendant un simple creux passager, puis de devoir les recréer. Manquer de capacité dégrade le service, alors qu'en garder un peu trop quelques minutes ne coûte que des ressources.
  2. Elle autorise au maximum la suppression d'un Pod toutes les 15 secondes.
  3. behavior.scaleDown.selectPolicy: Disabled.

Point de contrôle 7

  1. Le HPA ne parvient pas à calculer la métrique : metrics-server indisponible, métriques pas encore collectées, ou absence de request sur un conteneur.
  2. À chaque kubectl apply (ou helm upgrade), la valeur du fichier écrase celle choisie par le HPA, ce qui supprime des Pods en pleine charge.
  3. Les Pods manquants sont probablement Pending : kubectl get pods, puis kubectl describe pod sur l'un d'eux (ressources insuffisantes, règles d'affinité, quotas du namespace).

Exercice 1

Dans le conteneur de php-apache.yaml :

          resources:
            requests:
              cpu: 200m
              memory: 64Mi
            limits:
              cpu: 500m

Dans hpa.yaml :

  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 50
    - type: Resource
      resource:
        name: memory
        target:
          type: AverageValue
          averageValue: 50Mi
kubectl apply -f php-apache.yaml -f hpa.yaml
kubectl get hpa php-apache

La colonne TARGETS affiche les deux métriques, par exemple cpu: 180%/50%, memory: 12Mi/50Mi.

Réponse : le HPA calcule un nombre de réplicas pour chaque métrique et retient le plus grand. La métrique la plus exigeante l'emporte.

Exercice 2

  1. Le HPA monte au maximum (5 réplicas) alors qu'aucune charge n'est envoyée.
  2. Le chart fixe requests.cpu: 1m. La simple consommation au repos de podinfo (quelques millicores) représente déjà plusieurs centaines de pourcents de cette request, bien au-dessus de la cible de 80 %.
  3. Correction :
helm upgrade web podinfo/podinfo --version 6.15.0 -n hpa \
  --set hpa.enabled=true --set hpa.cpu=80 --set hpa.maxReplicas=5 \
  --set resources.requests.cpu=50m
kubectl get hpa web-podinfo -w

L'utilisation retombe à quelques pourcents et, après la fenêtre de stabilisation, le HPA redescend vers minReplicas.

Remarque : dans ce chart, minReplicas du HPA reprend la valeur replicaCount. Chaque chart a ses propres conventions, d'où l'intérêt de lire les templates (helm pull --untar).

Exercice 3

  1. Ajouter une readinessProbe (voire une startupProbe) pour que les Pods ne reçoivent du trafic qu'une fois prêts, garder une marge avec un minReplicas plus élevé ou une cible CPU plus basse, et une montée plus agressive (scaleUp avec une politique Pods généreuse) pour compenser le délai de démarrage.
  2. Ses Pods consomment peu de CPU même quand ils sont saturés de requêtes en attente : le HPA ne verrait aucune raison de monter. Il faut une métrique plus représentative (requêtes par seconde, latence, taille de file), via un adaptateur Prometheus ou KEDA.
  3. Un seul Pod : aucune tolérance à la panne d'un nœud ou au redémarrage du Pod, et une mise à jour progressive sans capacité de réserve. En production, on garde au moins 2 réplicas, idéalement répartis par anti-affinité (voir le TP sur les affinités).

Pour aller plus loin

  • KEDA : mise à l'échelle selon des événements (file RabbitMQ, Kafka, requêtes Prometheus, cron), y compris jusqu'à zéro réplica.
  • VPA (VerticalPodAutoscaler) : ajuste automatiquement les requests des Pods. À ne pas combiner avec un HPA sur la même métrique.
  • Cluster Autoscaler / Karpenter : ajout et retrait automatiques de nœuds.
  • PodDisruptionBudget : garantir un minimum de Pods disponibles pendant les descentes et les maintenances.