Files
kodekloud-engineer/kubernetes/mock exams/cka-exam-pack-1-by-claude.md

14 KiB

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)

#!/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 <<EOF
apiVersion: v1
kind: Pod
metadata: {name: edge-cache}
spec:
  containers:
  - name: cache
    image: redis:7-alpinee
    ports: [{containerPort: 6379}]
EOF'

# Q4: gateway for httproute task
kubectl apply -f - <<'EOF'
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata: {name: exam-class}
spec: {controllerName: example.com/exam}
---
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata: {name: main-gate, namespace: ex-venus}
spec:
  gatewayClassName: exam-class
  listeners: [{name: http, port: 80, protocol: HTTP}]
EOF
kubectl -n ex-venus create deploy web-v1 --image=hashicorp/http-echo -- /http-echo -text=v1 -listen=:5678
kubectl -n ex-venus create deploy web-v2 --image=hashicorp/http-echo -- /http-echo -text=v2 -listen=:5678
kubectl -n ex-venus expose deploy web-v1 --port=5678
kubectl -n ex-venus expose deploy web-v2 --port=5678

# Q3: netpol targets
kubectl -n ex-pluto run frontend --image=nginx --labels=role=frontend --port=80
kubectl -n ex-pluto run backend --image=nginx --labels=role=backend --port=80
kubectl -n ex-pluto run cache --image=nginx --labels=role=cache --port=80

# Q7: rbac targets
kubectl -n ex-saturn create sa deploy-bot

# Q11: rollout history to inspect
kubectl -n ex-mercury create deploy release-app --image=nginx:1.25
kubectl -n ex-mercury set image deploy/release-app nginx=nginx:1.26
kubectl -n ex-mercury set image deploy/release-app nginx=nginx:1.27-bogus

# Q12: scheduling
kubectl taint node drills-worker tier=critical:NoSchedule --overwrite
kubectl label node drills-worker zone=east --overwrite
kubectl label node drills-worker2 zone=west --overwrite

# Q13/Q14: storage
kubectl apply -f - <<'EOF'
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata: {name: local-manual}
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer
EOF
docker exec drills-worker mkdir -p /opt/vol-alpha
kubectl -n ex-io create deploy metrics-writer --image=busybox -- sleep 3600
echo "SETUP DONE"

THE EXAM — 120:00 starts now

Q1 — 8% — Troubleshooting

Node drills-worker2 is NotReady. Find the cause, fix it, make the node Ready again. Write the name of the failed component into /tmp/exam/q1-component.txt.

Q2 — 8% — Cluster Architecture

Create a snapshot of the cluster's etcd database and save it inside the control-plane node at /root/etcd-backup.db. Then verify the snapshot and write the number of keys/revision info into /tmp/exam/q2-status.txt on your host. (Hint allowed by the real exam's phrasing: certs live where kubeadm puts them. Enter the CP with docker exec -it drills-control-plane bash.)

Q3 — 6% — Services & Networking

In ex-pluto: Pods role=backend must accept ingress only from Pods role=frontend in the same namespace on port 80. Traffic from role=cache (and everything else) must be denied. Name the policy backend-shield. Egress stays open.

Q4 — 7% — Services & Networking

In ex-venus, attached to the existing Gateway main-gate, create HTTPRoute release-route: all requests to path prefix / go to web-v1:5678, except requests with header X-Version: v2 (exact) which go to web-v2:5678. Spec-level correctness counts (no dataplane on this range).

Q5 — 7% — Troubleshooting

Deployment web-portal in ex-neptune has 0/2 ready. There are two independent faults. Fix both. Desired end state: 2/2 Ready, env sourced from a ConfigMap named portal-config containing key MODE=production.

Q6 — 6% — Troubleshooting

Service api-svc in ex-mars returns no endpoints. Diagnose and repair the service (the deployment is correct). Prove endpoints exist afterward.

Q7 — 7% — Cluster Architecture

In ex-saturn, using imperative commands only: allow ServiceAccount deploy-bot to create, list, and delete Deployments in ex-saturn — nothing else, namespace-scoped. Verify with kubectl auth can-i (one positive, one negative check) and save both outputs to /tmp/exam/q7-cani.txt.

Q8 — 6% — Cluster Architecture

Using Helm: install chart bitnami/redis as release cache-layer in namespace ex-titan, chart version one minor behind latest, with architecture=standalone and auth disabled (auth.enabled=false) set via CLI. Then upgrade to the latest chart version preserving both overrides. Record helm history output to /tmp/exam/q8-history.txt.

Q9 — 4% — Cluster Architecture

A base kustomization exists at /tmp/drill-kz/base (from drill pack v1; recreate it if you cleaned it). Create overlay /tmp/drill-kz/overlays/exam that deploys into namespace ex-titan with name prefix exam- and image nginx:1.27. Apply it with -k.

Q10 — 5% — Workloads & Scheduling

Create HPA writer-hpa in ex-io for deployment metrics-writer: min 1, max 4, target 70% average CPU. Scale-down stabilization window 240s. (The deployment lacks CPU requests — part of the task is making the HPA functional.)

Q11 — 5% — Workloads & Scheduling

Deployment release-app in ex-mercury is stuck mid-rollout on a bad image. Roll it back to the previous working revision, then record: current image and the revision number you rolled back to → /tmp/exam/q11-rollback.txt.

Q12 — 5% — Workloads & Scheduling

Create deployment edge-daemon (image busybox, sleep 3600, 2 replicas) in namespace ex-io that runs only on drills-worker: tolerate its taint and pin via nodeAffinity on the zone=east label. Both replicas must land there.

Q13 — 5% — Storage

Create PV vol-alpha: 2Gi, RWO, storageClassName local-manual, hostPath /opt/vol-alpha. Create PVC claim-alpha in ex-io requesting 1Gi, same class. Explain in one line inside /tmp/exam/q13-why.txt why the PVC is Pending at this point. Then mount it in a pod vol-user (nginx) at /data and confirm Bound.

Q14 — 5% — Storage

Make local-manual the default StorageClass of the cluster. Then create PVC claim-default in ex-io with no storageClassName and prove (one command's output to /tmp/exam/q14-proof.txt) that it was assigned local-manual automatically.

Q15 — 5% — Services & Networking

In ex-mars, create an Ingress api-ingress (imperative generator allowed): host api.exam.local, path /v1 (Prefix) → service api-svc:80, ingressClassName nginx. The controller isn't installed — spec-level correctness counts. Ensure pathType is explicitly Prefix.

Q16 — 6% — Troubleshooting

Pod data-proc in ex-rescue is failing. Save its complete logs (the error line included) to /tmp/exam/q16-logs.txt, then recreate the pod so it runs successfully with the same name and image, sleeping 1 hour instead of crashing.

Q17 — 5% — Troubleshooting

A static pod edge-cache was configured on node drills-worker but never appears in kubectl get pods. Enter the node, find the fault, fix it, and get the mirror pod visible and Running in the default namespace.


VALIDATION (run only after the timer — expected outputs in comments)

EXAM_DIR="${EXAM_DIR:-./exam}"
mkdir -p "$EXAM_DIR"
# Q1
kubectl get node drills-worker2                                # Ready
cat "$EXAM_DIR/q1-component.txt"                                # kubelet
# Q2
docker exec drills-control-plane ls -la /root/etcd-backup.db   # exists, >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)

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