Pod Security (PSA)
For years, Kubernetes used PodSecurityPolicy (PSP) to lock down pods. It was complex, buggy, and confusing. In v1.25, it was completely removed.
The replacement is Pod Security Admission (PSA). It is built-in, on by default, and much easier to use. It relies on the Pod Security Standards (PSS) - a predefined set of rules maintained by the Kubernetes community.
The "Club Bouncer" Analogy
Think of PSA as the bouncer at the door of a nightclub (Namespace). You tell the bouncer what the "Dress Code" (Policy Level) is for that room.
- Privileged (The VIP Room): Anything goes. You can come in wearing pajamas, carrying weapons (root access), or acting wild.
- Baseline (The General Floor): Standard dress code. No obvious threats allowed, but we won't inspect your socks. (Prevents known privilege escalations).
- Restricted (The Black Tie Gala): Extremely strict. You must have a tie, polished shoes, and perfect behavior. (Follows hard-core hardening best practices).
1. The Three Levels (The Standards)
You cannot invent your own rules anymore. You must pick one of these three standard profiles.
| Level | Goal | Use Case |
|---|---|---|
| Privileged | Unrestricted. Allows known privilege escalations. | System agents (CNI, Storage Drivers), Logging agents. |
| Baseline | Minimally Restrictive. Prevents known escalations. | Standard applications, web servers, microservices. (90% of use cases). |
| Restricted | Hardened. Requires pods to explicitly drop capabilities and run as non-root. | High-security financial/gov apps. |
2. The Three Modes (The Action)
What happens when someone breaks the dress code?
| Mode | Action | When to use? |
|---|---|---|
| Enforce | Block the Pod. Return 403 Forbidden. | Production (after testing). |
| Audit | Log the violation to the audit log, but allow the pod. | Monitoring & Compliance. |
| Warn | Tell the user immediately in the CLI, but allow the pod. | Developer feedback loop. |
Visualizing the Flow
graph TD
User[Developer] -->|kubectl apply| API[API Server]
API -->|Check Namespace Labels| PSA[PSA Controller]
PSA -- "Namespace is 'restricted'?" --> Check{Check Pod Spec}
Check -- "Pod runs as Root!" --> Violation
Violation -- "Mode: Enforce" --> Block[Deny: 403 Forbidden]
Violation -- "Mode: Warn" --> Message[Warning: This pod violates policy...]
Message --> Allow[Allow Pod]
3. How to Configure (Namespace Labels)
PSA is controlled entirely via Namespace Labels. You don't need to create any CRDs or objects.
The Syntax
Practical Example: The Safe Rollout
You want to enforce restricted security, but you are afraid of breaking the app.
Step 1: Turn on Warnings & Audit (Dry Run)
kubectl label namespace backend \
pod-security.kubernetes.io/enforce=baseline \
pod-security.kubernetes.io/warn=restricted \
pod-security.kubernetes.io/audit=restricted
Result: The app runs (Baseline enforcement), but if the developer tries to deploy something that isn't fully "Restricted" compliant, they get a warning in their terminal.
Step 2: Fix the Warnings
The developer updates their securityContext in the YAML to meet the Restricted standard.
Step 3: Enforce Restricted
kubectl label namespace backend \
pod-security.kubernetes.io/enforce=restricted \
pod-security.kubernetes.io/warn=restricted --overwrite
4. The Versioning Trap (Critical!)
You will notice the label enforce-version. You can set this to latest or a specific version like v1.28.
Avoid latest in Production
Kubernetes security standards change. A setting that is allowed in Restricted v1.25 might be banned in Restricted v1.29.
If you use enforce-version=latest, and you upgrade your cluster, your existing valid pods might suddenly fail to restart because the rules changed under your feet.
Best Practice: Pin the version to your current cluster version (e.g., v1.29) and manually update it only when you have verified your apps against the new rules.
5. Troubleshooting: What a Block Looks Like
If you try to deploy a standard Nginx pod into a Restricted namespace, it will fail because Nginx tries to run as root by default, and it doesn't drop capabilities.
Command:
kubectl apply -f nginx.yaml
Error Output:
Error from server (Forbidden): error when creating "nginx.yaml":
pods "nginx" is forbidden: violates PodSecurity "restricted:v1.29":
- (container "nginx" must not set securityContext.allowPrivilegeEscalation=true)
- (container "nginx" must set securityContext.runAsNonRoot=true)
- (container "nginx" must set securityContext.seccompProfile.type to "RuntimeDefault" or "Localhost")
The Fix: You must update your Pod YAML to explicitly adhere to the rules:
spec:
securityContext:
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
containers:
- name: nginx
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
Summary
- PSA is the standard, built-in way to secure pods.
- Levels:
Privileged(Unsafe),Baseline(Standard),Restricted(Hardened). - Modes:
Enforce(Block),Audit(Log),Warn(Notify). - Configuration: Done strictly via labels on the Namespace.
- Production Tip: Pin your versions (don't use
latest) and useWarn/Auditmodes before switchingEnforceto a stricter level.