By Fatskills Exam Guides Team — the exam nerds behind 28,500+ quizzes and 2.1M practice questions across 500+ global exams.
For engineers who need to lock down Kubernetes clusters without wasting time on theory.
You’re a DevOps engineer at a fintech startup. Your team just migrated a legacy monolith to Kubernetes, and now any pod can run as root, mount host paths, or escalate privileges. A single misconfigured pod could let an attacker pivot to the host node, steal secrets, or cripple the cluster.
root
PodSecurityPolicies (PSP) (deprecated in Kubernetes 1.21, removed in 1.25) and Pod Security Admission (PSA) (the modern replacement) are your last line of defense against insecure workloads. They enforce security constraints like: - No root containers.- No privilege escalation.- No host filesystem access.- Read-only root filesystems.
Why this matters in production:- Compliance: PCI-DSS, SOC2, and HIPAA require least-privilege workloads.- Security: A single privileged: true pod can compromise the entire cluster.- Stability: Host path mounts can fill up node disks, crashing the node.- Cost: Unrestricted pods can consume all CPU/memory, starving other workloads.
privileged: true
Real-world scenario:You inherit a cluster where a developer deployed a pod with hostPID: true to debug a process. An attacker exploits this to read /etc/shadow from the host, then pivots to other nodes. PSA/PSP would’ve blocked this at admission time.
hostPID: true
/etc/shadow
privileged
allowPrivilegeEscalation
sudo
runAsUser
readOnlyRootFilesystem
volumes
hostPath
enforce
audit
warn
baseline
restricted
yaml pod-security.kubernetes.io/enforce: baseline pod-security.kubernetes.io/warn: restricted
runAsNonRoot: true
SecurityContext
CAP_NET_BIND_SERVICE
CAP_SYS_ADMIN
Prerequisites:- A Kubernetes cluster (v1.23+).- kubectl configured.- Cluster admin permissions.
kubectl
kubectl api-versions | grep admissionregistration.k8s.io/v1
✅ Expected output: admissionregistration.k8s.io/v1 (if missing, PSA isn’t available).
admissionregistration.k8s.io/v1
kubectl label ns default pod-security.kubernetes.io/enforce=baseline kubectl label ns default pod-security.kubernetes.io/warn=restricted
✅ Verify:
kubectl get ns default --show-labels
Expected output:
NAME STATUS AGE LABELS default Active 10d pod-security.kubernetes.io/enforce=baseline,pod-security.kubernetes.io/warn=restricted
# compliant-pod.yaml apiVersion: v1 kind: Pod metadata: name: compliant-pod spec: securityContext: runAsNonRoot: true runAsUser: 1000 containers: - name: nginx image: nginx securityContext: readOnlyRootFilesystem: true allowPrivilegeEscalation: false
kubectl apply -f compliant-pod.yaml
✅ Expected: Pod creates successfully.
# non-compliant-pod.yaml apiVersion: v1 kind: Pod metadata: name: non-compliant-pod spec: containers: - name: nginx image: nginx securityContext: privileged: true # Violates baseline/restricted
kubectl apply -f non-compliant-pod.yaml
✅ Expected output:
Error from server (Forbidden): pods "non-compliant-pod" is forbidden: violates PodSecurity "baseline:latest": privileged (container "nginx" must not set securityContext.privileged=true)
kubectl get events --sort-by='.metadata.creationTimestamp' | grep "PodSecurity"
Warning PodSecurityViolation 2m admission-controller Pod non-compliant-pod violates PodSecurity "restricted:latest": ...
Edit the API server manifest (/etc/kubernetes/manifests/kube-apiserver.yaml) and add:
/etc/kubernetes/manifests/kube-apiserver.yaml
- --enable-admission-plugins=NodeRestriction,PodSecurity - --admission-control-config-file=/etc/kubernetes/pod-security-admission-config.yaml
Create /etc/kubernetes/pod-security-admission-config.yaml:
/etc/kubernetes/pod-security-admission-config.yaml
apiVersion: apiserver.config.k8s.io/v1 kind: AdmissionConfiguration plugins: - name: PodSecurity configuration: apiVersion: pod-security.admission.config.k8s.io/v1 kind: PodSecurityConfiguration defaults: enforce: "baseline" enforce-version: "latest" audit: "restricted" audit-version: "latest" warn: "restricted" warn-version: "latest" exemptions: usernames: [] runtimeClasses: [] namespaces: [kube-system] # Exempt system namespaces
⚠️ Restart the API server:
sudo systemctl restart kubelet
default
prod
kube-system
bash kubectl get pods --all-namespaces -o json | jq '.items[] | select(.spec.securityContext == null or .spec.securityContext.runAsNonRoot != true)'
kubectl explain
bash kubectl explain pod.spec.securityContext
monitoring
promql kube_pod_security_violations_total{level="restricted"}
kubectl label ns <name> pod-security.kubernetes.io/enforce=restricted
kubectl apply --dry-run=server
kube-public
PodSecurityViolation
CKA/CKAD/CKS question patterns:1. Scenario: "A pod fails to start with Error: Forbidden: violates PodSecurity. What’s the issue?" - Answer: The pod violates the namespace’s PSA level (e.g., restricted blocks privileged: true).2. Trick question: "Which PSA level allows hostPath volumes?" - Answer: Only privileged. baseline and restricted block them.3. Command question: "How do you check a namespace’s PSA labels?" - Answer: kubectl get ns <name> --show-labels.4. Debugging question: "A pod works in dev but fails in prod. Why?" - Answer: prod likely has restricted PSA, while dev has baseline.
Error: Forbidden: violates PodSecurity
kubectl get ns <name> --show-labels
dev
Key distinctions:- PSP vs. PSA: - PSP: Deprecated, cluster-wide, uses ClusterRole. - PSA: Modern, namespace-scoped, uses labels.- baseline vs. restricted: - baseline: Blocks known privilege escalations (e.g., hostPath, privileged). - restricted: Enforces least privilege (e.g., runAsNonRoot, readOnlyRootFilesystem).
ClusterRole
runAsNonRoot
Challenge:Deploy a pod that: 1. Runs as a non-root user.2. Has a read-only root filesystem.3. Fails to start under restricted PSA.
Solution:
# challenge-pod.yaml apiVersion: v1 kind: Pod metadata: name: challenge-pod spec: containers: - name: alpine image: alpine command: ["sh", "-c", "echo 'I should fail!' && sleep 3600"] securityContext: readOnlyRootFilesystem: true runAsUser: 1000 allowPrivilegeEscalation: true # Violates restricted
kubectl apply -f challenge-pod.yaml
Why it fails:allowPrivilegeEscalation: true is blocked by restricted PSA.
allowPrivilegeEscalation: true
kubectl get ns --show-labels
kubectl explain pod.spec.securityContext
kubectl get events --sort-by='.metadata.creationTimestamp' \| grep PodSecurity
Join 4M+ learners. Unlock unlimited quizzes, wrong-answer tracking, flashcards + reminders, study guides, and 1-on-1 challenges.