Make a Deployment Pass the Restricted Pod Security Standard
Namespace restricted-ns enforces the restricted Pod Security Standard. A Deployment pss-app in this namespace is currently non-compliant and its Pods cannot start.
Live lab access
This task description is public. Live practice requires full access unless this is the selected free weekly task. AI Lab Coach is available in single-task labs, including the free weekly task. See this week's free task.
Create an account to continue →
On a phone? Read the task and create your account here, then sign in on a desktop or laptop for the terminal lab. Nothing starts until you choose Start.
The task
Task
Namespace restricted-ns enforces the restricted Pod Security Standard.
A Deployment pss-app in this namespace is currently non-compliant and its Pods cannot start.
Requirements
Update the Deployment so that its Pods comply with the restricted Pod Security Standard.
Ensure the Pods run successfully in the restricted namespace.
Original Prepium guide · Written for Kubernetes v1.35 and checked against the official documentation on 6 October 2026. Use a disposable practice cluster.
Read a Pod Security rejection and satisfy the restricted profile
The Pod Security Standards define three profiles: privileged (no restrictions), baseline (blocks known privilege escalations such as privileged containers, host namespaces and hostPath) and restricted (baseline plus current hardening practice). The built-in Pod Security Admission controller applies them per namespace, driven by labels. In the exam the namespace is usually already labelled; your job is to read why Pods are refused and change exactly the fields that the profile checks.
namespace labels
pod-security.kubernetes.io/enforce=restricted → violating Pods are rejected
pod-security.kubernetes.io/warn=restricted → client sees a warning, object allowed
pod-security.kubernetes.io/audit=restricted → audit log annotation, object allowed
pod-security.kubernetes.io/<mode>-version=v1.35 → pin the rules to a release (or latest)
1. Label a namespace and break a Deployment on purpose
kubectl create namespace prepium-tutorial
kubectl label --overwrite ns prepium-tutorial \
pod-security.kubernetes.io/enforce=restricted \
pod-security.kubernetes.io/enforce-version=v1.35 \
pod-security.kubernetes.io/warn=restricted \
pod-security.kubernetes.io/warn-version=v1.35
kubectl -n prepium-tutorial create deployment ticker --image=busybox:1.36 -- sleep 3600
kubectl -n prepium-tutorial get deploy,rs,pods
The Deployment is created, and because of the warn label kubectl prints a warning first. Enforcement is applied only to Pods, never to the Deployment or ReplicaSet, so the ReplicaSet exists but no Pod appears. Without a warn label you would get no hint at apply time and would have to read kubectl describe rs events to find the refusal.
2. Turn the message into a checklist
The warning has a documented shape: would violate PodSecurity "restricted:<version>": followed by one entry per failed check, each naming the container and the field it must set. For a stock busybox container you should see four entries, and each maps to one field:
allowPrivilegeEscalation != false → containers[*].securityContext.allowPrivilegeEscalation: false
unrestricted capabilities → containers[*].securityContext.capabilities.drop: ["ALL"]
runAsNonRoot != true → runAsNonRoot: true (Pod level covers every container)
seccompProfile → seccompProfile.type: RuntimeDefault (or Localhost)
Restricted also forbids runAsUser: 0, allows adding back only NET_BIND_SERVICE, limits volumes to types such as configMap, secret, emptyDir, projected and persistentVolumeClaim, and inherits every baseline rule. A real workload may trip several of these at once; fix them all, then re-read the message.
3. Apply the fields where they belong
Run kubectl -n prepium-tutorial edit deployment ticker and give the Pod template this shape:
spec:
securityContext:
runAsNonRoot: true
runAsUser: 10001
seccompProfile:
type: RuntimeDefault
containers:
- name: busybox # keep the existing container name
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
Pod-level runAsNonRoot and seccompProfile satisfy the check for every container; capabilities and escalation exist only per container, including init containers. The explicit non-zero runAsUser matters for a different reason: admission only checks fields, but the kubelet verifies runAsNonRoot at start time. busybox runs as root by default, so without a UID the Pod would be admitted and then its container would refuse to start.
4. Confirm
kubectl -n prepium-tutorial rollout status deployment/ticker
kubectl -n prepium-tutorial get pods
kubectl label --dry-run=server --overwrite ns prepium-tutorial \
pod-security.kubernetes.io/enforce-version=latest
Changing an enforce label, even in a server-side dry run, makes the admission plugin test every existing Pod in the namespace against the new setting and report violations as warnings. Here it asks whether your Pods would also pass the newest version of the profile; no warnings means they would.
Common mistakes
- Setting
capabilitiesat Pod level. The field does not exist there; strict validation rejects the edit. - Dropping
ALLon the app container but not on an init or sidecar container. One non-compliant container fails the whole Pod. - Satisfying admission with
runAsNonRoot: trueon an image whose default user is root, with no UID set. Admitted, then stuck before start. - Relabelling the namespace to
baselineto make the error go away. That changes the policy instead of fixing the workload.
| Example check | Evidence |
|---|---|
| Namespace policy unchanged | pod-security.kubernetes.io/enforce=restricted still on the namespace |
| Template compliant | No warning when the Deployment is re-applied |
| Pods admitted | New ReplicaSet has Pods; no FailedCreate events |
| Pods actually run | Ready Pods, container not stuck on the non-root check |
Cleanup: kubectl delete namespace prepium-tutorial. References: Pod Security Standards, Pod Security Admission, Enforce Pod Security Standards with namespace labels. Next, try immutable containers or Pod versus container securityContext.
What this tests
Apply Pod Security Standards, securityContext, and mTLS, and protect secrets at rest. On the CKS exam, Minimize Microservice Vulnerabilities tasks are graded purely on what you build in the cluster - not multiple choice - so the only way to get faster is to do them on a real cluster against a clock.
Practice it for real
The public description lets you study the task before signing up. Full access includes this live lab; the selected Task of the Week is free with an account. You solve the task in a real terminal, hit validate, and a programmatic checker scores exactly what you got right and wrong (with partial credit). You can open the solution while practising, then retry and use the failed checks to improve your score.