PodSecurityPolicy a disparu de Kubernetes en 2022, avec la version 1.25. Quatre ans plus tard, beaucoup de clusters tournent encore avec des pods capables de monter le système de fichiers de l’hôte ou de lancer des conteneurs en mode privilégié, simplement parce que personne n’a repris le relais. Pod Security Admission est le mécanisme natif qui a remplacé PodSecurityPolicy : il impose trois niveaux de restriction (Privileged, Baseline, Restricted) directement au niveau du namespace, sans contrôleur tiers à installer. Au 5 octobre 2026, les branches supportées sont Kubernetes 1.35.9 et 1.34.12, publiées le 15 septembre 2026. La branche 1.34 est entrée en maintenance le 27 août 2026 et atteindra sa fin de vie le 27 octobre 2026, ce qui en fait un bon moment pour migrer vers des politiques de sécurité modernes avant de passer à une version plus récente. Ce tutoriel détaille, en douze étapes, comment activer, tester puis appliquer Pod Security Admission sur un cluster réel, avec les pièges à éviter et les erreurs les plus fréquentes côté GKE, EKS et AKS.

Pourquoi cette politique compte en 2026

Un cluster Kubernetes mal configuré ne fait pas la une des médias de la même façon qu’une fuite de base de données, mais le chemin d’attaque est souvent plus court. Un conteneur privilégié combiné à un montage hostPath suffit, dans beaucoup de cas documentés par la communauté sécurité, à sortir du conteneur et à atteindre le nœud lui-même, puis à pivoter vers d’autres pods du même cluster. La fiche OWASP consacrée à la sécurité Kubernetes classe d’ailleurs le durcissement des pods parmi les premières lignes de défense, avant même les politiques réseau ou la supervision runtime.

Pod Security Admission a l’avantage d’être gratuit, déjà présent dans le binaire kube-apiserver et activable en quelques labels, sans opérateur tiers à maintenir. C’est aussi un point d’entrée naturel si votre organisation doit répondre à des exigences de traçabilité et de durcissement des conteneurs, un sujet que nous détaillons par ailleurs dans notre couverture du Cyber Resilience Act et du référentiel C5:2026 appliqués aux conteneurs. Ce tutoriel se concentre uniquement sur la mécanique technique de Pod Security Admission : les labels, les modes, les profils et les pièges à éviter en production.

Autre avantage pratique : contrairement à un admission webhook externe, Pod Security Admission reste disponible même si un composant tiers du cluster tombe en panne, puisqu’il fait partie du cœur de l’API server. Une équipe qui a déjà investi dans Kyverno ou dans Open Policy Agent pour des règles plus complexes peut conserver ces outils pour des contrôles métier spécifiques, tout en gardant Pod Security Admission comme filet de sécurité minimal qui continue de fonctionner même si le webhook tiers devient indisponible ou mal configuré après une mise à jour.

Prérequis : versions et outils nécessaires

Avant de commencer, vérifiez que votre environnement correspond à ces versions. Pod Security Admission est stable depuis Kubernetes 1.25, mais certains comportements liés aux exceptions ont évolué dans les versions plus récentes. Si vous gérez plusieurs clusters avec des versions hétérogènes, testez d’abord sur celui qui tourne la version la plus ancienne de votre parc: c’est généralement là que vous trouverez le plus de workloads non conformes à corriger avant de généraliser la démarche.

  • Un cluster Kubernetes en version 1.34.12, 1.35.9 ou ultérieure (kind, minikube, GKE, EKS ou AKS)
  • kubectl en version alignée avec le cluster (1.34.x ou 1.35.x)
  • Des droits cluster-admin pour modifier les labels de namespace et la configuration d’admission
  • Un éditeur YAML et un terminal avec accès au contexte du cluster cible
  • Optionnel : conftest ou kubeconform pour valider les manifestes en CI/CD (étape 12)
  • Environ 70 minutes pour suivre l’intégralité des douze étapes

Étape 1 : vérifier la version et les prérequis de votre cluster

Pod Security Admission fonctionne comme un contrôleur d’admission intégré à l’API server. Rien à installer, mais il faut confirmer que votre cluster l’expose bien et que la version est compatible.

kubectl version --short
kubectl api-versions | grep admissionregistration
kubectl get --raw /healthz

Si votre cluster tourne encore sur Kubernetes 1.24 ou une version antérieure, Pod Security Admission n’existe pas encore sous sa forme stable et vous dépendez probablement de PodSecurityPolicy, déjà retiré du code source depuis 1.25. Dans ce cas, planifiez d’abord la montée de version avant de poursuivre ce tutoriel, sous peine de casser des workloads en production. La documentation officielle des releases de patch Kubernetes vous donne la liste à jour des versions encore supportées: au 5 octobre 2026, seules les branches 1.34 et 1.35 reçoivent des correctifs, la 1.34 étant en fin de vie programmée pour le 27 octobre 2026.

Vérifiez aussi que le plugin d’admission PodSecurity figure bien dans la liste des admission controllers actifs. Sur un cluster standard il est activé par défaut, mais certaines distributions personnalisées ou certains clusters fortement allégés (edge, IoT) le désactivent pour gagner en performances au démarrage.

Étape 2 : choisir le profil cible (Privileged, Baseline, Restricted)

Les Pod Security Standards définissent trois profils cumulatifs. Le choix du profil dépend du type de charge applicative que vous hébergez dans le namespace concerné.

ProfilNiveau de restrictionCas d’usage typique
PrivilegedAucune restrictionComposants système, CNI, agents de nœud
BaselineBloque les escalades de privilèges connuesApplications métier classiques, compatibilité large
RestrictedDurcissement maximal (non-root, capabilities réduites, seccomp)Charges exposées sur Internet, environnements sensibles

Pour la majorité des namespaces applicatifs d’une entreprise, Baseline constitue un point de départ raisonnable. Restricted demande souvent d’adapter les manifestes (utilisateur non-root, capabilities Linux retirées) avant de pouvoir l’activer sans casser les déploiements existants. La définition exacte de chaque profil, avec la liste complète des champs du securityContext qu’il autorise ou interdit, vit dans la page officielle des Pod Security Standards, qui sert de référence à toute la communauté Kubernetes et qu’il vaut mieux garder sous la main pendant la migration.

Dans la pratique, le profil Restricted impose cinq contraintes principales: interdiction d’allowPrivilegeEscalation, obligation de retirer toutes les capabilities Linux puis d’ajouter uniquement celles strictement nécessaires (NET_BIND_SERVICE par exemple), obligation de tourner avec un utilisateur non-root, un profil seccomp obligatoire (RuntimeDefault ou personnalisé) et l’interdiction des volumes de type hostPath. Ce sont précisément ces cinq points que vous retrouverez corrigés dans le manifeste de l’étape 8.

Étape 3 : choisir le mode d’application (enforce, audit, warn)

Chaque profil peut être combiné avec trois modes distincts, appliqués indépendamment les uns des autres sur un même namespace.

  • enforce : refuse la création du pod s’il ne respecte pas le profil
  • audit : autorise le pod mais ajoute une entrée dans les journaux d’audit de l’API server
  • warn : autorise le pod et renvoie un avertissement visible dans la sortie de kubectl

La bonne pratique consiste à activer d’abord warn et audit sur le profil restricted, observer les violations pendant quelques jours, corriger les manifestes, puis seulement ensuite basculer en enforce. C’est exactement la séquence suivie dans les étapes suivantes. Beaucoup d’équipes découvrent, en lisant la documentation du contrôleur d’admission PodSecurity, qu’elles peuvent appliquer un mode différent selon le profil: rien n’empêche par exemple d’enforcer Baseline tout en gardant Restricted en simple warn, pour avancer par paliers sans tout bloquer d’un coup.

Étape 4 : créer un namespace de test dédié

Ne testez jamais directement sur un namespace de production. Créez un namespace isolé pour valider votre démarche sans impact. Ce réflexe paraît évident mais reste la cause la plus fréquente d’incident lors d’un déploiement de politique de sécurité: un label appliqué par erreur sur le mauvais namespace peut bloquer instantanément tous les déploiements d’une équipe entière, y compris ceux qui n’ont rien à voir avec le test en cours.

apiVersion: v1
kind: Namespace
metadata:
  name: psa-test
  labels:
    purpose: pod-security-admission-test
kubectl apply -f namespace.yaml
kubectl get namespace psa-test --show-labels

Étape 5 : activer warn et audit sur le profil restricted

Les labels de Pod Security Admission se posent directement sur le namespace, au format pod-security.kubernetes.io/<mode>. Vous pouvez fixer une version de profil explicite pour éviter qu’une mise à jour du cluster ne change silencieusement le comportement.

kubectl label --overwrite ns psa-test \
  pod-security.kubernetes.io/warn=restricted \
  pod-security.kubernetes.io/warn-version=latest \
  pod-security.kubernetes.io/audit=restricted \
  pod-security.kubernetes.io/audit-version=latest

À ce stade, aucun pod n’est encore bloqué. Vous collectez simplement de l’information sur ce qui casserait si vous passiez en enforce. Laissez cette configuration tourner quelques jours sur un namespace qui reçoit un trafic de déploiement représentatif: un cycle de CI/CD complet, avec ses rollouts et ses rollbacks, révèle souvent des violations qu’un simple test ponctuel ne montre jamais, notamment sur les CronJobs ou les Jobs ponctuels qui ne tournent qu’à certaines heures.

Étape 6 : déployer un pod non conforme pour observer les alertes

Déployez volontairement un pod qui viole le profil restricted, pour voir concrètement le retour que vous recevrez sur vos vraies applications.

apiVersion: v1
kind: Pod
metadata:
  name: demo-non-conforme
  namespace: psa-test
spec:
  containers:
  - name: app
    image: nginx:1.27
    securityContext:
      privileged: true
    volumeMounts:
    - name: host-root
      mountPath: /host
  volumes:
  - name: host-root
    hostPath:
      path: /

Ce manifeste combine deux violations graves à la fois : un conteneur privilégié et un montage hostPath sur la racine du système de l’hôte. En production, ce genre de combinaison permet souvent de sortir du conteneur et d’atteindre le nœud lui-même. Gardez ce pod de démonstration dans un namespace isolé et supprimez-le dès que vous avez observé le comportement attendu, pour éviter qu’il ne traîne et ne soit confondu plus tard avec un vrai workload applicatif par un collègue qui ne connaît pas le contexte du test.

Étape 7 : lire les journaux d’audit et identifier les violations

En mode warn, kubectl affiche directement l’avertissement au moment de l’application du manifeste.

$ kubectl apply -f demo-non-conforme.yaml
Warning: would violate PodSecurity "restricted:latest": privileged (container "app" must not set
securityContext.privileged=true), hostPath volumes (volume "host-root" uses restricted volume type "hostPath")
pod/demo-non-conforme created

Le pod est créé malgré tout, puisque enforce n’est pas encore actif. En mode audit, la même violation apparaît dans les événements d’audit de l’API server plutôt que dans la sortie du terminal, ce qui permet de centraliser les alertes avec des outils de supervision déjà en place dans le cluster. C’est généralement cette source, plutôt que le message warn éphémère du terminal, que les équipes branchent sur leur pipeline d’alerting, puisque personne ne relit en continu la sortie de chaque commande kubectl exécutée par toute l’organisation.

Étape 8 : corriger les privilèges, le hostPath et l’exécution root

Pour satisfaire le profil restricted, un pod doit tourner sans privilèges, sans montage de volumes sensibles de l’hôte, avec un utilisateur non-root et des capabilities Linux réduites au strict nécessaire.

apiVersion: v1
kind: Pod
metadata:
  name: demo-conforme
  namespace: psa-test
spec:
  securityContext:
    runAsNonRoot: true
    runAsUser: 1000
    seccompProfile:
      type: RuntimeDefault
  containers:
  - name: app
    image: nginx:1.27
    securityContext:
      allowPrivilegeEscalation: false
      capabilities:
        drop: ["ALL"]
      readOnlyRootFilesystem: true

Ce manifeste corrigé passe sans aucun avertissement. Notez que certaines images Docker publiques ne fonctionnent pas sans privilèges d’écriture sur le système de fichiers racine, d’où l’intérêt de tester avant de généraliser le profil restricted à toute une flotte d’applications. La page officielle sur le security context des pods et conteneurs détaille chaque champ disponible, y compris des options moins connues comme seccompProfile.localhostProfile, utile quand le profil RuntimeDefault du moteur de conteneurs se révèle trop permissif ou au contraire trop strict pour une application spécifique.

Étape 9 : basculer le namespace en mode enforce

Une fois les violations corrigées et validées en warn/audit pendant quelques jours, activez enforce pour bloquer réellement les créations non conformes.

kubectl label --overwrite ns psa-test \
  pod-security.kubernetes.io/enforce=restricted \
  pod-security.kubernetes.io/enforce-version=latest
$ kubectl apply -f demo-non-conforme.yaml
Error from server (Forbidden): error when creating "demo-non-conforme.yaml":
pods "demo-non-conforme" is forbidden: violates PodSecurity "restricted:latest":
privileged (container "app" must not set securityContext.privileged=true)

Gardez warn et audit actifs en parallèle d’enforce. Ils continuent de fournir un historique utile quand une nouvelle application non conforme tente de se déployer plus tard. C’est aussi le moment de prévenir les équipes concernées avant d’activer enforce sur un namespace partagé: un déploiement qui échoue en pleine astreinte de nuit, sans que personne ne comprenne pourquoi, nuit plus à la crédibilité de la démarche qu’un blocage attendu et documenté en amont.

Étape 10 : gérer les exceptions avec des labels dédiés

Certaines charges légitimes, comme les agents de supervision réseau ou les CNI, ont besoin de privilèges étendus. Plutôt que de dégrader tout le namespace en Baseline, isolez ces workloads dans un namespace séparé avec son propre profil.

kubectl label --overwrite ns kube-system-agents \
  pod-security.kubernetes.io/enforce=privileged \
  pod-security.kubernetes.io/warn=baseline

Les exceptions au niveau de l’admission plugin (par utilisateur, groupe ou runtimeClass) existent aussi, mais elles se configurent dans le fichier de configuration de l’API server, ce qui est abordé à l’étape suivante. Évitez d’accorder une exception trop large: elle redevient alors un trou de sécurité équivalent à l’absence totale de politique. Une bonne règle consiste à limiter chaque exception à un seul compte de service précis, utilisé par un seul operator ou un seul DaemonSet identifié, plutôt qu’à un groupe entier qui regrouperait plusieurs usages différents sous le même nom.

Étape 11 : appliquer une politique par défaut à l’échelle du cluster

Sur un cluster self-managed (kubeadm, kOps), vous pouvez définir un profil par défaut appliqué à tous les namespaces non labellisés explicitement, via un fichier AdmissionConfiguration chargé par l’API server.

apiVersion: apiserver.config.k8s.io/v1
kind: AdmissionConfiguration
plugins:
- name: PodSecurity
  configuration:
    apiVersion: pod-security.admission.config.k8s.io/v1
    kind: PodSecurityConfiguration
    defaults:
      enforce: "baseline"
      enforce-version: "latest"
      audit: "restricted"
      warn: "restricted"
    exemptions:
      usernames: []
      runtimeClasses: []
      namespaces: ["kube-system"]

Référencez ce fichier via le flag --admission-control-config-file de kube-apiserver. Sur un cluster managé, cette étape n’est pas disponible directement et vous dépendez du comportement par défaut du fournisseur, détaillé plus bas. Sur un cluster kubeadm, le fichier se dépose généralement sur chaque nœud de plan de contrôle et nécessite un redémarrage du processus kube-apiserver pour être pris en compte: testez ce changement sur un cluster de staging avant de le répliquer sur la production, un fichier mal formé peut empêcher l’API server de redémarrer correctement.

Étape 12 : intégrer la validation dans votre pipeline CI/CD

Attendre le déploiement pour découvrir une violation coûte du temps. Validez les manifestes avant même qu’ils n’atteignent le cluster, directement dans la pipeline CI/CD.

# Étape de pipeline GitLab CI ou GitHub Actions
- name: Valider les manifestes contre Restricted
  run: |
    kubeconform -strict -summary manifests/*.yaml
    conftest test --policy policy/pod-security-restricted.rego manifests/*.yaml

Cette double vérification (schéma avec kubeconform, règles métier avec conftest/Open Policy Agent) évite qu’un manifeste non conforme n’arrive même jusqu’au namespace en mode enforce, et raccourcit la boucle de correction pour l’équipe qui a écrit le manifeste. Un développeur qui voit l’échec directement dans sa pull request, avec le champ exact à corriger, règle le problème en quelques minutes. Le même développeur qui découvre l’erreur après un déploiement raté en environnement partagé perd souvent une bonne partie de sa journée à comprendre ce qui bloque.

Centraliser les alertes à l’échelle d’un cluster complet

Sur un cluster avec plusieurs centaines de pods, lire les événements d’audit namespace par namespace devient vite impraticable. Si votre cluster expose déjà ses logs d’audit vers un système de collecte (Loki, Elasticsearch, Cloud Logging), filtrez directement sur la chaîne caractéristique renvoyée par le contrôleur PodSecurity.

kubectl get events --all-namespaces \
  --field-selector reason=FailedCreate \
  -o json | jq '.items[] | select(.message | contains("PodSecurity"))'

Cette commande isole les tentatives de création de pods bloquées spécifiquement par Pod Security Admission, ce qui évite de les noyer parmi les autres échecs d’admission (quotas de ressources, politiques réseau, webhooks personnalisés). Branchez ce filtre sur une alerte Slack ou e-mail plutôt que de compter sur une consultation manuelle régulière: les violations apparaissent souvent au moment d’un déploiement que personne ne surveille activement, par exemple un vendredi en fin de journée. Sur GKE et AKS, les mêmes événements remontent aussi dans Cloud Logging ou dans Azure Monitor, ce qui permet de construire un tableau de bord unique si votre organisation gère déjà plusieurs clusters répartis entre fournisseurs différents.

Pod Security Admission chez GKE, EKS et AKS

Le comportement par défaut diffère sensiblement selon le fournisseur managé que vous utilisez, ce qui change directement le travail à prévoir pour sécuriser un cluster neuf. Avant de reproduire ce tutoriel sur un cluster de production, vérifiez lequel des trois scénarios suivants correspond à votre environnement, les étapes à mener ne sont pas les mêmes selon que votre fournisseur impose déjà un socle ou non.

GKE Autopilot

Sur GKE Autopilot, Google applique une politique d’admission gérée qui reprend le profil Baseline et une grande partie des contrôles du profil Restricted. Le profil Privileged n’est tout simplement pas utilisable sur Autopilot : les conteneurs privilégiés, le réseau de l’hôte et les montages hostPath sont rejetés par défaut, et les profils seccomp sont imposés automatiquement, selon la documentation officielle de Google Cloud sur PodSecurity. Si vous migrez une charge applicative existante vers Autopilot, le travail des étapes 6 à 8 reste pertinent: vous devez quand même corriger les manifestes, Google se charge seulement d’empêcher qu’un manifeste non corrigé passe en production.

Amazon EKS

Un cluster EKS créé sans configuration additionnelle n’impose aucun profil Pod Security par défaut, ce qui signifie que les pods privilégiés restent possibles jusqu’à ce que vous labellisiez vous-même les namespaces ou que vous déployiez un admission controller tiers. Ne partez jamais du principe qu’un cluster EKS neuf est durci dès sa création. Les douze étapes de ce tutoriel s’appliquent donc telles quelles sur EKS, y compris l’étape 11 si vous gérez le plan de contrôle vous-même via EKS Anywhere, ou uniquement les étapes de namespace si vous utilisez le service managé standard, qui ne donne pas accès à la configuration de l’API server.

Azure AKS

AKS suit une logique proche d’EKS : il n’offre pas d’équivalent au palier de restriction imposé par défaut sur GKE Autopilot. Azure Policy pour Kubernetes permet d’appliquer des contraintes supplémentaires, mais cela reste une étape à activer explicitement plutôt qu’un comportement natif du cluster. Le travail décrit dans ce tutoriel reste donc nécessaire sur AKS comme sur EKS. Si votre organisation utilise déjà Azure Policy pour d’autres besoins de conformité, vous pouvez superposer ses contraintes à celles de Pod Security Admission plutôt que de choisir l’un ou l’autre: les deux mécanismes s’exécutent indépendamment au moment de l’admission et ne se contredisent pas tant que les règles ne portent pas sur exactement le même champ du manifeste.

FournisseurProfil par défautAction nécessaire côté équipe
GKE AutopilotBaseline + contrôles Restricted, Privileged indisponibleVérifier la conformité des images existantes
Amazon EKSAucun profil imposé (Privileged possible)Labelliser chaque namespace manuellement
Azure AKSAucun profil imposé par défautActiver Azure Policy ou labelliser les namespaces
Cluster self-managed (kubeadm)Dépend de l’AdmissionConfigurationConfigurer un profil par défaut à l’étape 11

Aide-mémoire des labels Pod Security Admission

Avec trois modes et trois profils, il est facile de mélanger les labels au moment de les taper dans un terminal à 23h un vendredi. Ce tableau récapitule la syntaxe exacte attendue par l’API server, avec le nom complet du label, les valeurs qu’il accepte et son effet concret sur les pods du namespace concerné.

LabelValeurs possiblesEffet
pod-security.kubernetes.io/enforceprivileged, baseline, restrictedBloque la création d’un pod non conforme
pod-security.kubernetes.io/auditprivileged, baseline, restrictedJournalise la violation dans l’audit log
pod-security.kubernetes.io/warnprivileged, baseline, restrictedAffiche un avertissement côté kubectl
pod-security.kubernetes.io/enforce-versionlatest ou numéro de version (ex: v1.34)Fige la version du profil appliqué

Fixer une version plutôt que d’utiliser systématiquement latest présente un compromis: vous gagnez en prévisibilité (aucune surprise après une mise à niveau du cluster), mais vous devez mettre à jour ce label manuellement pour profiter des nouvelles restrictions ajoutées aux versions suivantes des Pod Security Standards. Beaucoup d’équipes choisissent latest en développement et une version figée en production, avec une revue planifiée à chaque montée de version majeure du cluster.

Erreurs fréquentes à éviter

  • Passer directement en enforce sans phase warn/audit : vous découvrez les pods cassés au moment du déploiement en production, pas avant.
  • Appliquer Restricted à tout le cluster d’un coup : certains workloads systèmes (CNI, agents de nœud) ont réellement besoin de privilèges étendus et ne doivent pas être forcés dans ce profil.
  • Oublier le suffixe de version du label : sans -version=latest ou une version fixe, le comportement du profil peut changer après une mise à niveau du cluster sans que personne ne s’en rende compte.
  • Confondre Pod Security Admission et un scanner d’image : Pod Security Admission contrôle la configuration du pod au moment de sa création, pas le contenu de l’image ni ses vulnérabilités logicielles.
  • Accorder des exceptions par nom d’utilisateur trop larges : une exemption donnée à un compte de service partagé par plusieurs pipelines revient à désactiver la politique pour tout le monde.
  • Ignorer les clusters managés en pensant qu’ils sont durcis par défaut : seul GKE Autopilot impose un socle restrictif nativement, EKS et AKS demandent une configuration explicite.
  • Ne tester qu’avec des pods statiques : les violations les plus coûteuses à découvrir tard apparaissent souvent sur des Jobs, CronJobs ou Helm hooks qui ne se déclenchent qu’à intervalles longs, bien après la fin de la phase de test initiale.

Ces erreurs reviennent régulièrement parce que Pod Security Admission paraît simple à activer au premier regard. La difficulté ne vient pas de la syntaxe des labels, mais de la séquence à respecter et de la communication avec les équipes qui possèdent les workloads concernés. Gardez une trace écrite de chaque namespace déjà migré, avec la date du passage en enforce, pour pouvoir répondre rapidement si une équipe demande pourquoi son déploiement a échoué un mois après le changement, une fois que le contexte initial s’est estompé dans les esprits.

Dépannage : problèmes courants et solutions

Voici les neuf situations qui reviennent le plus souvent sur les forums et dans les tickets de support, avec la cause réelle derrière chaque symptôme.

  • Le pod reste créé malgré une violation visible : vérifiez que le label porte bien sur enforce et non uniquement sur warn ou audit.
  • Erreur “is forbidden: violates PodSecurity” inattendue sur un Deployment existant : le ReplicaSet tente de recréer un pod non conforme après l’activation d’enforce, corrigez le template du Deployment, pas seulement le pod en cours.
  • Les labels de namespace n’ont aucun effet : confirmez que l’admission plugin PodSecurity est bien activé sur l’API server (actif par défaut depuis la 1.25, mais parfois désactivé sur certaines distributions personnalisées).
  • Un init container passe mais le conteneur principal est bloqué : chaque conteneur du pod, y compris les init containers et sidecars, doit individuellement respecter le profil, vérifiez chacun séparément.
  • Le mode warn n’affiche rien dans les logs : les avertissements apparaissent dans la sortie de kubectl au moment de la requête, pas dans les logs du pod lui-même, utilisez audit pour une trace persistante côté API server.
  • Un Helm chart tiers échoue systématiquement en Restricted : de nombreux charts publics supposent encore un accès root par défaut, surchargez les valeurs securityContext dans votre fichier values.yaml plutôt que de modifier le chart lui-même. Si le chart ne propose aucune valeur pour ce champ, ouvrez une issue sur son dépôt plutôt que de forker silencieusement le chart, d’autres utilisateurs rencontreront le même problème après vous.
  • readOnlyRootFilesystem casse une application qui écrit des fichiers temporaires : montez un volume emptyDir dédié au répertoire d’écriture plutôt que de désactiver la restriction. Les frameworks Java et Node.js qui écrivent des caches ou des fichiers de session dans leur répertoire d’installation sont les cas les plus fréquents, un simple volume monté sur /tmp ou sur le répertoire de cache de l’application règle la grande majorité des cas.
  • Un job CronJob échoue uniquement après la montée en enforce : les CronJobs créent de nouveaux pods à chaque exécution, la vérification s’applique donc aussi, testez une exécution manuelle avec kubectl create job --from=cronjob avant d’attendre le prochain déclenchement planifié.
  • Un operator personnalisé génère des pods non conformes : certains operators codent en dur un securityContext privilégié, vérifiez la documentation de l’operator pour une option de configuration équivalente avant de créer une exception permanente.

Astuces avancées pour les clusters en production

Une fois les douze étapes maîtrisées sur un cluster de test, quelques pratiques supplémentaires aident à tenir cette politique sur la durée, sans qu’elle ne se dégrade au fil des déploiements. Le piège classique après une migration réussie est de considérer le sujet comme clos: de nouveaux workloads arrivent en continu, écrits par des équipes qui n’ont pas suivi la montée en compétence initiale, et la dérive recommence discrètement si personne ne surveille les exceptions accordées au fil du temps.

  • Combinez Pod Security Admission avec un moteur de policy-as-code comme Kyverno pour des règles plus fines que les trois profils standards (notre article sur les six CVE récentes de Kyverno détaille les limites à connaître sur ce type d’outil).
  • Ajoutez une alerte Prometheus basée sur les événements d’audit PodSecurity pour être notifié dès qu’un nouveau workload génère une violation, plutôt que de dépendre d’une revue manuelle périodique.
  • Documentez chaque exception dans un registre central (fichier versionné ou wiki interne), avec la justification métier et une date de revue, pour éviter l’accumulation d’exceptions oubliées.
  • Associez Pod Security Admission à une politique réseau stricte : une politique d’admission ne remplace pas un filtrage réseau, les deux se complètent (voir notre tutoriel sur Cilium et le Zero Trust réseau sur Kubernetes).
  • Surveillez le comportement réel des conteneurs en exécution avec un outil de détection runtime, car Pod Security Admission contrôle la configuration déclarée, pas ce qui se passe réellement une fois le pod démarré (notre guide sur Falco en douze étapes couvre cette couche complémentaire).
  • Planifiez une revue trimestrielle des namespaces encore en Baseline, pour identifier ceux qui pourraient raisonnablement passer en Restricted sans effort de migration disproportionné par rapport au gain de sécurité obtenu.

Projet complet : la stack prête à l’emploi

Pour reproduire l’ensemble de ce tutoriel rapidement sur un nouveau cluster, voici la structure de fichiers minimale à conserver dans votre dépôt Git, avec le fichier kustomization qui les assemble. L’intérêt de versionner ces fichiers plutôt que de taper les commandes kubectl à la main est double: vous obtenez un historique Git de chaque changement de politique, et vous pouvez rejouer exactement la même configuration sur un cluster de secours en cas d’incident, sans dépendre de la mémoire de la personne qui a fait la configuration initiale.

psa-project/
├── namespace.yaml            # Namespace avec labels warn/audit/enforce
├── deployment-conforme.yaml  # Deployment respectant le profil restricted
├── admission-config.yaml     # Profil par défaut cluster-wide (étape 11)
├── policy/
│   └── pod-security-restricted.rego  # Règle conftest pour la CI
└── kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: psa-test
resources:
  - namespace.yaml
  - deployment-conforme.yaml

Appliquez ce projet avec kubectl apply -k psa-project/, puis enchaînez avec la commande de validation CI de l’étape 12 avant chaque fusion de pull request. Cette base reste volontairement minimale : elle complète utilement les pratiques déjà couvertes dans notre article sur la gestion des secrets Kubernetes et dans notre guide de durcissement de containerd, deux chantiers connexes à mener en parallèle de Pod Security Admission. Pour la vue d’ensemble des sujets liés au cloud sur le site, consultez notre rubrique cloud.

FAQ

Pod Security Admission remplace-t-il complètement PodSecurityPolicy ?

Fonctionnellement, Pod Security Admission couvre le même objectif avec un modèle plus simple à trois profils fixes, contre un système de règles personnalisables dans PodSecurityPolicy. Il ne reproduit pas chaque option fine de l’ancien système, mais il suffit pour la grande majorité des cas d’usage et c’est la seule option supportée en amont depuis la version 1.25. Pour les besoins qui dépassent les trois profils standards, la communauté recommande généralement de superposer un moteur de policy-as-code comme Kyverno ou Open Policy Agent Gatekeeper, plutôt que d’espérer le retour d’un système équivalent à PodSecurityPolicy dans une future version de Kubernetes.

Peut-on appliquer des profils différents par namespace ?

Oui, c’est même le fonctionnement par défaut. Chaque namespace porte ses propres labels enforce, audit et warn, totalement indépendants des autres namespaces du cluster.

Pod Security Admission bloque-t-il les images vulnérables ?

Non. Il contrôle uniquement la configuration du pod (privilèges, utilisateur, capabilities, volumes) et ne vérifie pas le contenu de l’image. Pour détecter des vulnérabilités logicielles dans vos images, combinez-le avec un scanner dédié.

Que se passe-t-il si je ne mets aucun label sur un namespace ?

Le namespace suit le profil par défaut défini dans l’AdmissionConfiguration du cluster, ou le profil Privileged si aucune configuration par défaut n’a été définie. Sur la majorité des clusters self-managed sans configuration personnalisée, cela revient à n’imposer aucune restriction.

Faut-il viser Restricted partout dès le départ ?

Non. Mieux vaut généraliser Baseline rapidement sur l’ensemble des namespaces applicatifs, puis monter progressivement vers Restricted namespace par namespace, en commençant par les charges les plus exposées (ingress public, traitement de données sensibles). Cette approche par paliers réduit aussi la charge de travail ponctuelle sur l’équipe plateforme: migrer tout le cluster directement vers Restricted en une seule campagne mobilise généralement plusieurs semaines de corrections de manifestes en parallèle, pour un bénéfice de sécurité qui aurait pu être obtenu plus vite en commençant par Baseline partout.

GKE Autopilot dispense-t-il de suivre ce tutoriel ?

Pas entièrement. Autopilot impose un socle restrictif par défaut, mais vous devez tout de même adapter vos propres manifestes pour qu’ils passent ce socle, et vous gardez l’intérêt de la phase warn/audit pour anticiper les blocages avant un déploiement.

Les exceptions d’admission ralentissent-elles l’API server ?

L’impact en performance est négligeable comparé au volume de requêtes qu’un API server traite déjà. La vraie question n’est pas la performance mais la gouvernance : trop d’exceptions non documentées finissent par rendre la politique inutile.

Pod Security Admission fonctionne-t-il avec Helm ?

Oui, sans configuration particulière. Helm génère des manifestes Kubernetes classiques, qui passent par l’API server comme n’importe quel autre pod et se voient donc appliquer les mêmes labels de namespace. Le point d’attention porte sur les charts tiers, dont les valeurs par défaut datent parfois d’avant la généralisation de Restricted et nécessitent une surcharge explicite du securityContext dans votre fichier values.yaml.

Comment migrer un cluster de production sans interruption de service ?

Namespace par namespace, jamais en une seule opération sur tout le cluster. Commencez par les namespaces à plus faible trafic, gardez warn et audit actifs plusieurs jours avant chaque passage en enforce, et prévenez systématiquement l’équipe propriétaire du namespace avant de changer le mode. Cette approche progressive prend plus de temps qu’un changement global, mais elle évite l’incident de production qui pousse souvent une organisation à abandonner la démarche après une seule mauvaise expérience.