Die Kubernetes Pod Security Standards legen in drei Stufen, Privileged, Baseline und Restricted, fest, welche Sicherheitseinstellungen ein Pod mitbringen muss, bevor Kubernetes ihn in einem Namespace überhaupt zulässt. Durchgesetzt werden diese Stufen über die Pod Security Admission, die jede Anfrage prüft, sobald ein passendes Label am Namespace hängt. Ohne diese Kontrolle kann ein einzelner falsch konfigurierter Pod weitreichenden Zugriff auf seine Node bekommen, ganz unabhängig davon, was RBAC ihm auf Ebene der Kubernetes-API erlaubt.
Ich betreibe produktionsreife Kubernetes-Cluster und habe Security Context und Admission ausführlich in meinem Kubernetes-Praxisbuch bei Rheinwerk beschrieben (2024). Diesen Beitrag findest du zusammen mit allen anderen Kubernetes-Themen auf meiner Seite Kubernetes.
Was Kubernetes Pod Security Standards regeln: die drei Stufen
Die drei Stufen der Pod Security Standards unterscheiden sich darin, wie viel Freiheit sie einem Pod lassen. Privileged ist die am wenigsten restriktive Stufe, sie erlaubt praktisch alles und eignet sich nur für System- und Infrastruktur-Workloads, die tatsächlich tiefen Zugriff auf die Node brauchen, etwa bestimmte Netzwerk- oder Storage-Komponenten. Baseline verhindert bekannte Wege zur Rechteausweitung, etwa privilegierte Container oder das Verändern von Host-Namespaces, lässt aber noch genug Spielraum für die meisten gewöhnlichen Anwendungen. Restricted geht am weitesten und verlangt unter anderem, dass ein Pod nicht als Root läuft und keine zusätzlichen Linux Capabilities beansprucht, orientiert an bewährter Praxis zur Härtung von Pods.
Wichtig ist, dass die Stufen aufeinander aufbauen: Jede strengere Stufe enthält alle Regeln der lockereren. Ein Pod, der Restricted erfüllt, erfüllt automatisch auch Baseline. Für dich als Betreiber bedeutet das: Du wählst pro Namespace eine Stufe, und jeder Pod darin muss diese Stufe einhalten, unabhängig davon, wie sorgfältig sein Team die Anwendung selbst geschrieben hat.
Security Context: die Stellschrauben je Pod und Container
Die Pod Security Standards greifen technisch über den Security Context, den du in jedem Pod-Manifest setzt. Auf Pod-Ebene bestimmst du unter anderem runAsNonRoot, das den Start als Root-Benutzer verbietet, runAsUser und runAsGroup für eine feste Benutzer- und Gruppen-ID, sowie fsGroup für die Dateiberechtigungen auf eingebundenen Volumes. Auf Container-Ebene kommen privileged für den privilegierten Modus, readOnlyRootFilesystem für ein schreibgeschütztes Root-Dateisystem, allowPrivilegeEscalation gegen das nachträgliche Erhöhen von Rechten und capabilities für einzelne Linux-Fähigkeiten hinzu, die du gezielt hinzufügen oder entziehen kannst.
Ein Pod, der die Restricted-Stufe erfüllt, sieht in der Praxis oft so aus:
apiVersion: v1
kind: Pod
metadata:
name: web-restricted
namespace: team-shop
spec:
securityContext:
runAsNonRoot: true
runAsUser: 10001
runAsGroup: 10001
seccompProfile:
type: RuntimeDefault
containers:
- name: web
image: nginxinc/nginx-unprivileged
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop: ["ALL"]
volumeMounts:
- name: tmp
mountPath: /tmp
- name: cache
mountPath: /var/cache/nginx
volumes:
- name: tmp
emptyDir: {}
- name: cache
emptyDir: {}
Der Pod läuft mit einer festen, nicht privilegierten Benutzer-ID, das Root-Dateisystem ist schreibgeschützt, Rechteausweitung ist verboten, und alle Linux Capabilities sind entfernt. Genau diese Kombination prüft die Restricted-Stufe der Pod Security Admission. Zwei ehrliche Hinweise dazu: Das Image muss von sich aus ohne Root auskommen, deshalb steht im Beispiel die unprivilegierte Nginx-Variante statt des Standard-Images. Und ein schreibgeschütztes Root-Dateisystem bringt Anwendungen zum Absturz, die zur Laufzeit ins eigene Verzeichnis schreiben wollen. Deshalb stehen im Manifest zwei emptyDir-Volumes: Nginx legt temporäre Dateien unter /tmp und seinen Cache unter /var/cache/nginx ab und würde ohne diese beiden Mounts sofort beim Start scheitern. Welche Pfade deine Anwendung braucht, findest du am schnellsten heraus, indem du sie einmal mit schreibgeschütztem Root startest und die Fehlermeldung liest.
Pod Security Admission: Standards an Namespaces durchsetzen
Die Pod Security Admission hat die frühere Pod Security Policy abgelöst, die als eigene Ressource im Cluster lag; den alten Namen findest du nur noch in älteren Dokumenten. Statt einer eigenen, komplexen Policy-Ressource reicht heute ein Label am Namespace, um eine der drei Stufen zu aktivieren:
apiVersion: v1
kind: Namespace
metadata:
name: team-shop
labels:
pod-security.kubernetes.io/enforce: baseline
pod-security.kubernetes.io/audit: restricted
pod-security.kubernetes.io/warn: restricted
Die drei Modi lassen sich unabhängig voneinander setzen. enforce lehnt Pods ab, die die angegebene Stufe verletzen, das ist die einzige Einstellung mit echter Durchsetzung. audit protokolliert Verstöße gegen eine strengere Stufe im Audit-Log, ohne den Pod zu blockieren. warn gibt bei kubectl apply eine Warnung an der Konsole aus, lässt den Pod aber ebenfalls laufen. Diese Kombination aus einem durchgesetzten enforce auf Baseline und einem beobachtenden audit beziehungsweise warn auf Restricted ist mein Standardvorgehen, um zu sehen, welche Pods heute schon restriktiver laufen könnten, ohne gleich etwas zu riskieren. Wie sich das zu Admission Controllern im Allgemeinen verhält, die auch andere Regeln als reine Pod Security durchsetzen können, beschreibe ich in Admission Controller und Policies.
Von Baseline zu Restricted: sicher migrieren ohne Ausfall
Eine bestehende Stufe nachträglich zu verschärfen, ist der Moment, in dem die meisten Ausfälle durch Pod Security entstehen, nicht die Ersteinführung in einen leeren Namespace. Ein Pod, der bisher als Root lief oder ein beschreibbares Root-Dateisystem brauchte, startet unter Restricted schlicht nicht mehr, und enforce verhindert das schon beim kubectl apply.
Mein Vorgehen dazu in echten Clustern: Erst audit und warn auf die Zielstufe setzen und ein paar Tage beobachten, was im Audit-Log und in den Warnungen der Entwickler auftaucht. Erst wenn dort nichts mehr auffällt, wandert dieselbe Stufe auch in enforce. Wichtig zu wissen: Die Stufe gilt immer für den ganzen Namespace, ein einzelner Pod kann sie nicht für sich absenken. Braucht ein Workload nachweislich mehr Rechte, bekommt er einen eigenen Namespace mit einer niedrigeren Stufe, oder du trägst eine Ausnahme in der Admission-Konfiguration des API-Servers ein. Beides sollte die Ausnahme bleiben und dokumentiert sein, sonst verwässert die Ausnahme irgendwann die ganze Regel.
Pod Security ist nicht RBAC: wo die Grenze verläuft
Pod Security Standards und RBAC lösen unterschiedliche Probleme, auch wenn beide unter Security-Governance laufen. RBAC entscheidet, wer über die Kubernetes-API welche Aktion auf welcher Ressource ausführen darf, also ob ein Mensch oder ein Service Account einen Pod überhaupt anlegen, ändern oder löschen darf. Was genau dieser Pod dann darf, sobald er läuft, regelt der Security Context und damit die Pod Security Standards. Mehr zum Rechtemodell für Menschen und Service Accounts liest du in Kubernetes RBAC: Rollen und Rechte.
In der Praxis ergänzen sich beide Ebenen: Selbst ein Service Account mit sehr engen RBAC-Rechten kann, wenn sein Pod privilegiert laufen darf, über den Container hinaus auf die Node zugreifen. Und selbst ein Pod mit striktem Security Context bringt nichts, wenn sein Service Account clusterweiten Lesezugriff auf alle Secrets hat. Wer nur eine der beiden Ebenen absichert, hat nur die halbe Miete.
Häufige Fragen
Was ist der Unterschied zwischen Baseline und Restricted?
Baseline verhindert bekannte Wege zur Rechteausweitung wie privilegierte Container, lässt aber sonst viel Spielraum für gewöhnliche Anwendungen. Restricted verlangt zusätzlich unter anderem einen Start ohne Root-Rechte und den Verzicht auf zusätzliche Linux Capabilities und eignet sich damit für Workloads, die keinen Sonderzugriff auf die Node brauchen.
Wie aktiviere ich Pod Security Standards für einen Namespace?
Mit einem Label am Namespace, zum Beispiel pod-security.kubernetes.io/enforce: baseline. Zusätzlich kannst du audit und warn mit einer strengeren Stufe setzen, um Verstöße gegen ein Ziel-Level sichtbar zu machen, bevor du es tatsächlich durchsetzt.
Was ist aus der Pod Security Policy geworden?
Die Pod Security Policy ist abgelöst und durch die einfacheren Pod Security Standards mit der Pod Security Admission ersetzt worden. Statt einer eigenen Policy-Ressource reicht seitdem ein Namespace-Label, um eine der drei Stufen zu aktivieren, das ist deutlich weniger fehleranfällig als die alte Policy-Ressource.
Reicht Pod Security Admission als alleinige Absicherung meiner Pods?
Nein, Pod Security Admission prüft nur eine feste Auswahl an Security-Context-Feldern gegen eine der drei Stufen. Für feinere Regeln, etwa erlaubte Image-Registries oder Pflichtfelder wie Ressourcen-Limits, brauchst du zusätzliche Admission Controller, und für die Frage, wer einen Pod überhaupt anlegen darf, weiterhin RBAC.
Wie du weitermachst
Wer Pods absichert, sollte als Nächstes auch regeln, mit wem sie im Netzwerk überhaupt sprechen dürfen, dazu mehr in Kubernetes Network Policy erklärt. Mein Vorschlag für heute: Setz audit und warn auf Restricted in einem unkritischen Namespace und schau dir nach ein paar Tagen an, welche deiner Pods heute schon durchgehen würden. Die vollständige Übersicht der Stufen und Kontrollen findest du in der Kubernetes-Dokumentation zu Pod Security Standards, Details zu den einzelnen Feldern in der Dokumentation zum Security Context.
Ausführlich mit allen Beispielen steht das in Kapitel 7 meines Kubernetes-Praxisbuchs bei Rheinwerk.