veilletech.fr
5 sept. Feed du jour
#07 DEVOPS Article

Kubernetes ne tourne plus en root sur l'hôte

Sortir du conteneur, et tomber sur un compte sans droits.

Kubernetes v1.37 promeut en bêta le feature gate KubeletInUserNamespace, dit mode rootless : kubelet, runtime CRI/OCI, plugins CNI et kube-proxy tournent tous sous un utilisateur non privilégié de l'hôte via un user namespace Linux. Les évasions de conteneur historiques — cr8escape sur CRI-O, deux failles runc, gitRepo sur le kubelet, containerd via labels d'image — donnaient root sur la machine ; elles se limiteraient désormais à un compte sans droits. Le gate est activé par défaut mais ne bascule rien seul.

3 min de lectureavancévidéo 1:20
Partager
Sommaire5 sections
  1. Ce qui se passe
  2. Pourquoi ça compte
  3. Comment ça marche
  4. Comment s'y prendre
  5. À retenir

Ce qui se passe

Kubernetes v1.37 fait passer le feature gate KubeletInUserNamespace en bêta. Activé, il permet à tous les composants du nœud — kubelet, runtimes CRI et OCI, plugins CNI, kube-proxy — de s'exécuter sous un utilisateur non root de l'hôte, dans un user namespace Linux. C'est ce qu'on appelle le mode rootless.

Le chemin a été long : expérimentation en 2018, alpha dans la v1.22 en 2021 sous KEP-2033, bêta cinq ans plus tard.

À ne pas confondre avec les user namespaces pour les pods (hostUsers: false, feature gate UserNamespacesSupport, GA depuis la v1.36), qui placent les pods dans un user namespace mais laissent les composants du nœud en root. Les deux ne s'opposent pas — ils se combinent, ce qui permet d'imbriquer un cluster dans un cluster sans recourir à privileged: true.

Pourquoi ça compte

Parce que les composants du nœud ont un historique d'évasions de conteneur qui donnaient root sur l'hôte :

CVE Composant Effet
CVE-2022-0811 (« cr8escape ») CRI-O sysctl arbitraires, dont kernel.core_pattern
CVE-2023-27561 runc contournement des masked paths par une course sur un montage
CVE-2024-10220 kubelet commandes arbitraires via les volumes gitRepo
CVE-2025-31133 runc bind-mount de chemins contrôlés, écriture dans le procfs de l'hôte
CVE-2026-53488 containerd commandes arbitraires via des labels d'image forgés

Dans un user namespace, le dégât reste confiné au compte non privilégié. L'attaquant ne peut notamment plus dissimuler son passage en modifiant le noyau, le chargeur de démarrage ou le micrologiciel.

Comment ça marche

Le noyau associe un utilisateur non root de l'hôte — disons l'UID 1000 — à un faux root à l'intérieur du namespace. Les privilèges de l'UID 0 s'arrêtent à la frontière. Ce faux root suffit à l'essentiel du travail des composants : monter des volumes, créer des cgroups, configurer les namespaces réseau des pods.

Le feature gate lui-même est, de l'aveu du billet, assez « ennuyeux » : il laisse le kubelet ignorer les erreurs de permission rencontrées en écrivant certains sysctl (vm.overcommit_memory, kernel.panic) et en lisant /dev/kmsg. Le user namespace, lui, se crée en dehors de Kubernetes — par exemple avec Docker rootless.

Ce qui change entre alpha et bêta :

Comment s'y prendre

Le chemin le plus court passe par kind sur un Docker rootless :

Terminal
dockerd-rootless-setuptool.sh install
kind create cluster

Selon l'hôte, des réglages supplémentaires peuvent être nécessaires du côté de systemd, des modules noyau ou des sysctl.

À retenir

  1. Un user namespace ne protège pas d'une faille du noyau lui-même. Il se combine avec seccomp pour restreindre les appels système, il ne le remplace pas.
  2. Certains pilotes CNI et CSI restent incompatibles — les caveats du KEP-2033 valent la lecture avant de généraliser.
  3. Un cas d'usage cité mérite l'attention au-delà des clusters de production : un compte local dédié pour faire tourner un agent de code IA et un cluster de test, précisément pour l'empêcher de casser l'hôte s'il se fait tromper par ce qu'il lit sur Internet.

Source : Kubernetes