# CKA Mock Exam Pack v1 — full 120-minute simulation > **Format-matched to the real thing:** 17 weighted tasks, 120 minutes, 66% to pass. > Domain distribution ≈ real curriculum: Troubleshooting ~30%, Cluster Architecture ~25%, Services & Networking ~20%, Workloads & Scheduling ~15%, Storage ~10%. > Range: kind cluster `drills` (1 CP + 2 workers, Calico, Gateway API CRDs, metrics-server, helm). > > **Kind-isms (read once, then forget):** the real exam says `ssh nodeX` — here it's `docker exec -it drills-worker bash` (or `drills-worker2`, `drills-control-plane`). Real exam switches kubectl contexts per task — here it's one context; the discipline you're simulating is *reading the target of every task carefully*. --- ## EXAM PROTOCOL 1. Run the entire **MASTER SETUP** below. Do not read it — it contains spoilers (it breaks things on purpose). Pipe it to a file and execute blind: copy the block into `/tmp/setup.sh`, then `bash /tmp/setup.sh > /tmp/setup.log 2>&1`. 2. Set a hard 120:00 timer. No pauses, no notes, no Claude. 3. Solve in any order. Flag anything stuck >8 min and move on. Reserve the last 10 minutes for a verification lap. 4. When the timer dies: run the **VALIDATION** blocks, fill the score sheet, compute your percentage from the weights. 5. Paste score sheet + your command history to Claude for the autopsy. --- ## MASTER SETUP (do not read — paste and run) ```bash #!/usr/bin/env bash set +e # --- namespaces for ns in ex-neptune ex-mars ex-venus ex-pluto ex-saturn ex-mercury ex-titan ex-io ex-rescue; do kubectl create ns $ns; done # Q1: kill kubelet on worker2 docker exec drills-worker2 systemctl stop kubelet # Q5: broken deployment — missing CM + bad image tag kubectl -n ex-neptune create deploy web-portal --image=nginx:1.99-fake --replicas=2 kubectl -n ex-neptune set env deploy/web-portal --from=configmap/portal-config 2>/dev/null kubectl -n ex-neptune patch deploy web-portal --type=json -p='[{"op":"add","path":"/spec/template/spec/containers/0/envFrom","value":[{"configMapRef":{"name":"portal-config"}}]}]' # Q6: service with selector mismatch kubectl -n ex-mars create deploy api-backend --image=nginx --replicas=2 kubectl -n ex-mars label deploy api-backend app=api-backend --overwrite kubectl -n ex-mars apply -f - <<'EOF' apiVersion: v1 kind: Service metadata: {name: api-svc, namespace: ex-mars} spec: selector: {app: api-backent} ports: [{port: 80, targetPort: 80}] EOF # Q16: crashing pod kubectl -n ex-rescue run data-proc --image=busybox --restart=Never -- sh -c 'echo "FATAL: config /etc/proc/settings.ini not found" >&2; exit 1' # Q17: broken static pod on worker docker exec drills-worker bash -c 'mkdir -p /etc/kubernetes/manifests && cat > /etc/kubernetes/manifests/edge-cache.yaml <1MB cat "$EXAM_DIR/q2-status.txt" # snapshot status table/json # Q3 PIP=$(kubectl -n ex-pluto get pod backend -o jsonpath='{.status.podIP}') kubectl -n ex-pluto exec frontend -- curl -s -m 2 $PIP | head -1 # HTML (allowed) kubectl -n ex-pluto exec cache -- curl -s -m 2 $PIP; echo EXIT=$? # EXIT=28 (blocked) # Q4 kubectl -n ex-venus get httproute release-route -o yaml # header match in same rule-entry as its path; default rule present; parentRef=main-gate # Q5 kubectl -n ex-neptune get deploy web-portal # 2/2 kubectl -n ex-neptune get cm portal-config -o jsonpath='{.data.MODE}' # production # Q6 kubectl -n ex-mars get endpoints api-svc # two pod IPs # Q7 cat "$EXAM_DIR/q7-cani.txt" # yes + no kubectl auth can-i delete deployments --as=system:serviceaccount:ex-saturn:deploy-bot -n ex-saturn # yes kubectl auth can-i create pods --as=system:serviceaccount:ex-saturn:deploy-bot -n ex-saturn # no # Q8 helm list -n ex-titan # cache-layer, latest chart helm get values cache-layer -n ex-titan # architecture: standalone, auth.enabled: false cat "$EXAM_DIR/q8-history.txt" # rev1 + rev2 # Q9 kubectl -n ex-titan get deploy exam-portal -o jsonpath='{.spec.template.spec.containers[0].image}' # nginx:1.27 # Q10 kubectl -n ex-io get hpa writer-hpa -o yaml | grep -E 'averageUtilization|stabilizationWindowSeconds' # 70 + 240 under scaleDown; deploy now has cpu requests # Q11 kubectl -n ex-mercury get deploy release-app -o jsonpath='{.spec.template.spec.containers[0].image}' # nginx:1.26 cat "$EXAM_DIR/q11-rollback.txt" # Q12 kubectl -n ex-io get pods -l app=edge-daemon -o wide # both on drills-worker # Q13 kubectl -n ex-io get pvc claim-alpha # Bound cat "$EXAM_DIR/q13-why.txt" # WaitForFirstConsumer explanation # Q14 kubectl get sc local-manual -o jsonpath='{.metadata.annotations.storageclass\.kubernetes\.io/is-default-class}' # true cat "$EXAM_DIR/q14-proof.txt" # claim-default → local-manual # Q15 kubectl -n ex-mars get ingress api-ingress -o jsonpath='{.spec.rules[0].http.paths[0].pathType}' # Prefix # Q16 grep FATAL "$EXAM_DIR/q16-logs.txt" # the error line kubectl -n ex-rescue get pod data-proc # Running # Q17 kubectl get pod edge-cache-drills-worker # Running ``` > **Configurable path:** the validation block reads/writes under `$EXAM_DIR` (defaults to `/tmp/exam`). Override by exporting it before running, e.g. `EXAM_DIR=/tmp/exam-attempt2 bash -c '...'` or `export EXAM_DIR=/tmp/exam-attempt2` beforehand. The exam task descriptions above still reference the literal `/tmp/exam/...` paths — either keep writing there during the exam, or export the same `EXAM_DIR` value before starting the timer and use `$EXAM_DIR/...` for every task's output path too. ## SCORE SHEET | Q | Weight | Domain | Pass? | Time | |---|---|---|---|---| | 1 | 8 | TS | | | | 2 | 8 | CA | | | | 3 | 6 | SN | | | | 4 | 7 | SN | | | | 5 | 7 | TS | | | | 6 | 6 | TS | | | | 7 | 7 | CA | | | | 8 | 6 | CA | | | | 9 | 4 | CA | | | | 10 | 5 | WS | | | | 11 | 5 | WS | | | | 12 | 5 | WS | | | | 13 | 5 | ST | | | | 14 | 5 | ST | | | | 15 | 5 | SN | | | | 16 | 6 | TS | | | | 17 | 5 | TS | | | **Score = sum of passed weights. Pass line: 66.** ## RESET (between attempts) ```bash for ns in ex-neptune ex-mars ex-venus ex-pluto ex-saturn ex-mercury ex-titan ex-io ex-rescue; do kubectl delete ns $ns --wait=false; done kubectl delete gatewayclass exam-class; kubectl delete pv vol-alpha kubectl taint node drills-worker tier=critical:NoSchedule- 2>/dev/null kubectl label node drills-worker zone- ; kubectl label node drills-worker2 zone- kubectl patch sc local-manual -p '{"metadata":{"annotations":{"storageclass.kubernetes.io/is-default-class":"false"}}}' docker exec drills-worker rm -f /etc/kubernetes/manifests/edge-cache.yaml docker exec drills-worker2 systemctl start kubelet 2>/dev/null kubectl delete pod edge-cache-drills-worker --force 2>/dev/null ```