~/cka

CKA Study Tracker

A study log for the Certified Kubernetes Administrator exam. Mark how well you know each of the 27 official competencies, log practice sessions, and get up to three suggestions for what to practice next.

  • Curriculum: Kubernetes v1.37, checked Wed, Oct 28, 2026
  • 9 hands-on lab tasks, 9 simulations
  • Progress stays in this browser

An independent learning tool by DamonSec. Not affiliated with or endorsed by the CNCF or the Linux Foundation. Tracking your progress here does not show that you are ready for the exam.

Jump to curriculum · Simulations · Practice tasks · Export / import

Practice today

How suggestions work

Loading suggestions…

Your progress

Loading progress saved in this browser…

Curriculum

The official CKA domains and competencies. Set a status for each one yourself; open a skill for docs, practice tasks, notes and your attempt history.

27 skills in 5 domains.

Storage · 10% of exam

Troubleshooting · 30% of exam

Workloads & Scheduling · 15% of exam

Cluster Architecture, Installation & Configuration · 25% of exam

Services & Networking · 20% of exam

Troubleshooting simulations

Practise the diagnosis without a cluster. Pick commands, read real recorded output, and decide what is wrong and how to fix it. A simulation only follows a script, so finish by repeating the matching lab task on a real cluster.

  • Service returns connection refused

    about 8 min (estimate) · Troubleshoot services and networking

  • Pod keeps restarting

    about 6 min (estimate) · Manage and evaluate container output streams

  • Pod and PVC stuck in Pending

    about 6 min (estimate) · Manage persistent volumes and persistent volume claims

  • Pod stuck in Pending

    about 5 min (estimate) · Configure Pod admission and scheduling (limits, node affinity, etc.)

  • Deployment stuck in CreateContainerConfigError

    about 8 min (estimate) · Use ConfigMaps and Secrets to configure applications

  • ServiceAccount cannot read Pod logs

    about 6 min (estimate) · Manage role based access control (RBAC)

  • Stalled rollout after a bad image

    about 6 min (estimate) · Understand application deployments and how to perform rolling update and rollbacks

  • Lock down database access

    about 6 min (estimate) · Define and enforce Network Policies

  • Worker node NotReady

    about 6 min (estimate) · Troubleshoot clusters and nodes

Practice tasks

Original DamonSec exercises, each mapped to one official competency. They are not exam questions. Every task changes cluster state: run them in a throwaway lab cluster on your own machine, not on this website and not on a cluster you care about. Hints and solutions stay hidden until you open them.

  • Service with no endpointsTroubleshooting · about 15 min (estimate) · Troubleshoot services and networking

    A team deployed nginx behind a ClusterIP Service called web. The Pods are Running, but requests to http://web time out or are refused.

    Objective: Make http://web in namespace cka-lab-svc return the nginx welcome page from inside the cluster. Fix the Service; do not recreate or relabel the Deployment.

    Competency: Troubleshoot services and networking (official)

    Environment

    A disposable cluster you can break: kind, minikube or kubeadm VMs. kubectl configured with cluster-admin access.

    • Nodes can pull nginx:1.27 and busybox:1.36 from Docker Hub.

    Setup

    kubectl create namespace cka-lab-svc
    kubectl -n cka-lab-svc create deployment web --image=nginx:1.27 --replicas=2
    kubectl -n cka-lab-svc apply -f - <<'EOF'
    apiVersion: v1
    kind: Service
    metadata:
      name: web
    spec:
      selector:
        app: frontend
      ports:
      - port: 80
        targetPort: 8080
    EOF

    Done when

    • The EndpointSlice for Service web lists two ready endpoints on port 80.
    • A request to http://web from a Pod in the namespace returns the nginx welcome page.
    • The Deployment web is unchanged.

    Verify

    kubectl -n cka-lab-svc get endpointslices -l kubernetes.io/service-name=web
    kubectl -n cka-lab-svc run probe --image=busybox:1.36 --restart=Never --rm -i -- \
      wget -qO- -T 5 http://web | grep -o '<title>.*</title>'

    Expected output of the last command: <title>Welcome to nginx!</title>

    Hints

    Hint 1

    Compare the SELECTOR column of kubectl get svc web -o wide with the labels from kubectl get pods --show-labels.

    Hint 2

    An EndpointSlice with no endpoints means the selector matches no ready Pods. Once endpoints appear, check which port they point to.

    Hint 3

    There are two separate problems. nginx in this image listens on port 80.

    Reference solution

    Point the selector at the label kubectl create deployment set (app=web):

    kubectl -n cka-lab-svc patch service web --type=merge -p '{"spec":{"selector":{"app":"web"}}}'

    Endpoints now exist but on port 8080, where nothing listens. Fix targetPort:

    kubectl -n cka-lab-svc patch service web --type=json \
      -p '[{"op":"replace","path":"/spec/ports/0/targetPort","value":80}]'

    Cleanup

    kubectl delete namespace cka-lab-svc

    Run end to end by DamonSec on 2026-10-28: kind v0.33 cluster, Kubernetes v1.37.0, default kindnet CNI.

  • Pending Pod with a node selectorTroubleshooting · about 10 min (estimate) · Configure Pod admission and scheduling (limits, node affinity, etc.)

    A reporting Pod must run on a node with fast disks. It has been Pending since it was created.

    Objective: Get Pod report in namespace cka-lab-sched Running without changing the Pod spec. Exactly one worker node should end up eligible.

    Competency: Configure Pod admission and scheduling (limits, node affinity, etc.) (official)

    Environment

    A disposable cluster you can break: kind, minikube or kubeadm VMs. kubectl configured with cluster-admin access. At least one worker node (not control plane).

    • Nodes can pull busybox:1.36.

    Setup

    kubectl create namespace cka-lab-sched
    kubectl -n cka-lab-sched apply -f - <<'EOF'
    apiVersion: v1
    kind: Pod
    metadata:
      name: report
    spec:
      nodeSelector:
        disktype: ssd
      containers:
      - name: app
        image: busybox:1.36
        command: ["sh", "-c", "sleep 3600"]
        resources:
          requests:
            cpu: 100m
            memory: 64Mi
    EOF

    Done when

    • Pod report is Running.
    • kubectl get nodes -l disktype=ssd returns exactly one node, and it is the node the Pod runs on.
    • The Pod was not deleted or recreated (its AGE keeps counting from setup).

    Verify

    kubectl -n cka-lab-sched get pod report -o wide
    kubectl get nodes -l disktype=ssd

    Hints

    Hint 1

    Read the Events section of kubectl describe pod report. The FailedScheduling message says which check failed.

    Hint 2

    nodeSelector is matched against node labels. List them with kubectl get nodes --show-labels.

    Hint 3

    The scheduler keeps retrying Pending Pods. Once a node matches, you do not need to touch the Pod.

    Reference solution

    Pick a worker node and label it:

    NODE=$(kubectl get nodes -l '!node-role.kubernetes.io/control-plane' -o jsonpath='{.items[0].metadata.name}')
    kubectl label node "$NODE" disktype=ssd
    kubectl -n cka-lab-sched wait --for=condition=Ready pod/report --timeout=60s
    kubectl -n cka-lab-sched get pod report -o wide

    Cleanup

    kubectl delete namespace cka-lab-sched
    kubectl label nodes -l disktype=ssd disktype-

    Run end to end by DamonSec on 2026-10-28: kind v0.33 cluster, Kubernetes v1.37.0, default kindnet CNI.

  • Deployment stuck in CreateContainerConfigErrorTroubleshooting · about 15 min (estimate) · Use ConfigMaps and Secrets to configure applications

    An API Deployment reads its mode and log level from a ConfigMap and a token from a Secret. After a manifest change, its Pod never starts.

    Objective: Fix Deployment api in namespace cka-lab-config so the Pod runs and logs mode=production level=info. Do not change the ConfigMap or the Secret.

    Competency: Use ConfigMaps and Secrets to configure applications (official)

    Environment

    A disposable cluster you can break: kind, minikube or kubeadm VMs. kubectl configured with cluster-admin access.

    • Nodes can pull busybox:1.36.

    Setup

    kubectl create namespace cka-lab-config
    kubectl -n cka-lab-config create configmap api-config \
      --from-literal=APP_MODE=production --from-literal=LOG_LEVEL=info
    kubectl -n cka-lab-config create secret generic api-secret --from-literal=API_TOKEN=lab-only-token
    kubectl -n cka-lab-config apply -f - <<'EOF'
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: api
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: api
      template:
        metadata:
          labels:
            app: api
        spec:
          containers:
          - name: api
            image: busybox:1.36
            command: ["sh", "-c", "echo mode=$APP_MODE level=$LOG_LEVEL; sleep 3600"]
            env:
            - name: APP_MODE
              valueFrom:
                configMapKeyRef:
                  name: api-config
                  key: app_mode
            - name: LOG_LEVEL
              valueFrom:
                configMapKeyRef:
                  name: api-config
                  key: LOG_LEVEL
            - name: API_TOKEN
              valueFrom:
                secretKeyRef:
                  name: api-secrets
                  key: API_TOKEN
    EOF

    Done when

    • The Deployment rollout completes and one Pod is Running.
    • The Pod logs show mode=production level=info.
    • API_TOKEN is set inside the container.

    Verify

    kubectl -n cka-lab-config rollout status deployment/api --timeout=90s
    kubectl -n cka-lab-config logs deployment/api
    kubectl -n cka-lab-config exec deployment/api -- sh -c 'test -n "$API_TOKEN" && echo token-present'

    Hints

    Hint 1

    kubectl get pods shows the status. kubectl describe pod shows the reason in Events.

    Hint 2

    The kubelet reports one missing reference at a time. After fixing one, check the events of the new Pod again.

    Hint 3

    ConfigMap keys and object names are case-sensitive. Compare with kubectl get configmap api-config -o yaml and kubectl get secrets.

    Reference solution

    The ConfigMap key is APP_MODE, not app_mode, and the Secret is api-secret, not api-secrets. Patch both references (env index 0 and 2):

    kubectl -n cka-lab-config patch deployment api --type=json -p '[
      {"op":"replace","path":"/spec/template/spec/containers/0/env/0/valueFrom/configMapKeyRef/key","value":"APP_MODE"},
      {"op":"replace","path":"/spec/template/spec/containers/0/env/2/valueFrom/secretKeyRef/name","value":"api-secret"}
    ]'

    kubectl edit deployment api works just as well in the exam environment.

    Cleanup

    kubectl delete namespace cka-lab-config

    Run end to end by DamonSec on 2026-10-28: kind v0.33 cluster, Kubernetes v1.37.0, default kindnet CNI.

  • PVC stuck in PendingTroubleshooting · about 20 min (estimate) · Manage persistent volumes and persistent volume claims

    A Pod that writes to a PersistentVolumeClaim is Pending, and so is its claim. The manifest was copied from another cluster.

    Objective: Get PVC data Bound and Pod writer Running in namespace cka-lab-pvc, using a StorageClass that exists in your cluster.

    Competency: Manage persistent volumes and persistent volume claims (official)

    Environment

    A disposable cluster you can break: kind, minikube or kubeadm VMs. kubectl configured with cluster-admin access. The cluster needs a default StorageClass with a dynamic provisioner (kind and minikube ship one named standard).

    • kubectl get storageclass shows one class marked (default).
    • Nodes can pull busybox:1.36.

    Setup

    kubectl create namespace cka-lab-pvc
    kubectl -n cka-lab-pvc apply -f - <<'EOF'
    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: data
    spec:
      accessModes: ["ReadWriteOnce"]
      storageClassName: fast-ssd
      resources:
        requests:
          storage: 1Gi
    ---
    apiVersion: v1
    kind: Pod
    metadata:
      name: writer
    spec:
      containers:
      - name: app
        image: busybox:1.36
        command: ["sh", "-c", "echo hello > /data/hello.txt && sleep 3600"]
        volumeMounts:
        - name: data
          mountPath: /data
      volumes:
      - name: data
        persistentVolumeClaim:
          claimName: data
    EOF

    Done when

    • PVC data is Bound to a dynamically provisioned PV.
    • Pod writer is Running and /data/hello.txt contains hello.

    Verify

    kubectl -n cka-lab-pvc get pvc data
    kubectl -n cka-lab-pvc exec writer -- cat /data/hello.txt

    Hints

    Hint 1

    Start with kubectl describe pvc data, not the Pod. The Pod is Pending because its claim is.

    Hint 2

    Compare the claim's storageClassName with kubectl get storageclass.

    Hint 3

    storageClassName cannot be changed on an existing claim. You have to recreate it, and the Pod that uses it.

    Hint 4

    If the new claim shows "waiting for first consumer", check the class's VOLUMEBINDINGMODE. That state is expected until a Pod uses the claim.

    Reference solution

    Find the default class, then recreate the claim and the Pod with it:

    SC=$(kubectl get storageclass -o jsonpath='{.items[?(@.metadata.annotations.storageclass\.kubernetes\.io/is-default-class=="true")].metadata.name}')
    echo "default class: $SC"
    kubectl -n cka-lab-pvc delete pod writer
    kubectl -n cka-lab-pvc delete pvc data
    kubectl -n cka-lab-pvc apply -f - <<EOF
    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: data
    spec:
      accessModes: ["ReadWriteOnce"]
      storageClassName: $SC
      resources:
        requests:
          storage: 1Gi
    ---
    apiVersion: v1
    kind: Pod
    metadata:
      name: writer
    spec:
      containers:
      - name: app
        image: busybox:1.36
        command: ["sh", "-c", "echo hello > /data/hello.txt && sleep 3600"]
        volumeMounts:
        - name: data
          mountPath: /data
      volumes:
      - name: data
        persistentVolumeClaim:
          claimName: data
    EOF
    kubectl -n cka-lab-pvc wait --for=condition=Ready pod/writer --timeout=120s

    Leaving storageClassName out entirely also works: the claim then gets the default class.

    Cleanup

    Deleting the namespace deletes the claim; with reclaimPolicy Delete the provisioner removes the PV too. Check with kubectl get pv.

    kubectl delete namespace cka-lab-pvc

    Run end to end by DamonSec on 2026-10-28: kind v0.33 cluster, Kubernetes v1.37.0, default kindnet CNI.

  • Read-only access for a ServiceAccountBuild · about 15 min (estimate) · Manage role based access control (RBAC)

    A log shipper running as ServiceAccount log-reader needs to list Pods and read their logs in one namespace, and nothing else.

    Objective: Allow ServiceAccount log-reader in namespace cka-lab-rbac to get, list and watch Pods and read Pod logs in that namespace only.

    Competency: Manage role based access control (RBAC) (official)

    Environment

    A disposable cluster you can break: kind, minikube or kubeadm VMs. kubectl configured with cluster-admin access.

    Setup

    kubectl create namespace cka-lab-rbac
    kubectl -n cka-lab-rbac create serviceaccount log-reader

    Done when

    • The first two checks below print yes.
    • The last three print no.

    Verify

    SA=system:serviceaccount:cka-lab-rbac:log-reader
    kubectl auth can-i list pods -n cka-lab-rbac --as=$SA
    kubectl auth can-i get pods --subresource=log -n cka-lab-rbac --as=$SA
    kubectl auth can-i delete pods -n cka-lab-rbac --as=$SA
    kubectl auth can-i list secrets -n cka-lab-rbac --as=$SA
    kubectl auth can-i list pods -n default --as=$SA

    Hints

    Hint 1

    Access limited to one namespace means a Role and a RoleBinding, not cluster-scoped objects.

    Hint 2

    Logs are a subresource: pods/log.

    Hint 3

    kubectl create role and kubectl create rolebinding --serviceaccount=<namespace>:<name> are faster than writing YAML.

    Reference solution
    kubectl -n cka-lab-rbac create role log-reader --verb=get,list,watch --resource=pods,pods/log
    kubectl -n cka-lab-rbac create rolebinding log-reader --role=log-reader \
      --serviceaccount=cka-lab-rbac:log-reader

    Cleanup

    kubectl delete namespace cka-lab-rbac

    Run end to end by DamonSec on 2026-10-28: kind v0.33 cluster, Kubernetes v1.37.0, default kindnet CNI.

  • Roll back a broken rolloutTroubleshooting · about 15 min (estimate) · Understand application deployments and how to perform rolling update and rollbacks

    Someone updated Deployment shop to an image tag that does not exist. The rollout has stalled.

    Objective: Restore the last working revision with rollout history (not by typing the old image), then roll out nginx:1.28 with a change-cause recorded.

    Competency: Understand application deployments and how to perform rolling update and rollbacks (official)

    Environment

    A disposable cluster you can break: kind, minikube or kubeadm VMs. kubectl configured with cluster-admin access.

    • Nodes can pull nginx:1.27 and nginx:1.28.

    Setup

    kubectl create namespace cka-lab-rollout
    kubectl -n cka-lab-rollout create deployment shop --image=nginx:1.27 --replicas=3
    kubectl -n cka-lab-rollout rollout status deployment/shop --timeout=120s
    kubectl -n cka-lab-rollout set image deployment/shop nginx=nginx:1.27-doesnotexist

    Done when

    • Deployment shop runs image nginx:1.28 with 3 ready replicas.
    • kubectl rollout history shows the change-cause on the latest revision.
    • At no point did fewer than 3 Pods serve traffic (the default strategy guarantees this here; know why).

    Verify

    kubectl -n cka-lab-rollout rollout status deployment/shop --timeout=120s
    kubectl -n cka-lab-rollout get deployment shop -o jsonpath='{.spec.template.spec.containers[0].image}{"\n"}'
    kubectl -n cka-lab-rollout rollout history deployment/shop

    Hints

    Hint 1

    kubectl get rs shows the old and new ReplicaSets side by side. Count how many old Pods are still running.

    Hint 2

    With 3 replicas, the default 25% maxUnavailable rounds down to 0 and 25% maxSurge rounds up to 1. That is why only one new Pod was attempted.

    Hint 3

    kubectl rollout undo goes back one revision. kubernetes.io/change-cause is the annotation rollout history displays.

    Reference solution
    kubectl -n cka-lab-rollout rollout history deployment/shop
    kubectl -n cka-lab-rollout rollout undo deployment/shop
    kubectl -n cka-lab-rollout rollout status deployment/shop --timeout=120s
    kubectl -n cka-lab-rollout set image deployment/shop nginx=nginx:1.28
    kubectl -n cka-lab-rollout annotate deployment/shop kubernetes.io/change-cause="update to nginx 1.28" --overwrite
    kubectl -n cka-lab-rollout rollout status deployment/shop --timeout=120s
    kubectl -n cka-lab-rollout rollout history deployment/shop

    rollout undo does not create a new revision number for the old template: the restored ReplicaSet moves to the newest revision, and revision 1 disappears from the history. The Deployment's change-cause annotation is copied to its current ReplicaSet, so annotate after set image if you only want the new revision to carry it.

    Cleanup

    kubectl delete namespace cka-lab-rollout

    Run end to end by DamonSec on 2026-10-28: kind v0.33 cluster, Kubernetes v1.37.0, default kindnet CNI.

  • Restrict database access with a NetworkPolicyBuild · about 20 min (estimate) · Define and enforce Network Policies

    Any Pod in the namespace can reach the db Service. Only the api Pod should.

    Objective: In namespace cka-lab-netpol, allow ingress to the db Pods on TCP 80 only from Pods labelled role=api. Block all other ingress to db.

    Competency: Define and enforce Network Policies (official)

    Environment

    A disposable cluster you can break: kind, minikube or kubeadm VMs. kubectl configured with cluster-admin access. The CNI plugin must enforce NetworkPolicy (for example Calico, Cilium, or kindnet in recent kind releases). Some CNIs accept policies without enforcing them.

    • Nodes can pull nginx:1.27 and busybox:1.36.

    Setup

    kubectl create namespace cka-lab-netpol
    kubectl -n cka-lab-netpol create deployment db --image=nginx:1.27
    kubectl -n cka-lab-netpol expose deployment db --port=80
    kubectl -n cka-lab-netpol run api --image=busybox:1.36 --labels=role=api -- sleep 3600
    kubectl -n cka-lab-netpol run other --image=busybox:1.36 --labels=role=other -- sleep 3600
    kubectl -n cka-lab-netpol wait --for=condition=Ready pod --all --timeout=120s

    Before writing a policy, confirm both clients can connect. If they cannot, fix that first.

    kubectl -n cka-lab-netpol exec api -- wget -qO- -T 3 http://db >/dev/null && echo api: allowed
    kubectl -n cka-lab-netpol exec other -- wget -qO- -T 3 http://db >/dev/null && echo other: allowed

    Done when

    • From Pod api, the request to http://db succeeds.
    • From Pod other, the request times out.
    • If other still connects after your policy is applied, your CNI is not enforcing NetworkPolicy.

    Verify

    kubectl -n cka-lab-netpol exec api -- wget -qO- -T 3 http://db >/dev/null && echo api: allowed || echo api: blocked
    kubectl -n cka-lab-netpol exec other -- wget -qO- -T 3 http://db >/dev/null && echo other: allowed || echo other: blocked

    Expected: api: allowed, other: blocked.

    Hints

    Hint 1

    A Pod becomes isolated for ingress as soon as any NetworkPolicy with policyTypes Ingress selects it.

    Hint 2

    spec.podSelector picks the Pods being protected. ingress.from.podSelector picks the allowed clients.

    Hint 3

    kubectl create deployment db labels its Pods app=db. kubectl get pods --show-labels confirms it.

    Reference solution
    kubectl -n cka-lab-netpol apply -f - <<'EOF'
    apiVersion: networking.k8s.io/v1
    kind: NetworkPolicy
    metadata:
      name: db-allow-api
    spec:
      podSelector:
        matchLabels:
          app: db
      policyTypes: ["Ingress"]
      ingress:
      - from:
        - podSelector:
            matchLabels:
              role: api
        ports:
        - protocol: TCP
          port: 80
    EOF

    Cleanup

    kubectl delete namespace cka-lab-netpol

    Run end to end by DamonSec on 2026-10-28: kind v0.33 cluster, Kubernetes v1.37.0, default kindnet CNI.

  • Worker node NotReadyTroubleshooting · about 20 min (estimate) · Troubleshoot clusters and nodes

    After maintenance on a worker node, the node shows NotReady and new Pods are not scheduled on it.

    Objective: Bring the node back to Ready and make sure the fix survives a reboot.

    Competency: Troubleshoot clusters and nodes (official)

    Environment

    A disposable kubeadm cluster on VMs with SSH and sudo on a worker node. (On kind, replace ssh with docker exec into the node container.)

    • SSH access with sudo to one worker node.
    • Do not use a node that runs workloads you need.

    Setup

    Pick a worker and break it. Run the second command on that worker.

    kubectl get nodes
    # on the worker node:
    sudo systemctl disable --now kubelet

    Wait about a minute, until kubectl get nodes shows the node NotReady. Then pretend you did not do the setup.

    Done when

    • The node is Ready.
    • kubelet is active and enabled on the node.

    Verify

    kubectl get nodes
    # on the worker node:
    systemctl is-active kubelet
    systemctl is-enabled kubelet

    Hints

    Hint 1

    kubectl describe node <name>: look at the Conditions table and its messages. Who is supposed to update them?

    Hint 2

    On the node, check the service that reports node status: systemctl status kubelet, then journalctl -u kubelet.

    Hint 3

    A running service is not the whole fix. Check whether it starts at boot.

    Reference solution
    # on the worker node:
    sudo systemctl enable --now kubelet
    systemctl status kubelet --no-pager
    # back on your workstation (Ctrl-C to stop watching):
    kubectl get nodes --watch

    Cleanup

    Nothing to remove. If the node stayed NotReady for more than about 5 minutes, Pods on it may have been evicted and rescheduled elsewhere; check with kubectl get pods -A -o wide.

    Checked by DamonSec on 2026-10-28 on a kind worker node (Kubernetes v1.37.0), using docker exec in place of SSH. Not yet run on kubeadm VMs.

  • CrashLoopBackOff from a missing settingTroubleshooting · about 10 min (estimate) · Manage and evaluate container output streams

    A worker Deployment restarts constantly. By the time you run kubectl logs, the container has often just restarted and shows little.

    Objective: Use the container's output to find why it exits, then fix Deployment worker in namespace cka-lab-logs. The queue URL is redis://queue:6379.

    Competency: Manage and evaluate container output streams (official)

    Environment

    A disposable cluster you can break: kind, minikube or kubeadm VMs. kubectl configured with cluster-admin access.

    • Nodes can pull busybox:1.36.

    Setup

    kubectl create namespace cka-lab-logs
    kubectl -n cka-lab-logs apply -f - <<'EOF'
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: worker
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: worker
      template:
        metadata:
          labels:
            app: worker
        spec:
          containers:
          - name: worker
            image: busybox:1.36
            command:
            - sh
            - -c
            - |
              echo "starting worker"
              if [ -z "$QUEUE_URL" ]; then
                echo "fatal: QUEUE_URL is not set" >&2
                exit 1
              fi
              echo "connected to $QUEUE_URL"
              sleep 3600
    EOF

    Done when

    • The Deployment rollout completes and the new Pod has 0 restarts.
    • The Pod logs contain connected to redis://queue:6379.

    Verify

    kubectl -n cka-lab-logs rollout status deployment/worker --timeout=90s
    kubectl -n cka-lab-logs get pods -l app=worker
    kubectl -n cka-lab-logs logs deployment/worker

    Hints

    Hint 1

    kubectl get pods shows the RESTARTS count. kubectl describe pod shows the last state and exit code.

    Hint 2

    kubectl logs <pod> shows the current container, or its output if it has already exited. kubectl logs <pod> --previous shows the instance before that, while it is still kept. stderr is included in both.

    Hint 3

    kubectl rollout status can report success for a crashing Pod that has no readiness probe, because the container is briefly Running. Trust RESTARTS, not the rollout message.

    Hint 4

    kubectl set env changes the Pod template and triggers a new rollout.

    Reference solution
    POD=$(kubectl -n cka-lab-logs get pod -l app=worker -o jsonpath='{.items[0].metadata.name}')
    kubectl -n cka-lab-logs logs "$POD"
    kubectl -n cka-lab-logs logs "$POD" --previous   # may fail if that instance is already gone
    kubectl -n cka-lab-logs set env deployment/worker QUEUE_URL=redis://queue:6379
    kubectl -n cka-lab-logs rollout status deployment/worker --timeout=90s

    Cleanup

    kubectl delete namespace cka-lab-logs

    Run end to end by DamonSec on 2026-10-28: kind v0.33 cluster, Kubernetes v1.37.0, default kindnet CNI.

Your data

Progress is stored only in this browser (localStorage). It is not sent to DamonSec and does not sync across devices or browsers. Clearing site data removes it. Export a JSON file to back it up or move it to another browser.

Replace your progress?

Reset all progress?

This deletes every status, note, attempt and goal saved in this browser (0 skills with a status, 0 attempts). It cannot be undone.

Export first if you might want it back.

How the numbers work

  • Status is yours. Each skill has four states you set by hand. Logging an attempt never changes it.
  • Coverage is skills with any status other than Not started, divided by 27.
  • Independent is skills marked Can do independently, divided by 27. Skills are not weighted by exam percentage.
  • This week adds the minutes of attempts dated Monday to Sunday of the current week, in your device's time zone.
  • Practice today picks up to three skills, in this order: skills whose latest attempt was unsuccessful or needed hints; skills you are learning that have not been practiced for 3 days or more; skills not started yet, spread across domains from the heaviest exam weight down; and skills marked independent that are due for review after 14 days.
  • There is no pass prediction. The tracker only reflects what you record.

Curriculum source

Domains, weights and competency wording are copied from the official curriculum (CKA_Curriculum_v1.37.pdf, Kubernetes v1.37), checked against both sources below on Wed, Oct 28, 2026. Skill summaries, documentation picks and practice tasks are written by DamonSec.

  • Domains, weights and all 27 competencies matched between the CNCF PDF and the Linux Foundation page on the verification date.
  • The Linux Foundation page states the exam is based on Kubernetes v1.37. The PDF's internal timestamp is from December 2024, so the competency wording has not changed since then; only the version label has.
  • The PDF titles the networking domain "Servicing and Networking"; the Linux Foundation page uses "Services & Networking", which is used here.

Domains: Storage 10% · Troubleshooting 30% · Workloads & Scheduling 15% · Cluster Architecture, Installation & Configuration 25% · Services & Networking 20%. Exam details change; check the Linux Foundation page before you book.

More tools: DamonSec tools