Le scale up du Cluster Autoscaler est la partie facile : un pod reste Pending faute de capacité, le contrôleur demande un nœud, le nœud arrive. Le scale down est la partie qui échoue en silence : un nœud sous-utilisé depuis des heures, jamais retiré, et rien dans les logs qui saute aux yeux tant qu’on ne sait pas où regarder.
Ce qui déclenche un scale up
Le contrôleur surveille les pods Pending dont le scheduler ne trouve aucun nœud satisfaisant leurs contraintes (requests, affinités, taints). Il simule alors l’ajout d’un nœud à partir des gabarits de chaque groupe de nœuds disponible, et provisionne celui qui permettrait de placer les pods en attente. Sans requests posées correctement sur les pods (le même prérequis silencieux que pour le HPA), cette simulation n’a pas de base fiable.
Ce qui bloque un scale down
Un nœud n’est candidat au retrait que si son utilisation reste sous un seuil pendant une durée soutenue (scale-down-unneeded-time, 10 minutes par défaut) et que tous ses pods peuvent être replacés ailleurs sans violer de contrainte. C’est cette seconde condition qui bloque le plus souvent, silencieusement :
- Un PodDisruptionBudget trop strict (
minAvailableégal au nombre de replicas, par exemple) interdit toute éviction, donc tout drain du nœud qui les héberge. - Un pod géré par aucun contrôleur (créé directement, sans Deployment ni ReplicaSet derrière) n’a aucune garantie de recréation ailleurs ; le Cluster Autoscaler refuse de l’évincer par défaut.
- Un volume local ou un
emptyDiravec des données jugées importantes rend le pod non déplaçable sans perte, sauf annotation explicite acceptant l’éviction. - Des règles d’anti-affinité restrictives peuvent rendre un pod replaçable nulle part ailleurs que sur son nœud actuel, ce qui bloque son retrait indéfiniment.
# Voir pourquoi un nœud précis n'est pas retiré : le statut détaillé
# du Cluster Autoscaler liste les raisons, nœud par nœud.
kubectl -n kube-system get configmap cluster-autoscaler-status -o yaml
L’annotation qu’on oublie
Un pod qui tourne seul, sans contrôleur, ou un DaemonSet-like maison, peut débloquer explicitement son éviction :
metadata:
annotations:
cluster-autoscaler.kubernetes.io/safe-to-evict: "true"
À l’inverse, un pod dont l’éviction serait dangereuse (une tâche de migration en cours, par exemple) peut la refuser explicitement avec la même annotation à "false" : c’est plus sûr que de compter sur l’absence de contrôleur pour produire le même effet par accident.
Plusieurs groupes de nœuds : l’expander
Avec plusieurs groupes de nœuds éligibles (types d’instances différents, zones différentes), le Cluster Autoscaler doit choisir lequel agrandir. La stratégie par défaut (random) ne reflète aucune priorité métier ; l’expander priority permet de définir un ordre explicite par expression régulière sur le nom des groupes, utile pour préférer un pool de nœuds moins coûteux avant de basculer sur un pool de secours.
À retenir
Le scale up du Cluster Autoscaler dépend des mêmes requests honnêtes que le HPA. Le scale down dépend d’une condition bien plus fragile : que chaque pod du nœud puisse être replacé ailleurs sans violer un PDB, une contrainte d’affinité ou une garantie de contrôleur. Un nœud qui refuse de partir n’est presque jamais un bug du contrôleur : c’est une contrainte posée ailleurs qui fait exactement son travail. Poser ce socle correctement fait partie de ce qui se joue dès la migration Kubernetes.