Ce qui se passe
Le HorizontalPodAutoscaler accepte minReplicas: 0. La porte de
fonctionnalité HPAScaleToZero passe en bêta et est activée par défaut
en v1.37, sur kube-apiserver comme sur kube-controller-manager. Avant, il
fallait un composant externe — KEDA, typiquement — ou activer la porte en alpha.
L'économie est nette sur les consommateurs de files et les traitements par lots, surtout quand chaque pod réserve des ressources chères : CPU dédiés, GPU.
Pourquoi CPU et mémoire ne peuvent pas marcher
Le HPA s'appuie d'ordinaire sur l'usage processeur ou mémoire. Ces deux mesures proviennent des pods en cours d'exécution : à zéro réplique, il n'y a plus rien à mesurer, donc plus aucun signal pour remonter.
Les métriques Object et External n'ont pas ce défaut : une longueur de
file existe indépendamment des workers qui la consomment. L'API rejette
d'ailleurs un HPA en minReplicas: 0 qui ne contiendrait que des métriques de
ressource.
Il faut donc un adaptateur qui expose la série via l'API External Metrics — le Prometheus Adapter, par exemple. Vérifiez la lecture avant de créer le HPA :
kubectl get --raw \
'/apis/external.metrics.k8s.io/v1beta1/namespaces/default/queue_consumer_lag?labelSelector=name%3Dworker_tasks'apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: queue-worker
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: queue-worker
minReplicas: 0
maxReplicas: 10
metrics:
- type: External
external:
metric:
name: queue_consumer_lag
selector:
matchLabels:
name: worker_tasks
target:
type: Value
value: "30"Zéro choisi, ou zéro subi ?
Un compte de répliques à zéro est ambigu : le contrôleur a-t-il réduit la
charge, ou un opérateur l'a-t-il mise en pause à la main ? Kubernetes tranche
avec une condition de statut ScaledToZero. Le HPA la met à True quand
c'est lui qui a descendu la charge à zéro ; une charge à zéro sans cette
condition reste en pause, et le contrôleur ne la réveillera pas.
Au retour, la condition repasse à False avec la raison NotScaledToZero.
Si l'adaptateur ne rend plus la métrique, le HPA signale ScalingActive=False
avec, par exemple, FailedGetExternalMetric — à surveiller, car la capacité ne
revient pas toute seule. Tout se lit avec kubectl describe hpa queue-worker.
Les limites à connaître
- Démarrage à froid : observation de la métrique, planification du pod, démarrage de l'application. Rien ne met les requêtes en tampon — un Service ne bufferise pas. Les charges HTTP ont besoin d'une couche d'attente séparée.
- Fenêtre de stabilisation : la descente reste soumise aux cinq minutes par
défaut, configurables via
spec.behavior.scaleDown. - Démarrez le Deployment avec au moins une réplique : mettre manuellement à zéro a toujours mis l'autoscaling en pause, et ce comportement est conservé.
- Mise à jour désynchronisée : attendez que les deux composants du plan de
contrôle portent la fonctionnalité avant de créer des HPA à
minReplicas: 0. Un controller-manager sans la porte lirareplicas: 0comme une pause manuelle et laissera la charge à zéro.
Avant un retour arrière ou une désactivation de la porte : repasser les HPA
concernés à minReplicas: 1 et remonter les charges actuellement à zéro.
À retenir
- La fonctionnalité est en alpha depuis la v1.16 ; la v1.36 a apporté la
condition
ScaledToZero, la v1.37 l'active par défaut. Détails dans KEP-2021. - Elle vise les charges pilotées par une file durable, pas les services HTTP.
- Le retour arrière est immédiat :
minReplicas: 1, ouHPAScaleToZero=false.
Source : Kubernetes