HackBlue

Tools · Containers and Kubernetes security · 04 / 20

Pod Security Standards and Pod Security Admission: privileged, baseline, and restricted

Learn the three Pod Security Standards levels, apply them to namespaces with labels in enforce, audit, and warn modes, and roll out restricted without breaking deployments.

10 min read · practice only with authorization

Three levels

Privileged applies no restrictions and is meant for trusted system workloads. Baseline blocks known privilege escalations: privileged containers, hostNetwork, hostPID, hostIPC, hostPath volumes, added dangerous capabilities, and host ports. Restricted adds hardening on top: containers must run as non-root, drop all capabilities, disallow privilege escalation, and use a RuntimeDefault or Localhost seccomp profile.

Pod Security Admission is the built-in controller that enforces these levels. It replaced PodSecurityPolicy, which was removed in Kubernetes 1.25.

Enforce, audit, warn

Each namespace can set a level per mode with labels. enforce rejects violating pods. audit records a violation annotation in the audit log. warn returns a warning to the client such as kubectl. A common rollout sets warn and audit to restricted while enforce stays at baseline, then raises enforce when warnings stop.

Snippet
kubectl label ns shop \
  pod-security.kubernetes.io/enforce=baseline \
  pod-security.kubernetes.io/warn=restricted \
  pod-security.kubernetes.io/audit=restricted

Lab: watch a pod get rejected

Label a test namespace with enforce=restricted and try to run a plain nginx pod. Read the error: it lists each failed check, such as allowPrivilegeEscalation, capabilities, runAsNonRoot, and seccompProfile. Use a server-side dry run against existing namespaces to preview the impact before labeling them.

Snippet
kubectl create ns psa-lab
kubectl label ns psa-lab pod-security.kubernetes.io/enforce=restricted
kubectl -n psa-lab run web --image=nginx:1.27

kubectl label --dry-run=server --overwrite ns --all pod-security.kubernetes.io/enforce=baseline

Exceptions

System namespaces such as kube-system and some monitoring or CNI agents genuinely need privileged settings. Keep them in dedicated namespaces at the privileged level rather than weakening application namespaces. For finer-grained rules than the three levels, add a policy engine such as Kyverno or ValidatingAdmissionPolicy.

Diagram

What each level allows

Choose the strictest level the workload tolerates.

  • Privileged

    Anything. Only for trusted node agents.

  • Baseline

    Blocks privileged, host namespaces, hostPath, and dangerous capabilities.

  • Restricted

    Baseline plus non-root, drop ALL capabilities, no privilege escalation, seccomp required.

Check yourself

1. Which level requires containers to run as non-root and drop all capabilities?

2. Which mode returns a message to kubectl but still lets the pod run?

3. A pod mounts a hostPath volume. Which is the lowest level that rejects it?