Am 07.09. ging es an dieser Stelle um Kyverno und darum, wie du erzwingst, dass nur signiert Images in deinen Cluster kommen („Nur signierte Images im Cluster: Provenance mit Kyverno erzwingen“). Kyverno ist dafür der richtige Werkzeugkasten: frei definierbare Admission-Policies, die du selbst schreibst, für Regeln, die es in Kubernetes von Haus aus nicht gibt.
Für einen großen Teil der Pod-Härtung brauchst du diesen Werkzeugkasten aber gar nicht erst aufzuschlagen. Kubernetes bringt seit Version 1.25 einen eigenen Admission-Controller mit, der drei fertige Sicherheitsstufen kennt und sich über ein einziges Namespace-Label aktivieren lässt: Pod Security Admission (PSA). Kein Helm-Chart, kein CRD, kein Update-Zyklus einer dritten Komponente – nur ein Label, das der kube-apiserver selbst auswertet.
Dieser Artikel klärt, was PSA tatsächlich kann, wo die eingebaute Grenze verläuft und ab wann du zwangsläufig bei Kyverno (oder einer vergleichbaren Policy-Engine) landest.
Was Pod Security Admission ist
PSA ist ein in kube-apiserver eingebauter Admission-Controller. Die offizielle Dokumentation führt ihn als „built-in Pod Security admission controller to enforce the Pod Security Standards“ (kubernetes.io, Pod Security Admission). Der Feature-Status ist seit Kubernetes 1.25 „Stable“ – PSA ist damit kein Beta-Feature mehr, sondern GA (General Availability).
Die Pod Security Standards, die PSA durchsetzt, sind kein MHM-Konstrukt, sondern eine eigene Kubernetes-Spezifikation mit drei kumulativen Stufen (kubernetes.io, Pod Security Standards):
- Privileged: „purposely-open, and entirely unrestricted“ – keine Einschränkung, gedacht für System- und Infrastruktur-Workloads unter vertrauenswürdiger Kontrolle.
- Baseline: „aimed at ease of adoption for common containerized workloads while preventing known privilege escalations“ – verbietet unter anderem privilegierte Container, das Teilen von Host-Namespaces (
hostNetwork,hostPID,hostIPC), Host-Path-Volumes und zusätzliche Linux-Capabilities über eine feste Erlaubnisliste hinaus. - Restricted: „Heavily restricted policy, following current Pod hardening best practices“ – verlangt zusätzlich zu Baseline unter anderem, dass Container nicht als root laufen, dass Privilege Escalation (
allowPrivilegeEscalation) deaktiviert ist, dass alle Capabilities gedroppt werden (nurNET_BIND_SERVICEdarf optional ergänzt werden) und dass ein Seccomp-Profil explizit gesetzt ist.
Diese drei Stufen sind vordefiniert. Du kannst sie auswählen, aber nicht umschreiben – genau das ist der Unterschied zu Kyverno, dazu unten mehr.
Die drei Modi: enforce, audit, warn
PSA kennt pro Namespace drei unabhängig konfigurierbare Modi (kubernetes.io, Pod Security Admission):
| Modus | Verhalten |
|---|---|
enforce |
Verstoß führt zur Ablehnung des Pods. |
audit |
Verstoß wird als Audit-Annotation im Audit-Log vermerkt, der Pod wird trotzdem erstellt. |
warn |
Verstoß erzeugt eine Warnung für den Nutzer (z. B. bei kubectl apply), der Pod wird trotzdem erstellt. |
Wichtig für die Praxis: enforce wirkt laut Dokumentation nur auf die finalen Pod-Objekte, nicht auf die Templates von Deployments, StatefulSets oder Jobs selbst – audit und warn dagegen werden zusätzlich auf die Workload-Ressourcen angewendet, damit Verstöße schon beim kubectl apply auf ein Deployment sichtbar werden, bevor der erste Pod überhaupt entsteht.
Das Namespace-Label in der Praxis
Jede Stufe und jeder Modus wird über ein Label-Paar pod-security.kubernetes.io/<MODE>: <LEVEL> gesetzt. Optional lässt sich die Kubernetes-Minor-Version fixieren, gegen die geprüft wird (kubernetes.io, Pod Security Admission):
apiVersion: v1
kind: Namespace
metadata:
name: team-checkout
labels:
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/enforce-version: latest
pod-security.kubernetes.io/audit: restricted
pod-security.kubernetes.io/warn: restricted
Mit diesem Label ist der Namespace team-checkout sofort auf die restriktivste Stufe gesetzt – ohne Controller-Deployment, ohne eigene Policy-Sprache, ohne zusätzliche Wartung. Willst du erst beobachten, bevor du hart durchsetzt, setzt du enforce vorerst auf baseline und audit/warn bereits auf restricted – so siehst du im Audit-Log und in der kubectl-Ausgabe, welche Workloads bei einer Verschärfung brechen würden, ohne dass produktiv schon etwas blockiert wird.
Wo die eingebaute Grenze endet
PSA prüft ausschließlich Felder im securityContext eines Pods und einige verwandte Spec-Felder – festgelegt durch die drei Standard-Stufen. Es gibt keinen Mechanismus, um eine eigene Regel zu ergänzen, etwa „nur Images aus einer bestimmten Registry“ oder „nur Images mit gültiger Signatur“. Genau das war der Gegenstand des Kyverno-Artikels vom 07.09.: Provenance- und Signatur-Prüfung ist keine der drei vordefinierten Pod Security Standards, also kann PSA sie grundsätzlich nicht abbilden – unabhängig davon, welche Stufe du wählst.
Kyverno wiederum ist laut eigener Dokumentation dafür gebaut, Policies „as declarative Kubernetes resources“ zu verwalten und dabei „YAML and CEL … with no new language to learn“ für frei definierte Regeln zu nutzen (kyverno.io, Introduction). Es lässt sich als eigener Admission-Controller im Cluster betreiben und prüft nicht nur Pods, sondern beliebige Ressourcentypen gegen selbst geschriebene Bedingungen.
Abgrenzung zum Kyverno-Artikel vom 07.09.: Dort ging es um frei definierbare Admission-Policies – etwa die Durchsetzung von Image-Signaturen –, die als eigene Regeln geschrieben und im Cluster betrieben werden. Hier geht es um die eingebauten, vordefinierten Pod-Security-Standards, die ohne Custom-Policy-Sprache und ohne zusätzliche Installation direkt im Namespace-Label stecken.
PSA vs. Kyverno im Vergleich
| Pod Security Admission | Kyverno | |
|---|---|---|
| Installation | Eingebaut in kube-apiserver, keine zusätzliche Komponente (kubernetes.io) |
Eigener Admission-Controller, muss im Cluster betrieben werden (kyverno.io) |
| Regelumfang | Drei vordefinierte Stufen: privileged, baseline, restricted (kubernetes.io) | Frei definierbare Regeln als eigene YAML-Ressourcen (kyverno.io) |
| Konfiguration | Ein Namespace-Label pro Modus | Policy-Ressourcen (z. B. ClusterPolicy) mit eigener Logik |
| Prüfgegenstand | Pod-securityContext und verwandte Spec-Felder |
Beliebige Ressourcentypen und Felder |
| Beispiel-Use-Case | root-Container, privilegierte Container, Host-Namespaces verbieten | Image-Signaturen erzwingen, Registry-Whitelisting, Label-Pflichten |
| Betriebsaufwand | Keiner über die Label-Pflege hinaus | Eigener Lebenszyklus: Updates, CRDs, Monitoring der Policy-Engine |
Wann PSA reicht – und wann nicht
Wenn deine Anforderung sich in einem Satz mit „root“, „privilegiert“, „Host-Namespace“ oder „Capabilities“ formulieren lässt, deckt eine der drei Pod Security Standards das vermutlich schon ab – dann reicht das Namespace-Label, und du sparst dir den Betrieb einer zusätzlichen Policy-Engine. Sobald deine Anforderung eine Regel ist, die es in den drei Standards nicht gibt – Bildherkunft, Registry-Zugehörigkeit, eigene Label- oder Annotation-Pflichten, Beziehungen zwischen mehreren Ressourcen –, ist PSA am Ende seiner Reichweite, und du brauchst eine Engine wie Kyverno, die eigene Regeln versteht.
Der wirtschaftlich sinnvolle Weg ist deshalb nicht „Kyverno für alles“, sondern die Stufen zu trennen: erst das eingebaute, kostenlose PSA-Label auf restricted setzen, dort wo es reicht – und Kyverno gezielt für die Regeln einsetzen, die PSA strukturell nicht abbilden kann.
Bei der Einordnung von Pod Security Admission oder Kyverno für deinen Cluster: Schreib mir an mm@mhm-dl.de.
Hinterlasse einen Kommentar