How to Implement Pod Security Standards
Secure your Kubernetes workloads using Pod Security Standards (PSS). Learn to enforce Privileged, Baseline, and Restricted policies at the namespace level.
The Problem
You need to enforce security policies to prevent containers from running with dangerous privileges like root access or host networking.
The Solution
Use Pod Security Standards (PSS) with Pod Security Admission (PSA) to enforce security policies at the namespace level.
Understanding Pod Security Standards
There are three policy levels:
| Level | Description |
|---|---|
| Privileged | Unrestricted, allows all capabilities |
| Baseline | Minimally restrictive, prevents known privilege escalations |
| Restricted | Highly restrictive, follows security best practices |
Enforcement Modes
| Mode | Behavior |
|---|---|
| enforce | Rejects pods that violate the policy |
| audit | Logs violations but allows pods |
| warn | Shows warnings but allows pods |
Step 1: Label Namespaces
Apply Pod Security Standards via namespace labels:
apiVersion: v1
kind: Namespace
metadata:
name: production
labels:
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/enforce-version: latest
pod-security.kubernetes.io/audit: restricted
pod-security.kubernetes.io/warn: restrictedApply it:
kubectl apply -f namespace.yamlOr label an existing namespace:
kubectl label namespace production \
pod-security.kubernetes.io/enforce=restricted \
pod-security.kubernetes.io/warn=restrictedStep 2: Gradual Rollout Strategy
Start with warn/audit, then enforce:
apiVersion: v1
kind: Namespace
metadata:
name: staging
labels:
# Start with warnings only
pod-security.kubernetes.io/warn: restricted
pod-security.kubernetes.io/audit: restricted
# Don't enforce yet
pod-security.kubernetes.io/enforce: baselineCompliant Pod Examples
Baseline Compliant Pod
apiVersion: v1
kind: Pod
metadata:
name: baseline-pod
spec:
containers:
- name: app
image: nginx:latest
ports:
- containerPort: 80Restricted Compliant Pod
apiVersion: v1
kind: Pod
metadata:
name: restricted-pod
spec:
securityContext:
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
containers:
- name: app
image: nginx:latest
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsUser: 1000
capabilities:
drop:
- ALL
ports:
- containerPort: 8080
volumeMounts:
- name: tmp
mountPath: /tmp
- name: cache
mountPath: /var/cache/nginx
- name: run
mountPath: /var/run
volumes:
- name: tmp
emptyDir: {}
- name: cache
emptyDir: {}
- name: run
emptyDir: {}Non-Compliant Pod (Will Be Rejected)
This pod violates restricted policy:
apiVersion: v1
kind: Pod
metadata:
name: privileged-pod
spec:
containers:
- name: app
image: nginx:latest
securityContext:
privileged: true # β Not allowed
runAsUser: 0 # β Root not allowedRestricted-Compliant Deployment Template
apiVersion: apps/v1
kind: Deployment
metadata:
name: secure-app
namespace: production
spec:
replicas: 3
selector:
matchLabels:
app: secure-app
template:
metadata:
labels:
app: secure-app
spec:
securityContext:
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 1000
fsGroup: 1000
seccompProfile:
type: RuntimeDefault
containers:
- name: app
image: myapp:latest
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
resources:
limits:
memory: "256Mi"
cpu: "500m"
requests:
memory: "128Mi"
cpu: "100m"
ports:
- containerPort: 8080
volumeMounts:
- name: tmp
mountPath: /tmp
volumes:
- name: tmp
emptyDir: {}Exemptions
For system pods that need elevated privileges, use exemptions at the cluster level (configured in AdmissionConfiguration):
apiVersion: apiserver.config.k8s.io/v1
kind: AdmissionConfiguration
plugins:
- name: PodSecurity
configuration:
apiVersion: pod-security.admission.config.k8s.io/v1
kind: PodSecurityConfiguration
defaults:
enforce: "restricted"
audit: "restricted"
warn: "restricted"
exemptions:
usernames: []
runtimeClasses: []
namespaces:
- kube-system
- cert-managerChecking Policy Violations
Dry-Run Test
Test if a pod would be admitted:
kubectl label --dry-run=server --overwrite ns production \
pod-security.kubernetes.io/enforce=restrictedView Audit Logs
Check the API server audit logs for violations.
Warnings in kubectl
# You'll see warnings when applying non-compliant pods
kubectl apply -f deployment.yaml
# Warning: would violate PodSecurity "restricted:latest"Migration Checklist
When moving to Restricted:
Run as non-root:
securityContext: runAsNonRoot: true runAsUser: 1000Drop all capabilities:
securityContext: capabilities: drop: ["ALL"]Disable privilege escalation:
securityContext: allowPrivilegeEscalation: falseUse read-only root filesystem:
securityContext: readOnlyRootFilesystem: trueSet seccomp profile:
securityContext: seccompProfile: type: RuntimeDefault
Best Practices
- Start with
warnandauditbeforeenforce - Use Restricted for production workloads
- Document exemptions and review regularly
- Test workloads in staging first
- Use namespace isolation for different security levels
Key Takeaways
- Pod Security Standards replace PodSecurityPolicies
- Three levels: Privileged, Baseline, Restricted
- Apply via namespace labels
- Use gradual rollout with warn/audit before enforce
- Most production workloads should target Restricted
π Go Further with Kubernetes Recipes
Love this recipe? Thereβs so much more! This is just one of 100+ hands-on recipes in our comprehensive Kubernetes Recipes book.
Inside the book, youβll master:
- β Production-ready deployment strategies
- β Advanced networking and security patterns
- β Observability, monitoring, and troubleshooting
- β Real-world best practices from industry experts
βThe practical, recipe-based approach made complex Kubernetes concepts finally click for me.β
π Get Your Copy Now β Start building production-grade Kubernetes skills today!
π Get All 100+ Recipes in One Book
Stop searching β get every production-ready pattern with detailed explanations, best practices, and copy-paste YAML.
Want More Kubernetes Recipes?
This recipe is from Kubernetes Recipes, our 750-page practical guide with hundreds of production-ready patterns.