Enforce Pod Security Admission
# Enforce the restricted standard on a namespace with three labelskubectl label namespace orders \ pod-security.kubernetes.io/enforce=restricted \ pod-security.kubernetes.io/warn=restricted \ pod-security.kubernetes.io/audit=restrictedPodSecurityPolicy is gone — don’t look for it
Section titled “PodSecurityPolicy is gone — don’t look for it”If a hardening guide tells you to write a PodSecurityPolicy, stop reading it.
PSP was deprecated in 1.21 and removed entirely in 1.25. The API doesn’t
exist. A cluster on any current version has no PSP, and manifests referencing it
are inert.
Its replacement, Pod Security Admission (PSA), is built into the API server and works completely differently — and much more simply. There’s no policy object, no RBAC binding, no controller to install. You apply one of three built-in Pod Security Standards to a namespace with labels, and the API server enforces it on every pod created there.
This matters because the two are not similar. Time spent trying to make PSP work, or copying a PSP-based guide, is time spent on an API that Kubernetes removed. PSA is the answer, and it’s less work.
The three standards
Section titled “The three standards”| Standard | What it allows |
|---|---|
| privileged | Everything — no restrictions. The unsafe default. |
| baseline | Blocks known privilege escalations: no privileged, no host namespaces, no hostPath, limited capabilities. |
| restricted | Baseline plus hardening: must run as non-root, drop all capabilities, seccomp RuntimeDefault, read-only where possible. |
restricted is the target for application namespaces — it enforces most of
the workload security context
automatically, so a pod that tries to run privileged or as root is rejected at
admission. baseline is the pragmatic floor when restricted breaks too much
to adopt at once.
The unlabelled default is effectively privileged — no enforcement — which is why
a fresh namespace lets a pod request anything.
The three modes
Section titled “The three modes”Each standard can be applied in three modes, and using them together is how you adopt safely:
enforce— reject pods that violate the standard. The teeth.warn— allow, but return a warning to the user who created it.audit— allow, but record a violation in the audit log.
Set warn and audit to restricted before you set enforce, so you see
what would be rejected without breaking anything. That’s the safe rollout, and
it’s the whole reason the three modes exist.
It’s per-namespace, and kube-system is exempt
Section titled “It’s per-namespace, and kube-system is exempt”PSA is applied per namespace, so hardening the cluster means labelling every
application namespace — a new namespace with no label has no enforcement.
kube-system and other control-plane namespaces legitimately run privileged pods
and should not be set to restricted; scope your enforcement to workload
namespaces.
For cluster-wide defaults, the API server’s AdmissionConfiguration can set a
baseline that applies everywhere unless a namespace overrides it — better than
relying on remembering to label each one.
Related
Section titled “Related”- Restrict privileged containers — the settings
restrictedenforces. - Audit logging — where PSA
auditmode records violations.