Veröffentlicht am

Pod Security Admission: PSA richtig konfigurieren

Teilen:
Authors

TL;DR

Pod Security Admission (PSA) ist seit Kubernetes 1.25 der offizielle Nachfolger der PodSecurityPolicy. PSA definiert drei Sicherheitsprofile -- privileged, baseline und restricted -- und drei Enforcement-Modi pro Namespace. Die Konfiguration erfolgt über Namespace-Labels, ohne zusätzliche Installation. Für die meisten Workloads reicht das baseline-Profil als Einstieg.


PodSecurityPolicy ist tot -- was jetzt?

Mit Kubernetes 1.25 wurde PodSecurityPolicy (PSP) endgültig entfernt. Der Nachfolger heisst Pod Security Admission (PSA) und ist als Built-in Admission Controller direkt im API-Server verfügbar. Kein Helm-Chart, kein Webhook -- PSA ist ab Werk aktiv.

Der groesste Unterschied: PSP war eine eigenständige Ressource mit RBAC-Bindung. PSA arbeitet mit Namespace-Labels und Pod Security Standards.

# PSA aktivieren: Ein einziges Label auf dem Namespace reicht
apiVersion: v1
kind: Namespace
metadata:
  name: production
  labels:
    pod-security.kubernetes.io/enforce: restricted

Das wars. Jeder Pod in diesem Namespace muss jetzt die restricted-Anforderungen erfuellen -- oder wird abgelehnt.


Die drei Pod Security Standards

PSA definiert drei Profile mit steigendem Sicherheitsniveau:

ProfilBeschreibungTypischer Einsatz
privilegedKeine EinschränkungenSystem-Namespaces, kube-system
baselineVerhindert bekannte Privilege-EscalationsStandard-Workloads
restrictedMaximale Sicherheit, Best PracticesProduktions-Workloads, Multi-Tenant

Was baseline verbietet

Das baseline-Profil blockiert die gefährlichsten Konfigurationen:

  • hostNetwork: true, hostPID: true, hostIPC: true
  • Privilegierte Container (privileged: true)
  • Bestimmte Linux-Capabilities wie NET_RAW
  • hostPath-Volumes

Was restricted zusätzlich verlangt

Das restricted-Profil geht weiter und erzwingt aktiv sichere Konfigurationen:

  • Container müssen als non-root laufen (runAsNonRoot: true)
  • Seccomp-Profil muss gesetzt sein (RuntimeDefault oder Localhost)
  • Alle Capabilities muessen gedroppt werden (drop: ["ALL"])
  • Read-only Root-Filesystem wird empfohlen

Enforcement-Modi: enforce, audit, warn

Jedes Profil kann in drei Modi angewendet werden:

apiVersion: v1
kind: Namespace
metadata:
  name: staging
  labels:
    # Modus 1: enforce -- Pod wird abgelehnt
    pod-security.kubernetes.io/enforce: baseline
    pod-security.kubernetes.io/enforce-version: v1.31

    # Modus 2: audit -- Verstoss wird im Audit-Log vermerkt
    pod-security.kubernetes.io/audit: restricted
    pod-security.kubernetes.io/audit-version: v1.31

    # Modus 3: warn -- Benutzer bekommt eine Warnung
    pod-security.kubernetes.io/warn: restricted
    pod-security.kubernetes.io/warn-version: v1.31

Die empfohlene Migrationsstrategie: Startet mit warn und audit auf dem strengeren Profil, während ihr mit enforce auf dem schwächeren bleibt. So seht ihr Verstoesse, ohne Workloads zu blockieren.

# Prüfen welche Pods gegen restricted verstossen würden
kubectl label namespace staging \
  pod-security.kubernetes.io/warn=restricted \
  pod-security.kubernetes.io/audit=restricted \
  --overwrite

# Danach einen Pod deployen und Warnungen beobachten
kubectl apply -f deployment.yaml -n staging
# Warning: would violate PodSecurity "restricted:v1.31": ...

Namespace-Konfiguration für typische Szenarien

Produktions-Namespace mit maximaler Sicherheit

apiVersion: v1
kind: Namespace
metadata:
  name: production
  labels:
    pod-security.kubernetes.io/enforce: restricted
    pod-security.kubernetes.io/enforce-version: v1.31
    pod-security.kubernetes.io/audit: restricted
    pod-security.kubernetes.io/audit-version: v1.31
    pod-security.kubernetes.io/warn: restricted
    pod-security.kubernetes.io/warn-version: v1.31

Pod der restricted erfuellt

apiVersion: v1
kind: Pod
metadata:
  name: secure-app
  namespace: production
spec:
  securityContext:
    runAsNonRoot: true
    seccompProfile:
      type: RuntimeDefault
  containers:
    - name: app
      image: nginx:1.27
      securityContext:
        allowPrivilegeEscalation: false
        capabilities:
          drop: ["ALL"]
        readOnlyRootFilesystem: true
      volumeMounts:
        - name: tmp
          mountPath: /tmp
  volumes:
    - name: tmp
      emptyDir: {}

System-Namespace mit Ausnahmen

Für kube-system und Monitoring-Namespaces braucht ihr oft privileged:

apiVersion: v1
kind: Namespace
metadata:
  name: monitoring
  labels:
    pod-security.kubernetes.io/enforce: privileged
    pod-security.kubernetes.io/warn: baseline

Exemptions: Ausnahmen konfigurieren

Manchmal brauchen einzelne Workloads in einem sonst restriktiven Namespace erhöhte Rechte. PSA bietet dafür Exemptions auf API-Server-Ebene.

Die Exemptions werden in der AdmissionConfiguration des API-Servers definiert:

# /etc/kubernetes/admission-config.yaml
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
        audit-version: latest
        warn: restricted
        warn-version: latest
      exemptions:
        usernames: []
        runtimeClasses: []
        namespaces:
          - kube-system
          - kube-node-lease
          - monitoring

Den API-Server mit dieser Konfiguration starten:

# In der kube-apiserver Manifest-Datei ergänzen
# /etc/kubernetes/manifests/kube-apiserver.yaml
# Unter spec.containers.command:
#   --admission-control-config-file=/etc/kubernetes/admission-config.yaml

Migration von PodSecurityPolicy

Falls ihr noch alte PSP-Konfigurationen migriert, hier der Ablauf:

  1. Bestandsaufnahme: Welche PSPs existieren und welche Namespaces nutzen sie?
  2. Mapping: PSP-Regeln auf PSA-Profile abbilden (baseline deckt die meisten Standard-PSPs ab)
  3. Labels setzen: Zuerst nur warn und audit aktivieren
  4. Testen: Deployments neu deployen und Warnungen prüfen
  5. Enforce: Nach erfolgreichem Test auf enforce umstellen
# Alle Namespaces ohne PSA-Labels finden
kubectl get namespaces -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.metadata.labels}{"\n"}{end}' | grep -v pod-security

FAQ

Was passiert mit laufenden Pods wenn ich enforce aktiviere?

Bestehende Pods werden nicht beendet. PSA prueft nur bei der Erstellung neuer Pods. Aber: Beim naechsten Rollout oder Neustart werden die Pods gegen das Profil geprüft. Plant die Umstellung also vor einem Deployment-Zyklus.

Kann ich PSA und OPA Gatekeeper gleichzeitig nutzen?

Ja. PSA bietet ein solides Basissicherheitsniveau, während Gatekeeper für feinere, individuelle Policies zuständig ist. PSA fängt die groben Verstösse, Gatekeeper die spezifischen.

Welches Profil soll ich für neue Namespaces verwenden?

Startet mit enforce: baseline und warn: restricted. Das blockiert die gefährlichsten Konfigurationen und zeigt euch gleichzeitig, was für restricted noch angepasst werden muss.

Gibt es PSA auch für einzelne Pods statt ganze Namespaces?

Nein. PSA arbeitet ausschliesslich auf Namespace-Ebene. Für Pod-spezifische Policies braucht ihr einen externen Admission Controller wie OPA Gatekeeper oder Kyverno.


Fazit

Pod Security Admission ist pragmatisch und sofort einsatzbereit. Die Kombination aus drei Profilen und drei Modi gibt euch genug Flexibilität für eine schrittweise Migration. Setzt mindestens enforce: baseline auf allen Namespaces ausser kube-system -- und arbeitet euch schrittweise zu restricted vor.


Verwandte Artikel

Kubernetes-Security & Compliance?

Security-Audits, Penetration Tests und Compliance-Beratung für Ihre Container-Infrastruktur. BSI-Grundschutz, DSGVO, ISO 27001.

Kubernetes-Beratung gesucht?

Wir helfen deutschen Unternehmen bei der Kubernetes-Implementierung, Migration und Optimierung. DSGVO-konform und praxiserprobt.

📖 Verwandte Artikel

Weitere interessante Beiträge zu ähnlichen Themen