Articles / Pod Security Standards and Admission Control
Kubernetes · Admission

Pod Security Standards and Admission Control

For years the answer to 'how do I stop someone deploying a privileged, host-mounting pod?' was PodSecurityPolicy. PSP was deprecated in Kubernetes 1.21 and removed in 1.25, and its replacement is not a single successor but a pattern: enforce security constraints at admission, before a pod is ever scheduled. Get this layer right and the hardening advice in the rest of this series stops being optional guidance and becomes a rule the cluster mechanically enforces.

Admission control is the checkpoint every object passes through after authentication and authorization but before it is persisted and scheduled. An admission controller can inspect a pod spec and reject it, or mutate it, based on policy. This is where you stop a workload that runs as root, mounts the host filesystem, or requests privileged: true — at the door, not after it is already running.

Pod Security Standards and the built-in admission controller

violatescompliantkubectl applypod specAPI serverauthn + authzAdmissionPSS / policy engineRejectedprivileged pod blockedScheduled & runningUnlabelled namespace→ no profileenforced
Admission control decides whether a dangerous pod is ever scheduled.

Kubernetes defines three Pod Security Standards as named profiles. Privileged is unrestricted. Baseline blocks known privilege escalations — no host namespaces, no privileged containers, no dangerous capabilities — while staying broadly compatible. Restricted is the hardened profile: it additionally requires running as non-root, dropping ALL capabilities, a read-only-friendly configuration, and a seccomp profile.

Since 1.25, Pod Security Admission enforces these profiles natively, configured per namespace with labels. Each profile can run in three modes at once: enforce rejects violating pods, audit records them in the audit log, and warn returns a client-side warning. The usual rollout is to start in warn/audit, find what breaks, then flip to enforce.

Namespace labels turning on the Restricted profileapiVersion: v1
kind: Namespace
metadata:
  name: payments
  labels:
    pod-security.kubernetes.io/enforce: restricted
    pod-security.kubernetes.io/warn: restricted
Why it matters: Hardening you merely document is hardening that erodes. Admission control converts 'please don't run privileged pods' into 'you cannot' — the difference between a guideline and a guardrail.

When built-in PSA is not enough

Pod Security Admission is deliberately limited: three fixed profiles, namespace-level granularity, pods only. Real policy needs are often finer — 'only images from our registry', 'every pod must set resource limits', 'these labels are mandatory', 'no latest tags'. For that, policy engines run as admission webhooks and evaluate arbitrary rules against any resource.

  • OPA Gatekeeper. Policy written in Rego, with a constraint framework and audit of existing violations. Powerful and expressive; a learning curve.
  • Kyverno. Policies expressed as Kubernetes YAML, no new language. Can validate, mutate, and generate resources — and verify image signatures at admission.
  • Validating Admission Policy. In-tree CEL-based policy, no external webhook to run or keep highly-available — useful for simpler rules without a separate controller.

Layer these: PSA for the baseline pod-hardening profile across every namespace, and a policy engine for the organisation-specific rules on top. A key operational point — a validating webhook that is down can fail open (admit everything) or closed (block everything); choose the failure mode deliberately per policy, because it is a real availability-versus-security trade-off.

Rolling it out without breaking production

  • Audit before you enforce. Run the target profile in audit/warn across namespaces first and read the violations — they are your migration backlog.
  • Default new namespaces to Restricted. Make the hardened profile the path of least resistance and exceptions the reviewed case.
  • Namespace the exceptions. Genuinely privileged workloads (CNI, storage, monitoring agents) belong in their own clearly-labelled namespaces, not as blanket cluster carve-outs.
  • Enforce image provenance here too. Admission is the natural place to reject unsigned images — the trust layer meets the runtime gate.

Admission control is the point where policy becomes physics: past it, a non-conforming pod simply cannot exist. But it only governs the clusters where it is installed and the namespaces you have labelled. A cluster stood up without these controls — or a namespace someone left on the Privileged profile — is a gap that inherits none of your guardrails, and you can't gate admission to a cluster you didn't know was there.

Test for it — in practice
  • Check the Pod Security labels on your namespaces — any that are unlabelled or left on privileged inherit no baseline hardening.
  • In a non-prod namespace, try applying a trivially privileged pod spec and see whether admission rejects it; silent acceptance means the gate is not really there.

One namespace is a quick check; auditing every cluster and namespace for the gaps that quietly opt out is what our assessment runs for you.

Keep reading
Privileged Containers and Container Escapes