Home › CKAD › Topics › Practice tasks › Security Contexts
CKAD · Application Environment, Configuration and Security

Set runAsUser and Add a Capability with securityContext

In namespace default, Deployment secure-app exists without any security context.

Check live lab access → All CKAD tasks

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 →

Read this week's free task →

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

In namespace default, Deployment secure-app exists without any security context.

Requirements

  1. Set Pod-level runAsUser: 1000
  2. Add container-level capability NET_ADMIN to the container named app

Note: Capabilities are set at the container level, not the Pod level.

Original Prepium guide · Written for Kubernetes v1.35 and checked against the official documentation on 6 October 2026. Use a disposable practice cluster.

Pod-level and container-level securityContext, and how to prove each one took effect

A Pod has two places for security settings. spec.securityContext sets defaults that every container inherits, such as which user and group the processes run as. Each container's own securityContext can override those defaults and also holds settings that exist only per container: Linux capabilities, allowPrivilegeEscalation, readOnlyRootFilesystem and privileged. Exam tasks often hinge on putting a field at the right level, and then on showing it worked from inside the container.

spec.securityContext            runAsUser, runAsGroup, fsGroup, runAsNonRoot, seccompProfile ...
   │ inherited, unless overridden
   ▼
containers[].securityContext    runAsUser, runAsGroup ... (wins on overlap)
                                capabilities, allowPrivilegeEscalation,
                                readOnlyRootFilesystem, privileged (container only)

1. Apply a Pod that uses both levels

Save this as ckad-secctx-pod.yaml. The worker container inherits the Pod identity; binder overrides the user and trims its capabilities.

apiVersion: v1
kind: Pod
metadata:
  name: ctx-lab
  namespace: prepium-tutorial
spec:
  securityContext:          # Pod level: inherited by every container
    runAsUser: 2500
    runAsGroup: 2600
    fsGroup: 2700
  volumes:
    - name: scratch
      emptyDir: {}
  containers:
    - name: worker
      image: busybox:1.36
      command: ["sh", "-c", "sleep 3600"]
      volumeMounts:
        - name: scratch
          mountPath: /scratch
      securityContext:      # container level: only for this container
        allowPrivilegeEscalation: false
        readOnlyRootFilesystem: true
    - name: binder
      image: busybox:1.36
      command: ["sh", "-c", "sleep 3600"]
      securityContext:
        runAsUser: 0        # overrides the Pod-level 2500 for this container only
        capabilities:
          drop: ["ALL"]
          add: ["NET_BIND_SERVICE"]
kubectl create namespace prepium-tutorial
kubectl apply -f ckad-secctx-pod.yaml
kubectl -n prepium-tutorial wait --for=condition=Ready pod/ctx-lab --timeout=90s

2. Check identity with id and /proc

kubectl -n prepium-tutorial exec ctx-lab -c worker -- id
kubectl -n prepium-tutorial exec ctx-lab -c worker -- grep -E 'Uid|Gid|NoNewPrivs' /proc/1/status
kubectl -n prepium-tutorial exec ctx-lab -c binder -- id

In worker, id reports uid 2500 and gid 2600, and the group list includes 2700 from fsGroup, which is added as a supplementary group to every container. The Uid line of /proc/1/status repeats the same number for the real, effective, saved and filesystem IDs, and NoNewPrivs is 1: setting allowPrivilegeEscalation: false is what turns on the kernel's no_new_privs flag. In binder, id shows uid 0, because the container value beats the Pod value, while the gid is still 2600 since that field was not overridden.

3. Read the capability bitmap

kubectl -n prepium-tutorial exec ctx-lab -c binder -- grep Cap /proc/1/status

CapEff is a hexadecimal mask with one bit per capability. After dropping everything and adding back one, only bit 10 should be set (0000000000000400), and bit 10 is CAP_NET_BIND_SERVICE in the kernel's capability header. Note the spelling in YAML: you list NET_BIND_SERVICE without the CAP_ prefix. To see what a runtime grants by default, run the same command in a container with no capabilities block and compare the masks.

4. Test the read-only root filesystem

kubectl -n prepium-tutorial exec ctx-lab -c worker -- touch /probe
kubectl -n prepium-tutorial exec ctx-lab -c worker -- touch /scratch/probe
kubectl -n prepium-tutorial exec ctx-lab -c worker -- ls -ln /scratch

The first write fails with a read-only file system error; the second succeeds because the emptyDir volume is a separate, writable mount. The numeric listing shows the new file owned by uid 2500, with group 2700 coming from fsGroup.

Common mistakes

Example checkEvidence
Pod-level identity appliedid in an inheriting container shows the Pod's uid, gid and fsGroup
Container override winsOverriding container reports its own uid
Capabilities trimmed or addedCapEff mask in /proc/1/status has exactly the expected bits
Escalation blockedNoNewPrivs: 1 in /proc/1/status

Cleanup: kubectl delete namespace prepium-tutorial. References: Configure a Security Context for a Pod or Container, Pod API reference (PodSecurityContext and SecurityContext), proc_pid_status(5). Next, try immutable containers or the restricted Pod Security Standard.

Exam
CKAD
Domain
Application Environment, Configuration and Security
Grading
Programmatic · partial credit

What this tests

Wire up configmaps, secrets, service accounts, RBAC, securityContext, and resource limits. On the CKAD exam, Application Environment, Configuration and Security 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.

Related CKAD tasks