EN
en direct

Kubernetes programme la suppression de cgroup v1 en v1.38 et bloque le kubelet sur les nœuds cgroup v1 dès la v1.35

Kubernetes a déprécié cgroup v1 et prévoit sa suppression complète en v1.38 ; depuis la v1.35, le kubelet refuse de démarrer sur un nœud resté en cgroup v1. Si vos nœuds tournent encore sous cgroup v1, migrez-les vers cgroup v2 avant de monter en version, sinon le cluster refusera de démarrer.

Une rangée de tiroirs de serveur identiques dans une baie sombre, un tiroir extrait et vide.

6 octobre 2026. Kubernetes publie un guide de migration vers cgroup v2 signé Paco Xu de DaoCloud, et le message est sans ambiguïté : le support de cgroup v1 est déprécié, le kubelet refuse de démarrer sur un nœud cgroup v1 par défaut depuis la v1.35, et la suppression complète est programmée pour la v1.38. Pourquoi c’est important : beaucoup de nœuds tournent encore sous cgroup v1 sans le savoir, et la première montée de version en v1.35 ou plus se soldera par un échec au démarrage du kubelet.

Ce qui est déprécié, et à quelle échéance

Le calendrier est précis. cgroup v2 est stable dans Kubernetes depuis la v1.25, sortie en 2022, et cgroup v1 est passé en mode maintenance avec la v1.31. La dépréciation est actée : à partir de la v1.35, l’option failCgroupV1 vaut true par défaut, donc le kubelet ne démarre pas sur un nœud resté en cgroup v1. Un administrateur peut temporairement forcer failCgroupV1: false dans la configuration du kubelet, mais la suppression suivra la politique de dépréciation de Kubernetes.

Le travail de retrait est suivi dans KEP-5573 (« Remove cgroup v1 support »). La bascule de secours est programmée pour disparaître en v1.38. Concrètement : si vous êtes encore sur une version antérieure à v1.35, migrez chaque nœud Linux vers cgroup v2 avant de monter en version, ou prévoyez l’override failCgroupV1: false. Si vous êtes déjà en v1.35 ou plus, vérifiez que chaque nœud tourne bien sous cgroup v2 — ou assumez l’override. Pour les clusters gérés par kubeadm, la v1.35 durcit aussi le contrôle en amont : le preflight check SystemVerification renvoie une erreur pendant kubeadm init, kubeadm join et kubeadm upgrade quand il détecte cgroup v1 avec un kubelet v1.35 ou plus.

Pourquoi cgroup v1 ne suffit plus

Le guide énumère les limites concrètes de l’ancienne interface, qui motivent la migration au-delà de la seule dépréciation.

La plus insidieuse concerne la mémoire : le kubelet traite la mémoire active_file comme non récupérable. Pour des charges intensives en entrées-sorties, un gros cache de pages peut donc déclencher une pression mémoire et évincer des pods, même si la mémoire est en réalité récupérable. C’est le bug kubernetes/kubernetes#43916, et la migration vers cgroup v2 ne change pas ce calcul à elle seule : la parade documentée consiste à fixer des requests et limites mémoire égales pour les conteneurs qui font beaucoup d’I/O.

Surtout, cgroup v2 débloque des fonctions récentes que cgroup v1 ne peut pas fournir. Memory QoS, introduit en alpha en v1.22 et toujours alpha en v1.36, s’appuie sur le contrôleur mémoire de cgroup v2 : memory.high fournit l’étranglement, tandis que memory.min et memory.low assurent la protection dure et souple du mode tiered reservation. La gestion OOM par conteneur repose aussi sur v2 : par défaut, singleProcessOOMKill vaut false, et le kubelet fixe memory.oom.group pour tuer tous les processus d’un conteneur ensemble au lieu d’en laisser un partiellement fonctionnel. Enfin, cgroup v2 est la seule interface qui supporte officiellement la délégation aux conteneurs moins privilégiés — la base des conteneurs rootless.

Sur le plan structurel, la différence de fond est la hiérarchie unique. cgroup v1 empile des hiérarchies séparées par contrôleur, ce qui complique la délégation et rend la cohérence des limites plus difficile à auditer ; cgroup v2 unifie ces hiérarchies en une seule, plus simple à raisonner et à sécuriser. C’est cette propriété dont dépendent à la fois les conteneurs rootless et le contrôleur mémoire.

La généalogie de cgroup v2 dans le noyau

Le passage à v2 est aussi une affaire de version de noyau, et le guide détaille la chronologie. Quand Kubernetes a été annoncé en 2014, seul cgroup v1 existait. cgroup v2 est apparu dans le noyau Linux 4.5, sorti en 2016, avec les contrôleurs io, memory et pids. Le contrôleur cpu est arrivé en 4.15, et le PSI (Pressure Stall Information) à partir de 4.20. Le projet déconseille d’utiliser cgroup v2 avec un noyau antérieur à 5.2, faute de support du task freezer au niveau cgroup, et documente 5.8 comme minimum : c’est la version qui a ajouté le fichier cpu.stat du cgroup racine. La correction du livelock de memory.high, exploitée par Memory QoS, n’est présente qu’à partir de 5.9.

Cette chronologie explique pourquoi tant de nœuds restent en cgroup v1 : les distributions ont adopté v2 par défaut de façon progressive, et un serveur installé il y a plusieurs années peut très bien tourner encore en v1 sans que rien ne le signale. La commande stat -fc %T /sys/fs/cgroup/ est justement le moyen de lever l’ambiguïté en une seconde.

Ce que la migration exige

Les prérequis sont concrets et vérifiables. Il faut une version de Kubernetes avec support v2 (stable depuis la v1.25), un noyau Linux 5.8 minimum (5.9 recommandé pour Memory QoS), et un runtime conteneur compatible : containerd v1.4 au minimum, ou v2.0 pour la détection automatique du pilote cgroup ; CRI-O v1.20 au minimum. Le kubelet et le runtime doivent utiliser le même pilote cgroup.

Le guide recommande le pilote systemd quand le cluster est géré par kubeadm, puisque kubeadm gère le kubelet comme un service systemd. Depuis la v1.34, la détection automatique du pilote du runtime via le CRI (KEP-4033) est stable, à condition d’utiliser un runtime qui implémente le RPC RuntimeConfig (containerd v2.0+ ou CRI-O v1.28+).

Deux points d’attention méritent une note. Le premier : la conversion des poids CPU. cgroup v1 utilise cpu.shares, cgroup v2 utilise cpu.weight, et les runtimes récents appliquent une conversion non linéaire plus fidèle — disponible dans crun v1.23 et runc v1.3.2. Après une mise à jour du runtime, les outils de supervision qui prédisent les valeurs exactes de cpu.weight peuvent devoir être ajustés. Le second : le PSI (Pressure Stall Information), qui expose la contention CPU, mémoire et I/O par nœud, pod et conteneur, requiert cgroup v2, un noyau 4.20 ou plus et CONFIG_PSI=y. Le kubelet l’expose désormais par défaut (KubeletPSI est stable).

Le contrôle après migration

Pour vérifier l’état d’un nœud, une commande suffit : stat -fc %T /sys/fs/cgroup/ doit renvoyer cgroup2fs. Pour lister les unités système liées à Kubernetes, systemctl list-units "kube*" --type=slice puis systemd-cgls /sys/fs/cgroup/* montrent les hiérarchies effectives. Quand on trace un pod jusqu’à son cgroup, le guide rappelle un piège classique : avec le pilote systemd, la valeur info.runtimeSpec.linux.cgroupsPath est un chemin d’unité systemd (slice:runtime:id), pas un répertoire sous /sys/fs/cgroup — ne pas la traiter comme un chemin de système de fichiers.

Le flux complet pour confirmer qu’une limite est bien appliquée tient en quelques commandes :

bash
# 1. Le nœud est-il bien en cgroup v2 ?
stat -fc %T /sys/fs/cgroup/          # doit afficher « cgroup2fs »

# 2. Retrouver le cgroup d’un conteneur précis (pilote systemd)
CONTAINER_ID=$(crictl ps \
  --label io.kubernetes.pod.namespace=<ns> \
  --label io.kubernetes.pod.name=<pod> \
  --name <conteneur> -q | head -n1)
PID=$(crictl inspect "$CONTAINER_ID" | jq -r '.info.pid')
CGROUP="/sys/fs/cgroup$(awk -F: '$1=="0"{print $3}' /proc/$PID/cgroup)"

# 3. Lire les valeurs effectives
cat "$CGROUP/cpu.weight"    # request CPU : shares convertis en weight
cat "$CGROUP/cpu.max"       # limit CPU
cat "$CGROUP/memory.max"    # limit mémoire

La lecture est directe : si cpu.weight ou memory.max ne correspondent pas à ce que le manifeste déclare, c’est soit une conversion runtime à revoir, soit un pod en cours de resize dont spec et status sont désynchronisés.

Verdict

Si vos nœuds sont encore sous cgroup v1, ne montez pas en version tant que la migration n’est pas faite : la v1.35 fera échouer le kubelet par défaut, et la v1.38 supprimera la bascule de secours. Le chemin est mécanique — noyau 5.8+, runtime à jour, pilote systemd, puis vérification stat -fc %T. Si vous êtes déjà en cgroup v2, profitez-en pour activer les fonctions que v2 débloque, à commencer par Memory QoS en tiered reservation si vos charges ont besoin d’une protection mémoire fine. Dans tous les cas, traitez la dépréciation comme une échéance de migration, pas comme un avertissement que l’on peut repousser indéfiniment.

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

Les pull requests empilées de GitHub passent en disponibilité générale avec 9 % de code fusionné en plus

GitHub annonce la disponibilité générale des pull requests empilées, qui découpent une grosse évolution en petites demandes revues indépendamment puis fusionnées ensemble. Si vos branches se bloquent les unes les autres, les chiffres de GitHub — 9 % de code fusionné en plus, 5 % de délai de fusion en moins — justifient de les adopter dès maintenant.

← Retour au fil

Tapez au moins deux caractères.

↑ ↓ naviguer ↵ ouvrir esc fermer