Pod Security Admission GA: The New Standard for Pod Security

Table of Contents
Introduction
With Kubernetes 1.25 in August 2022 (and broader adoption in 2023), Pod Security Admission reached General Availability (GA), completing the replacement of the deprecated PodSecurityPolicy. Pod Security Admission provided a simpler, namespace-scoped approach to pod security enforcement that addressed PSP’s complexity and usability issues.
This mattered because PodSecurityPolicy had been deprecated in Kubernetes 1.21 (2021) and removed in 1.25 (2022), forcing teams to migrate to alternatives. Pod Security Admission offered a Kubernetes-native solution that was simpler than PSP, more flexible than basic pod security, and easier to use than policy engines like Gatekeeper or Kyverno.
Historical note: Pod Security Admission was introduced as alpha in Kubernetes 1.23 (December 2021) and reached GA in 1.25 (August 2022). By 2023, it had become the standard pod security mechanism, with PSP fully removed from Kubernetes.
Pod Security Admission Features
Namespace-Scoped Enforcement
- Namespace Labels: Security profiles enforced via namespace labels
- Three Profiles: Privileged, Baseline, and Restricted security profiles
- Enforcement Modes: Enforce, audit, and warn modes for gradual adoption
- Standard Profiles: Predefined profiles eliminate policy complexity
Security Profiles
Privileged Profile:
- Unrestricted policy, provides widest range of permissions
- Equivalent to running without restrictions
- Use for: System components, privileged workloads
Baseline Profile:
- Minimally restrictive policy
- Prevents known privilege escalations
- Allows common volume types
- Use for: Legacy applications, development
Restricted Profile:
- Highly restrictive policy
- Requires running as non-root
- Disallows privilege escalation
- Requires read-only root filesystem
- Use for: Production workloads, security-sensitive applications
Comparison: Pod Security Admission vs PSP vs Policy Engines
| Capability | Pod Security Admission | PodSecurityPolicy | Gatekeeper/Kyverno |
|---|---|---|---|
| Scope | Pods only | Pods only | Any resource |
| Complexity | Low (labels) | High (RBAC) | Medium (policies) |
| Performance | Good (built-in) | Poor | Good |
| Flexibility | Low (3 profiles) | Medium | High (custom policies) |
| Kubernetes Native | Yes | Yes (deprecated) | No (add-ons) |
| Namespace Scoping | Yes (native) | Limited | Yes |
| Best For | Standard pod security | Legacy clusters | Custom requirements |
Implementation Patterns
Namespace-Level Enforcement
# Production namespace with Restricted profile
apiVersion: v1
kind: Namespace
metadata:
name: production
labels:
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/audit: restricted
pod-security.kubernetes.io/warn: restricted
---
# Development namespace with Baseline profile
apiVersion: v1
kind: Namespace
metadata:
name: development
labels:
pod-security.kubernetes.io/enforce: baseline
pod-security.kubernetes.io/audit: restricted
pod-security.kubernetes.io/warn: restricted
Gradual Adoption
# Start with warn mode
apiVersion: v1
kind: Namespace
metadata:
name: staging
labels:
pod-security.kubernetes.io/enforce: baseline
pod-security.kubernetes.io/audit: restricted
pod-security.kubernetes.io/warn: restricted
Exemptions
# Exempt specific namespaces
apiVersion: v1
kind: Namespace
metadata:
name: kube-system
labels:
pod-security.kubernetes.io/enforce: privileged
pod-security.kubernetes.io/audit: privileged
pod-security.kubernetes.io/warn: privileged
Migration from PodSecurityPolicy
PSP Policy
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: restricted
spec:
privileged: false
allowPrivilegeEscalation: false
requiredDropCapabilities:
- ALL
runAsUser:
rule: MustRunAsNonRoot
Pod Security Admission Equivalent
apiVersion: v1
kind: Namespace
metadata:
name: production
labels:
pod-security.kubernetes.io/enforce: restricted
Standard Security Profiles
Restricted Profile Requirements
- runAsNonRoot: Containers must run as non-root user
- allowPrivilegeEscalation: Privilege escalation disallowed
- capabilities: All capabilities dropped
- readOnlyRootFilesystem: Root filesystem must be read-only
- seccomp: Seccomp profile required
Baseline Profile Requirements
- allowPrivilegeEscalation: Privilege escalation disallowed (if not explicitly set)
- hostNetwork: Host network disallowed
- hostIPC: Host IPC disallowed
- hostPID: Host PID disallowed
Practical Considerations
Profile Selection
- Privileged: System components, CNI plugins, storage drivers
- Baseline: Legacy applications, development workloads
- Restricted: Production workloads, security-sensitive applications
Gradual Rollout
- Warn Mode: Start with warn mode to identify violations
- Audit Mode: Enable audit mode to track violations
- Enforce Mode: Enable enforcement after fixing violations
Workload Updates
Some workloads may need updates to comply with profiles:
- Run as Non-Root: Update containers to run as non-root users
- Read-Only Root FS: Configure volumes for writable data
- Capabilities: Remove unnecessary capabilities
- Seccomp Profiles: Configure seccomp profiles
Getting Started
# Enable Pod Security Admission (Kubernetes 1.23+)
# Feature gate enabled by default in 1.25+
# Create namespace with Restricted profile
kubectl create namespace production
kubectl label namespace production \
pod-security.kubernetes.io/enforce=restricted \
pod-security.kubernetes.io/audit=restricted \
pod-security.kubernetes.io/warn=restricted
# Test pod creation
kubectl run test-pod --image=nginx --namespace=production
Caveats & Lessons Learned
- Workload Compatibility: Some workloads may not work with Restricted profile; use Baseline for legacy apps
- System Components: System components may need Privileged profile; plan exemptions
- Gradual Migration: Migrate gradually, starting with warn mode
- Profile Limitations: Three profiles may not cover all use cases; use policy engines for custom requirements
Common Failure Modes
- “Pods rejected”: Pods fail to start due to profile restrictions; update workloads or use appropriate profile
- “System components broken”: System components need Privileged profile; create exemptions
- “Legacy app issues”: Legacy apps don’t comply with profiles; use Baseline profile or update apps
Conclusion
Pod Security Admission’s GA in Kubernetes 1.25 (and broader adoption in 2023) marked the completion of the PSP replacement. It provided teams with a simpler, more usable alternative to PodSecurityPolicy that addressed PSP’s complexity and performance issues. While Pod Security Admission offered less flexibility than policy engines, it provided standard security profiles that covered most use cases.
For organizations migrating from PSP, Pod Security Admission provided a straightforward migration path. It demonstrated that pod security didn’t have to be complex—it could be simple, namespace-scoped, and built into Kubernetes. Pod Security Admission proved that Kubernetes security could be both powerful and accessible, enabling teams to enforce pod security without learning complex policy languages or managing additional infrastructure.
The patterns and practices established with Pod Security Admission would become the standard for pod security in Kubernetes. It demonstrated that security could be both comprehensive and simple, enabling teams to enforce security standards without sacrificing usability or performance. Pod Security Admission marked the evolution of pod security from a complex, hard-to-use mechanism to a simple, built-in capability.