EN
en direct

Memory QoS passe en bêta et devient actif par défaut dans Kubernetes 1.37

La fonctionnalité Memory QoS de Kubernetes, qui guide le noyau Linux dans la gestion de la mémoire des conteneurs via cgroup v2, passe en bêta et s’active par défaut dans la version 1.37. Le changement clé est ailleurs : le facteur de throttling implicite disparaît, ce qui rend la mise à niveau sans surprise pour les clusters existants.

Une vanne ambre sur une canalisation sombre au milieu d’un rack de serveurs, la jauge partiellement fermée.

Kubernetes 1.22. Memory QoS apparaît en alpha. Kubernetes 1.36. La fonctionnalité s’enrichit d’une réservation de mémoire par paliers. Kubernetes 1.37. Elle passe en bêta et s’active par défaut sur tous les nœuds. Pourquoi c’est important : la gestion de la mémoire est la cause première des OOM kills et de l’instabilité des nœuds, et Kubernetes vient de changer la façon dont il la pilote — sans pour autant changer le comportement de vos clusters au moment de la mise à niveau.

Ce que fait réellement Memory QoS

Memory QoS s’appuie sur le contrôleur mémoire de cgroup v2, disponible uniquement sur les nœuds Linux qui l’utilisent. Son principe : donner au noyau de meilleures indications sur la façon de traiter la mémoire de chaque conteneur, au-delà des seules limites déclarées dans les objets Pod. Concrètement, il écrit trois valeurs dans les cgroups :

  • memory.high, qui déclenche un throttling — le noyau ralentit le conteneur pour l’inciter à libérer de la mémoire avant d’atteindre la limite dure ;
  • memory.min, une protection ferme : cette quantité de mémoire n’est jamais récupérée, même sous pression ;
  • memory.low, une protection souple : la mémoire est récupérable tant que le reste du système ne réclame pas plus.

L’objectif est de remplacer le tout-ou-rien du OOM kill par une gradation : ralentir d’abord, protéger les workloads critiques, et ne tuer qu’en dernier recours.

Un point d’attention pour l’adoption : Memory QoS ne fonctionne que sous cgroup v2. Les clusters encore en cgroup v1 — une minorité en déclin, mais encore présente dans certains parcs historiques — n’en bénéficient pas. La migration vers cgroup v2 est un prérequis, et elle n’est pas anodine sur des nœuds anciens : c’est un projet de plateforme à planifier, pas une bascule à chaud.

Trois classes de QoS, trois traitements

Pour comprendre ce que Memory QoS change, il faut repartir des trois classes de QoS définies par Kubernetes :

  • Guaranteed : chaque conteneur déclare une requête et une limite mémoire égales. C’est la classe des workloads critiques, celle qu’on veut protéger en priorité.
  • Burstable : requête inférieure à la limite. Le pod peut dépasser sa requête tant que le nœud a de la marge.
  • BestEffort : aucune requête ni limite. Premier candidat au OOM kill en cas de pression.

Memory QoS joue sur ces classes : le throttling memory.high ne s’applique qu’aux Burstable et BestEffort — les Guaranteed sont supposés avoir déjà payé leur réservation. La réservation par paliers, elle, protège les Guaranteed avec memory.min et les Burstable avec memory.low. Le résultat est une hiérarchie cohérente : les workloads garantis sont protégés, les burstables sont ralentis avant d’être tués, et les best-effort sont tués en premier.

Le changement qui compte : memoryThrottlingFactor passe à null

La promotion en bêta cache une décision de conception plus importante qu’elle n’en a l’air. En alpha, le champ memoryThrottlingFactor valait 0.9 par défaut : activer la feature gate suffisait à ce que le kubelet écrive memory.high sur les conteneurs. En 1.37, ce défaut devient null, ce qui signifie qu’aucun memory.high n’est écrit tant que vous ne le configurez pas explicitement.

La raison est pragmatique. Puisque la feature gate est désormais active par défaut, conserver un memory.high automatique aurait pu ralentir des workloads qui tournaient jusque-là sans throttling. Rendre la valeur nulle garantit que la mise à niveau vers 1.37 ne change pas le comportement au moment de la migration : c’est une mise à niveau sans surprise, un choix que les opérateurs de clusters apprécieront.

Si votre fichier de configuration kubelet contient déjà un memoryThrottlingFactor explicite, cette valeur est préservée et le throttling continue de fonctionner. Si le fichier n’en contient pas, le kubelet adopte le nouveau défaut null et cesse d’écrire memory.high. Pour conserver le throttling dans ce cas, il faut l’ajouter explicitement :

yaml
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
memoryThrottlingFactor: 0.9

Activer la throttling et la réservation par paliers

Memory QoS s’active par deux champs de configuration du kubelet, indépendants l’un de l’autre :

  • memoryThrottlingFactor (valeur entre 0 et 1) : active le throttling memory.high sur les conteneurs Burstable et BestEffort. Le kubelet calcule memory.high à partir de ce facteur pour chaque classe de QoS.
  • memoryReservationPolicy (valeur TieredReservation) : active la protection par paliers via memory.min et memory.low. Par défaut, la valeur est None, donc aucune réservation n’est écrite.

Les deux peuvent être combinés ou utilisés séparément. Pour activer les deux :

yaml
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
memoryThrottlingFactor: 0.9
memoryReservationPolicy: TieredReservation

Pour activer la réservation sans throttling, il suffit de retirer le premier champ. Enfin, pour désactiver complètement Memory QoS après une mise à niveau, il faut passer la feature gate à false et retirer les champs de configuration, faute de quoi le kubelet rejette la configuration.

Ce que ça change pour l’observabilité

Le throttling memory.high a une conséquence visible dans les métriques : un conteneur ralenti consomme plus de CPU par unité de travail, et sa latence augmente avant même qu’un OOM kill ne survienne. C’est un signal précoce, plus utile qu’un kill brutal, mais il faut savoir le lire. Les équipes qui activent memoryThrottlingFactor doivent corréler la latence des applications avec les métriques cgroup (memory.high, memory.peak, memory.events) plutôt que de s’en tenir au seul compteur d’OOM kills. Sinon, le throttling apparaît comme une dégradation inexpliquée.

La limite connue : une politique à l’échelle du nœud

memoryReservationPolicy s’applique à tous les pods du nœud, sans exception possible. Avec TieredReservation, chaque pod Guaranteed reçoit memory.min et chaque pod Burstable reçoit memory.low. Il n’existe aucun moyen d’inclure ou d’exclure un pod individuel : un nœud qui mélange des workloads nécessitant une réservation ferme et des workloads qui doivent rester récupérables doit choisir une seule politique pour tous.

La réservation ferme couvre par ailleurs tout ce qui est facturé au cgroup du conteneur, y compris le page cache. Un pod qui lit de gros fichiers peut ainsi retenir de la mémoire que le noyau aurait autrement récupérée pour servir ses voisins. SIG Node suit ces deux limitations dans l’issue kubernetes/kubernetes#140246 — c’est l’endroit où décrire votre workload si vous êtes concerné.

Prenons un exemple concret. Un nœud héberge à la fois une base de données Guaranteed et des jobs de traitement par lots Burstable. Avec TieredReservation, la base est protégée par memory.min — c’est voulu. Mais si un job de lot lit de gros fichiers, son memory.low couvre aussi son page cache, qui reste donc résident tant que le système ne réclame pas davantage. Sur un nœud où les jobs de lot se succèdent, ce cache peut réduire la mémoire récupérable et accélérer la pression sur les BestEffort. Le réglage est correct, mais ses effets de bord se mesurent sur la durée.

Verdict

Memory QoS en bêta est une amélioration nette pour qui gère des clusters Linux sous cgroup v2 : le throttling et la réservation par paliers donnent au noyau des signaux que les seules limites de pod ne peuvent pas fournir.

Si vos nœuds subissent des OOM kills réguliers, activez d’abord memoryThrottlingFactor autour de 0.9 sur un nœud pilote et mesurez l’impact sur la latence avant de généraliser. Si vous exécutez un mélange de workloads critiques et récupérables sur les mêmes nœuds, testez TieredReservation en gardant à l’esprit sa granularité au nœud : elle protège bien les Guaranteed, mais elle protège aussi le page cache, ce qui peut surprendre sur des pods très lecteurs. Si vous mettez simplement à niveau, vous n’avez rien à faire : le défaut null garantit que rien ne change au moment du passage à 1.37.

Références

Le brief cyber, chaque mardi

Les failles qui comptent, les correctifs à appliquer, en dix minutes de lecture.

Pas de spam. Désinscription en un clic.
à lire ensuite

Sur le même sujet

La retraite d’ingress-nginx impose une migration vers Gateway API avant novembre 2026

Le 12 novembre 2025, Kubernetes a annoncé la retraite d’ingress-nginx ; la maintenance amont s’est arrêtée en mars 2026 et la dernière passerelle de correctifs, celle d’AKS, expire en novembre 2026. Chaque annotation de votre flotte doit désormais devenir une route Gateway API — ou rester une vulnérabilité sans correctif.

Les runners auto-hébergés GitHub Actions cessent de recevoir des jobs le 25 septembre

GitHub a durci l’application de la version minimale des runners auto-hébergés : des brownouts ont commencé le 14 septembre et, à partir du 25 septembre 2026, tout runner non mis à jour sous 30 jours ne reçoit plus aucun job. L’échec est silencieux — les jobs restent « Queued » sans erreur : auditez vos runners avant la prochaine fenêtre.

← Retour au fil

Tapez au moins deux caractères.

naviguer ouvrir esc fermer