Kubernetes v1.37 arrive le 26 August 2026, et avec lui SELinuxMount passe GA et actif par défaut. Concrètement : si tes nœuds tournent SELinux en mode enforcing et que tu as deux pods avec des niveaux SELinux différents qui partagent un même PersistentVolumeClaim sur un même nœud, l'un des deux ne démarre plus. Aucun manifeste n'a changé. Aucune image n'a changé. Le kubelet signale simplement des labels SELinux en conflit sur le volume, et le pod reste en ContainerCreating tant que son voisin ne s'en va pas. Ma position, avant toute chose : c'est le bon changement, et je préfère que tu prennes la casse sur un cluster de staging cette semaine plutôt que de basculer les workloads concernés en seLinuxChangePolicy: Recursive en considérant l'affaire réglée.
kubectl get csidrivers -o custom-columns='NAME:.metadata.name,SELINUX_MOUNT:.spec.seLinuxMount'La mécanique mérite dix secondes, parce qu'elle explique pourquoi il n'y a pas de demi-mesure. L'ancien chemin faisait parcourir le volume par le runtime de conteneurs, qui réétiquetait chaque inode au démarrage du pod, pour un coût proportionnel au nombre de fichiers, à repayer à chaque redémarrage. Quiconque a regardé un pod avec un gros PVC végéter en ContainerCreating sur un système de fichiers distant a probablement réglé cette facture sans en connaître le nom. Le nouveau chemin monte le volume avec une option context et laisse le noyau appliquer un seul label à tout le superbloc. Temps constant. Sauf qu'un superbloc porte exactement un contexte SELinux, donc monter deux fois le même système de fichiers avec deux contextes différents se fait refuser au niveau du noyau. Red Hat documente ce comportement depuis bien plus de dix ans. Kubernetes ne décide pas de te casser ici, il arrête juste de demander au noyau une chose que le noyau n'allait jamais accorder.
Voilà ce que je trouve intéressant, et ce n'est pas la tuyauterie de stockage. Le motif qui casse ne fonctionnait que parce que le réétiquetage était fichier par fichier. Le pod A réétiquetait le volume à son niveau, le pod B arrivait et écrasait les labels avec les siens, et les deux continuaient à lire. Personne n'a conçu ça. Ce n'est pas dans un KEP, ce n'est dans le registre de décisions d'architecture de personne, ça n'est simplement jamais tombé en panne. Si tu fais tourner du PHP sur Kubernetes avec un deployment php-fpm et un sidecar de sauvegarde ou d'expédition de logs qui monte la même claim sous un autre contexte de sécurité, tu t'appuies sur un effet de bord qui a survécu à l'implémentation qui le produisait. On connaît cette forme dans notre propre écosystème : chaque base de code a son endroit où quelque chose marche, et où la réponse honnête à la question pourquoi est que ça a toujours marché.
Le meilleur argument contre ma position n'est pas la nostalgie, ce sont deux choses concrètes. D'abord, les montages avec contexte refusent les changements de label fichier par fichier. Lance chcon dans un tel volume et tu récoltes Operation not supported, parce que le label n'a jamais été écrit sur disque au départ. Si une partie de ton workload gère elle-même ses labels de fichiers, Recursive n'est pas une manœuvre dilatoire pour toi, c'est la configuration correcte : mets-la et cesse de t'inquiéter. Ensuite, et c'est celui qui me dérange : la détection est aveugle d'une façon que personne n'a résolue. Kubernetes v1.36 livre un selinux-warning-controller que tu peux activer avec --controllers=*,selinux-warning-controller, et il émet selinux_warning_controller_selinux_volume_conflict avec les deux pods fautifs en labels. Associe-le au compteur kubelet volume_manager_selinux_volume_context_mismatch_warnings_total et tu sais quels pods sont en conflit maintenant. Maintenant, c'est justement le problème. Ni le contrôleur ni un scrape improvisé de l'API ne voit la paire qui n'entrera en collision qu'une fois que l'ordonnanceur les aura colocalisés mardi prochain.
J'en reste malgré tout à la mise à jour, pour une raison qui n'a rien à voir avec la latence de démarrage. C'est le réétiquetage récursif qui rendait CVE-2021-25741 exploitable sous la forme qu'il avait : tu piges le kubelet pour qu'il expose une portion du système de fichiers de l'hôte, et le runtime réétiquette obligeamment ces fichiers hôtes pour que ton pod puisse les lire. Sous un montage avec contexte, le pod est simplement refusé par la politique. C'est une propriété de sécurité que tu rends à chaque fois que tu saupoudres l'échappatoire sur un workload qui n'en avait pas besoin. Et il y a une conséquence désagréable : poser seLinuxChangePolicy: Recursive empêche aussi, par conception, le contrôleur d'alerte de signaler ce pod. Donc la métrique autour de laquelle tu as construit ton déploiement devient silencieuse pendant que le travail reporté reste exactement là où il était. Si tu exclus vraiment quelque chose, colle-lui une annotation et un numéro de ticket, parce que l'observabilité, elle, ne s'en souviendra pas pour toi.
La plupart d'entre vous liront tout ça et ne feront rien, à juste titre, et ça vaut la peine de le dire tout haut. Si /sys/fs/selinux/enforce n'existe pas sur tes nœuds, le kubelet saute tout ce chemin de code. Même avec SELinux en enforcing, seuls les volumes dont l'objet CSIDriver positionne .spec.seLinuxMount à true sont concernés, et côté in-tree cette liste se réduit à fc et iscsi. Les volumes emptyDir, configMap, secret et projected continuent d'être réétiquetés récursivement, donc ta config et tes credentials ne bougent pas. Le driver AWS EBS CSI illustre bien pourquoi deviner est mauvais dans les deux sens : son chart Helm ne rend seLinuxMount: true que si node.selinux est défini, si bien qu'une installation par défaut ne change rien pour les volumes EBS. Va regarder ton propre fichier values plutôt que de faire confiance à l'une ou l'autre moitié de cette phrase.
Ce qui continue de me tracasser, c'est qu'un audit à un instant T ne peut pas prouver qu'un cluster est sain, parce que la panne est fonction de l'ordonnancement, pas de ton YAML. Tu peux énumérer les conflits du jour en un seul appel kubectl et te faire quand même réveiller en novembre, quand un drain de nœud réunira deux pods pour la première fois. La politique d'admission est la réponse honnête, que ce soit MutatingAdmissionPolicy, un webhook ou Kyverno cadré aux namespaces qui partagent réellement des claims, mais c'est une politique que tu dois écrire avant de savoir quels workloads en ont besoin. Alors, collègues : comment prouverais-tu concrètement qu'un conflit dépendant de l'ordonnanceur ne peut pas se produire dans ton cluster, à part activer le feature gate sur staging et attendre ? Je n'ai pas trouvé de réponse à laquelle je fasse confiance, et j'aimerais bien te piquer la tienne.
Point de départ pratique si tu en veux un, en une commande : liste tes drivers et regarde lesquels ont opté pour le nouveau comportement. Tout le reste découle de cette réponse.
Commentaires
Pas encore de commentaire — écris le premier.
Lance la discussion
Pas de compte ni de mot de passe — saisis simplement ton adresse e-mail et nous t’envoyons un lien de connexion à usage unique. Première visite ? Tout se met en place automatiquement.
Ton évaluation sera appliquée automatiquement après ta connexion.
Vérifie ta boîte mail
Nous avons envoyé un lien de connexion à …. Ouvre-le sur cet appareil — cet onglet te connectera automatiquement.
Rien reçu ? Vérifiez le dossier spam — et marquez le message « Non spam » pour qu'il arrive directement la prochaine fois.