KubernetesBy Nova AI Ops TeamPublished Sep 26, 202611 min read

Kubernetes Pod Security Standards in 2026: Migrating from PSP

PodSecurityPolicy was removed in Kubernetes 1.25. The replacement, Pod Security Standards, is simpler and easier to enforce, but only if you understand the three profiles and the namespace-level enforcement model.

Why PSP Was Replaced

PodSecurityPolicy (PSP) was the original Kubernetes mechanism for enforcing security constraints on pods. It was deprecated in Kubernetes 1.21 and removed entirely in 1.25. The reasons were practical: PSPs were complex (you had to grant ServiceAccounts use of specific PSPs through RBAC), the enforcement order was unintuitive (the first matching PSP wins, which surprised everyone), and the policies themselves were hard to reason about because they composed in unexpected ways.

Pod Security Standards (PSS) is the simpler replacement. Three predefined profiles, namespace-level labels for enforcement, no RBAC tricks. If you are still on PSP, you should have migrated by now; if you have not, this guide will get you there.

The Three Profiles

PSS defines three profiles of increasing restriction:

Privileged. No restrictions. The default. Allows everything: privileged containers, hostPath volumes, hostNetwork, hostPID, hostIPC, capability ALL, etc. Use only for system workloads (CNI agents, storage drivers, monitoring) that genuinely need elevated permissions.

Baseline. Minimally restrictive. Disallows the most dangerous fields: privileged containers, host namespaces (hostNetwork, hostPID, hostIPC), hostPath volumes, NET_ADMIN/SYS_ADMIN capabilities, and arbitrary Linux capabilities. Designed to prevent obvious privilege escalation while allowing common application patterns. The right default for most application workloads.

Restricted. Heavily restricted. Disallows everything in Baseline plus: running as root, all Linux capabilities (must drop ALL), writable root filesystem, and seccomp must be set to RuntimeDefault or Localhost. Designed for workloads where security takes priority over compatibility. Required for high-security environments.

Namespace-Level Enforcement

Unlike PSPs, which were cluster-wide and per-pod, PSS is enforced at the namespace level via labels:

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

The three modes:

The recommended migration pattern: set warn first, fix all the violations that surface, then promote to enforce after a soak period of 1-2 weeks.

Migrating from PSP

The migration is straightforward in most cases:

  1. Audit existing PSPs. Run kubectl get psp -A to enumerate all PodSecurityPolicies. Map each to its closest PSS profile. Most production PSPs map to Baseline; most "developer" PSPs map to Restricted.
  2. Label namespaces with audit mode. Apply pod-security.kubernetes.io/audit: <profile> labels to every namespace based on its workload type.
  3. Run for 1-2 weeks. Watch the audit logs for violations. Each violation is a workload that won't pass enforcement.
  4. Fix or exempt violations. Most violations are removable: drop unnecessary capabilities, set runAsNonRoot: true, add seccompProfile. The remaining violations are workloads that genuinely need elevated permissions and should run in a Privileged-labeled namespace.
  5. Promote to enforce. Change audit to enforce on each namespace once all violations are fixed.
  6. Delete the PSPs. Once all namespaces are on PSS enforce mode, the old PSPs (if any remain in versions that still support them) can be removed.

Common Migration Gotchas

Gotcha 1: System namespaces need Privileged. kube-system, kube-public, and any namespace running CNI agents or storage drivers need the Privileged profile. Do not try to apply Restricted to these.

Gotcha 2: Helm charts often violate Restricted. Many off-the-shelf Helm charts run as root, mount hostPath, or use elevated capabilities by default. Check chart values for security overrides; most charts support them.

Gotcha 3: Older container images do not support runAsNonRoot. Restricted requires runAsNonRoot: true, but many container images expect to start as root and drop to a non-root user. Either rebuild the image to start as non-root, or apply Baseline instead of Restricted to these workloads.

Gotcha 4: PSS does not enforce things PSP did. AppArmor profiles, SELinux options, and some volume restrictions are not part of PSS. If you used PSP for those, you need a separate admission controller (OPA Gatekeeper, Kyverno) for the gap.

What PSS Does Not Replace

PSS handles pod-level security primitives. It does not handle: NetworkPolicies (use the dedicated API), runtime security (use Falco or similar), image vulnerability scanning (use Trivy, Snyk, etc.), secrets management (use external Vault), or RBAC (use the dedicated RBAC API).

For organizations that need policies more sophisticated than the three PSS profiles allow, OPA Gatekeeper or Kyverno provide rule-based admission control with arbitrary policy logic. Both layer on top of PSS rather than replacing it.

For continuous detection of pod security drift (workloads that satisfy PSS at admission time but accumulate risky config later via patches or operator changes), AI-native platforms like Nova AI Ops include continuous compliance scanning across the cluster fleet.