Kubernetes Error Guide: 'violates PodSecurity restricted' — Fix Admission Rejections
Fix the 'violates PodSecurity restricted' admission error in Kubernetes: satisfy the restricted standard's securityContext, capabilities, and seccomp rules.
- #kubernetes
- #troubleshooting
- #errors
- #security
Stuck on this Kubernetes & Helm error? Get the free incident triage checklist
A one-page PDF — the exact steps to isolate, fix, and verify a production error like this one. No spam, unsubscribe anytime.
Overview
Your pod (or its controller) is rejected at admission because it does not meet the Pod Security Standard enforced on the namespace. Pod Security admission is a built-in controller that evaluates every pod against one of three levels — privileged, baseline, or restricted — based on labels on the namespace. When the level is restricted and your pod is missing the required hardening, the API server refuses to create it and lists exactly which fields are wrong.
The literal error looks like this:
Error from server (Forbidden): error when creating "pod.yaml": pods "api" is forbidden:
violates PodSecurity "restricted:latest": allowPrivilegeEscalation != false (container "api" must set
securityContext.allowPrivilegeEscalation=false), unrestricted capabilities (container "api" must set
securityContext.capabilities.drop=["ALL"]), runAsNonRoot != true, seccompProfile (pod or container
must set securityContext.seccompProfile.type to "RuntimeDefault" or "Localhost")
Unlike a runtime failure, this happens at creation time — the object is never stored. For a Deployment/StatefulSet the Deployment is created but pods are not, and the failure shows up as a FailedCreate event on the ReplicaSet. The fix is to add the specific securityContext settings the message names.
Symptoms
kubectl applyreturnsForbidden ... violates PodSecurity "restricted:latest"with a list of violations.- A Deployment exists but has zero pods;
kubectl describe rsshowsFailedCreate. - The namespace carries
pod-security.kubernetes.io/enforce=restricted. - Each violation names the exact field to set.
kubectl apply -f pod.yaml
Error from server (Forbidden): pods "api" is forbidden: violates PodSecurity "restricted:latest":
allowPrivilegeEscalation != false, unrestricted capabilities, runAsNonRoot != true, seccompProfile
Common Root Causes
1. Missing allowPrivilegeEscalation=false
restricted requires every container to explicitly set allowPrivilegeEscalation: false. Omitting it (even though the default is often false at runtime) is a violation because admission requires it to be explicit.
allowPrivilegeEscalation != false (container "api" must set securityContext.allowPrivilegeEscalation=false)
2. Capabilities not dropped to ALL
Containers must drop: ["ALL"] and may only add back NET_BIND_SERVICE. Any container without an explicit drop-all is rejected.
unrestricted capabilities (container "api" must set securityContext.capabilities.drop=["ALL"])
3. runAsNonRoot not set to true
restricted requires runAsNonRoot: true at the pod or container level.
runAsNonRoot != true (pod or container "api" must set securityContext.runAsNonRoot=true)
4. Missing seccompProfile
The pod or each container must set seccompProfile.type to RuntimeDefault or Localhost.
seccompProfile (pod or container must set securityContext.seccompProfile.type to "RuntimeDefault")
5. Host namespaces, hostPath, or privileged set
Using hostNetwork, hostPID, hostPath volumes, or privileged: true violates restricted (and baseline for privileged) and cannot be waved through without lowering the level.
Diagnostic Workflow
Step 1: Read every violation in the message
kubectl apply -f pod.yaml
Pod Security lists all failing fields at once — fix them together rather than one at a time.
Step 2: Confirm the enforced level
kubectl get ns <NS> -o jsonpath='{.metadata.labels}'
{"pod-security.kubernetes.io/enforce":"restricted","pod-security.kubernetes.io/enforce-version":"latest"}
Step 3: Dry-run to preview violations for a controller
For Deployments where pods fail silently, use the warn behavior or a server dry-run:
kubectl apply -f deployment.yaml --dry-run=server
kubectl describe rs -l app=<APP> | grep -A3 FailedCreate
Step 4: Apply the compliant securityContext
Add pod- and container-level settings covering all four common requirements, then re-apply.
Step 5: Verify pods are created
kubectl get pods -l app=<APP>
kubectl get events -n <NS> --sort-by='.lastTimestamp' | grep -i podsecurity
Example Root Cause Analysis
A team deploys a Deployment into a hardened namespace and sees the workload with no pods:
kubectl get deploy,rs,pods -l app=api
deployment.apps/api 0/2 0 0 30s
replicaset.apps/api-6c9d 2 0 0 30s
The ReplicaSet cannot create pods:
kubectl describe rs api-6c9d | grep -A3 FailedCreate
Warning FailedCreate ... pods "api-6c9d-" is forbidden: violates PodSecurity "restricted:latest":
allowPrivilegeEscalation != false, unrestricted capabilities, runAsNonRoot != true, seccompProfile
The namespace enforces restricted, and the pod template has no securityContext. Adding the required fields makes it compliant:
spec:
template:
spec:
securityContext:
runAsNonRoot: true
runAsUser: 10001
seccompProfile:
type: RuntimeDefault
containers:
- name: api
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
kubectl apply -f deployment.yaml
kubectl rollout status deployment api
The ReplicaSet now creates pods and the Deployment reaches 2/2.
Prevention Best Practices
- Bake a
restricted-compliant securityContext into every workload template so admission never blocks a deploy. - Label namespaces with
warnandauditin addition toenforceso violations surface as warnings in lower environments before they block production. - Set pod-level
runAsNonRoot,seccompProfile, andfsGrouponce, and container-levelallowPrivilegeEscalation: false+capabilities.drop: ["ALL"]on each container. - Validate manifests in CI with a policy check (or
kubectl --dry-run=server) so violations are caught pre-merge. - Reserve
privileged/baselinenamespaces for the few workloads that genuinely need host access, and keep everything elserestricted. See more in Kubernetes & Helm guides.
Quick Command Reference
# See the full list of violations
kubectl apply -f pod.yaml
# Confirm the enforced level
kubectl get ns <NS> -o jsonpath='{.metadata.labels}'
# Preview violations for a controller
kubectl apply -f deployment.yaml --dry-run=server
kubectl describe rs -l app=<APP> | grep -A3 FailedCreate
# Check PodSecurity events
kubectl get events -n <NS> --sort-by='.lastTimestamp' | grep -i podsecurity
# Verify pods after the fix
kubectl get pods -l app=<APP>
Conclusion
violates PodSecurity "restricted:latest" means Pod Security admission rejected the pod for missing the restricted standard’s hardening. The usual causes:
allowPrivilegeEscalationnot explicitly false.- Capabilities not dropped to
ALL. runAsNonRootnot true.- Missing
seccompProfile. - Host namespaces,
hostPath, orprivilegedin use.
Read every violation the message lists and add the corresponding securityContext fields together. For workloads behind a controller, check the ReplicaSet’s FailedCreate event. For ad-hoc triage, the free incident assistant can turn a PodSecurity rejection into a compliant securityContext block.
Fixed it? Get 500 Kubernetes & Helm & DevOps AI prompts — free
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.
Stuck on this? Start guided troubleshooting
Open an interactive diagnostic session with this error already loaded. Work a step-by-step plan, record what each check returns, land on a root cause, and export a clean incident summary — no account needed to start.
Did this fix your issue?
Solved it a different way?
Share the fix that worked for you — reviewed, then published to help the next engineer.
That looks like it may contain a secret (key, token, password, or connection string). Please remove it — a note with a detected secret can’t be published.
Thanks — that helps. Published notes appear after a quick review.
Trending errors this week
The error guides other engineers are actually reading right now.
- 1mount: wrong fs type, bad option, bad superblock
- 2Docker 'failed to set up container networking': Fix the Bridge and IP Pool
- 3Docker 'failed to create shim task': How to Fix the containerd Runtime Error
- 4Transport endpoint is not connected
- 5modprobe: FATAL: Module not found
- 6mount: wrong fs type, bad option, bad superblock
Get 500 Battle-Tested DevOps AI Prompts — Free
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.