Pod Security Admission Levels
Pod Security Admission is the control a KCSA candidate is most likely to be asked about and least likely to have seen refuse anything. This guide labels a namespace restricted, submits an ordinary Pod, and reads the rejection.
Cloud Native Security Guide 6 of 42 Beginner
- Kubernetesapiserver v1.36.4, kubelet v1.36.3
- Runtimecontainerd 2.2.6
- CNICilium 1.18.1
- Built withkubeadm v1.36.3
- TimeAbout 14 min
PSA is built into the apiserver and needs nothing installed - which is why it works on this cluster where no admission webhook exists at all. The three levels (privileged, baseline, restricted) and three modes (enforce, audit, warn) are stable API.
- Host kernel7.0.0-29
| Server Name | IP Address | OS | Roles | CPU | RAM | HDD |
|---|---|---|---|---|---|---|
| CKA5001 | 192.168.0.41 | Ubuntu 26.04 LTS | Control Plane Node (tainted NoSchedule) | 2 Core | 4 GB | 50 GB |
| CKA5001-NODE01 | 192.168.0.42 | Ubuntu 26.04 LTS | Worker Node | 2 Core | 4 GB | 50 GB |
| CKA5001-NODE02 | 192.168.0.43 | Ubuntu 26.04 LTS | Worker Node | 2 Core | 4 GB | 50 GB |
| CKA5001-NODE03 | 192.168.0.44 | Ubuntu 26.04 LTS | Worker Node | 2 Core | 4 GB | 50 GB |
This guide includes
Use this because Pod Security Admission is the control KCSA is most likely to ask you about. This matters because it is built into the API server and needs nothing installed - one label on a namespace is the entire configuration.
- creating two namespaces where the only difference between them is a label
- applying the identical Pod to both and getting opposite results
- reading the violation list that the rejection hands back
Before you start
- guide 3 - which showed 5 of 5 namespaces with no PSA label at all.
-
Two namespaces, one of them labelled
The label is the entire configuration. There is nothing to install.
bash Example session kubectl create ns kcsa-open >/dev/null && kubectl create ns kcsa-strict >/dev/null && kubectl label ns kcsa-strict pod-security.kubernetes.io/enforce=restricted pod-security.kubernetes.io/warn=restricted >/dev/null && kubectl get ns kcsa-open kcsa-strict -o custom-columns='NAME:.metadata.name,ENFORCE:.metadata.labels.pod-security\.kubernetes\.io/enforce'NAME ENFORCEkcsa-open <none>kcsa-strict restrictedExpected result
kcsa-openwithENFORCE <none>,kcsa-strictwithENFORCE restricted.Success conditionYou have a controlled namespace and an uncontrolled one to compare.
-
The same Pod, twice
Identical spec. One namespace takes it, the other does not.
bash Example session kubectl -n kcsa-open run plain --image=docker.io/library/busybox:1.37 --restart=Never --command -- sh -c 'sleep 600' 2>&1 | tail -1; kubectl -n kcsa-open wait --for=condition=Ready pod/plain --timeout=120spod/plain createdpod/plain condition metkubectl -n kcsa-strict run plain --image=docker.io/library/busybox:1.37 --restart=Never --command -- sh -c 'sleep 600' 2>&1 | head -4; echo "--- the SAME Pod spec, refused. Pod Security Admission names every rule it broke"Error from server (Forbidden): pods "plain" is forbidden: violates PodSecurity "restricted:latest": allowPrivilegeEscalation != false (container "plain" must set securityContext.allowPrivilegeEscalation=false), unrestricted capabilities (container "plain" must set securityContext.capabilities.drop=["ALL"]), runAsNonRoot != true (pod or container "plain" must set securityContext.runAsNonRoot=true), seccompProfile (pod or container "plain" must set securityContext.seccompProfile.type to "RuntimeDefault" or "Localhost")--- the SAME Pod spec, refused. Pod Security Admission names every rule it brokeExpected result
pod/plain createdandcondition metinkcsa-open. Inkcsa-strict:Error from server (Forbidden): pods "plain" is forbidden: violates PodSecurity "restricted".Success conditionYou have seen the control refuse something.
Troubleshooting
PSA is not restricting anything.
Why: No namespace carries a
pod-security.kubernetes.io/enforcelabel.Fix:It is opt-in per namespace. Label it, or nothing happens.
A Deployment reports no error but no Pods appear.
Why: The Deployment was accepted; its ReplicaSet cannot create Pods.
Fix:
kubectl describe replicaset- the PSA rejection is on the ReplicaSet's events.Existing Pods keep running after a namespace is labelled.
Why: Admission judges submissions, not existing objects.
Fix:Expected. Recreate them, or use
warn/auditfirst to find what would break.A level's meaning changed after a cluster upgrade.
Why: No
enforce-versionlabel, so the level tracks the apiserver.Fix:Pin it:
pod-security.kubernetes.io/enforce-version: v1.31.Forbiddenand it is not clear whether RBAC or PSA.Why: Both use the word.
Fix:Read the body.
violates PodSecurityis admission;cannot <verb>is RBAC.