CKA — Common Mistakes

8 minute read

CKA Exam Domain

All Domains — These mistakes span every domain on the exam.

Thousands of candidates fail the CKA not because they lack knowledge, but because they make avoidable mistakes under exam pressure. Here are the top 10 mistakes — learn them now so you don’t make them on exam day.

Mistake 1: Forgetting to Switch Context

This is the #1 reason candidates lose points.

Every question specifies a cluster context:

Context: kubectl config use-context cluster2

If you don’t switch, you’re working on the wrong cluster. Your work won’t be graded, and you might even break another question’s environment.

The fix: Make it the FIRST thing you do for every question.

kubectl config use-context cluster2

Verify:

kubectl config current-context

Make it a reflex. Read the context line → switch → then read the rest of the question.

Mistake 2: Wrong Namespace

Many candidates create resources in the default namespace when the question asks for a specific one.

Example trap:

“Create a Deployment named api in namespace production…”

If you run:

k create deployment api --image=nginx --replicas=3

That’s created in default. Zero points.

The fix: Always specify the namespace explicitly:

k create deployment api --image=nginx --replicas=3 -n production

Or set the namespace for your current context:

k config set-context --current --namespace=production

Pro tip: Check if the namespace exists first. If it doesn’t, create it:

k create namespace production

Mistake 3: YAML Indentation Errors

YAML is whitespace-sensitive. A single misplaced space breaks everything.

Common scenario: You paste YAML from kubernetes.io/docs into vi, and vi’s auto-indent adds extra spaces:

# This is WRONG — extra indentation from auto-indent
spec:
    containers:
        - name: nginx
            image: nginx
# This is CORRECT
spec:
  containers:
  - name: nginx
    image: nginx

The fix:

  1. Always run :set paste in vi before pasting
  2. After saving, validate before applying:
k apply --dry-run=client -f file.yaml

If you see error: error validating, your YAML is broken. Fix it before applying.

Mistake 4: Spending Too Long on One Question

Candidates often get emotionally attached to a difficult question and refuse to move on.

The math: If you spend 15 minutes on a 7% question and run out of time for three 4% questions (12% total), you’ve lost a net of 5%.

The fix: Set a mental timer for each question:

  • 4% questions: 3–5 minutes max
  • 7% questions: 5–8 minutes max
  • 10%+ questions: 8–12 minutes max

If you hit the limit, flag it and move on. Come back in Pass 3 with fresh eyes.

Mistake 5: Not Verifying Your Work

You created the resource. You think it’s correct. But did you actually check?

The fix: Always verify after creating or modifying resources:

# Check resource exists
k get deployment web -n production

# Check details
k describe deployment web -n production

# For RBAC, test permissions
k auth can-i get pods --as jane -n production

# For Services, check endpoints exist
k get endpoints my-service

# For NetworkPolicies, verify they're applied
k get networkpolicy -n secure

# For Pods, verify they're Running
k get pods -n production

Verification takes 10–15 seconds and catches mistakes that would cost you the entire question.

Mistake 6: Forgetting etcd Flags

etcd commands require TLS certificates. Forgetting even one flag means the command fails.

The wrong way:

etcdctl snapshot save /opt/backup.db

The right way:

ETCDCTL_API=3 etcdctl snapshot save /opt/backup.db \
  --cacert=/etc/kubernetes/pki/etcd/ca.crt \
  --cert=/etc/kubernetes/pki/etcd/server.crt \
  --key=/etc/kubernetes/pki/etcd/server.key \
  --endpoints=https://127.0.0.1:2379

How to find the correct paths: Check the running etcd Pod:

k describe pod etcd-controlplane -n kube-system

Look at the --cert-file, --key-file, --trusted-ca-file, and --listen-client-urls flags.

Mistake 7: Not Reading the Question Fully

Exam questions often have subtle requirements buried in the text:

“Create a Pod named web with image nginx:1.27 in namespace dev, with label tier=frontend, and a resource limit of 256Mi memory.”

Candidates often create the Pod with the image but forget:

  • The namespace (dev)
  • The label (tier=frontend)
  • The resource limit (256Mi)

Missing any of these means partial or zero credit.

The fix: Before typing anything, list every requirement from the question:

  1. Pod name: web
  2. Image: nginx:1.27
  3. Namespace: dev
  4. Label: tier=frontend
  5. Memory limit: 256Mi

Then verify each one after creating the resource.

Mistake 8: Using Deprecated Commands

Kubernetes commands evolve. Some candidates study from outdated material.

Deprecated (don’t use):

# WRONG — --generator was removed
kubectl run web --generator=deployment/v1beta1 --image=nginx

# WRONG — kubectl run no longer creates Deployments
kubectl run web --image=nginx --replicas=3

Current commands:

# Create a Pod
kubectl run web --image=nginx

# Create a Deployment
kubectl create deployment web --image=nginx --replicas=3

Rule of thumb:

  • kubectl run = Pods only
  • kubectl create deployment = Deployments
  • kubectl create = most other resource types

Mistake 9: Not Draining Nodes Before Upgrade

When upgrading a worker node, you must drain it first to safely evict all workloads.

The wrong way:

# Skipping drain — Pods may be disrupted during upgrade
apt-get update && apt-get install -y kubeadm=1.31.0-00

The right way:

# Step 1: Drain the node (from controlplane)
kubectl drain worker-1 --ignore-daemonsets --delete-emptydir-data

# Step 2: SSH to the node and upgrade
ssh worker-1
apt-get update && apt-get install -y kubeadm=1.31.0-1.1
kubeadm upgrade node
apt-get install -y kubelet=1.31.0-1.1 kubectl=1.31.0-1.1
systemctl daemon-reload
systemctl restart kubelet

# Step 3: Uncordon the node (from controlplane)
kubectl uncordon worker-1

Forgetting to drain means Pods may be lost during the upgrade, and the grader may check for proper procedure.

Mistake 10: Forgetting DNS Port in NetworkPolicy Egress

This is a sneaky one. When you create a default-deny egress NetworkPolicy, you block all outgoing traffic — including DNS resolution (UDP/TCP port 53).

The problem:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-egress
  namespace: secure
spec:
  podSelector: {}
  policyTypes:
  - Egress

This blocks DNS. Pods in secure namespace can’t resolve any Service names.

The fix — allow DNS egress:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-egress
  namespace: secure
spec:
  podSelector: {}
  policyTypes:
  - Egress
  egress:
  - to:
    - namespaceSelector: {}
    ports:
    - protocol: UDP
      port: 53
    - protocol: TCP
      port: 53

Always include DNS egress unless the question explicitly says DNS isn’t needed.

CKA vs CKAD Mistakes

Some mistakes are specific to the CKA (as opposed to CKAD). Here’s what to watch for:

CKA-Specific Area Common Mistake How to Avoid
etcd backup/restore Forgetting TLS flags Get certs from kubectl describe pod etcd-controlplane -n kube-system
kubeadm upgrade Not draining node first Always: drain → upgrade → uncordon
kubelet troubleshooting Not checking journalctl -u kubelet Always check service logs first
Static Pods Wrong manifest directory Check --pod-manifest-path in kubelet config
Cluster DNS Not checking CoreDNS Pods kubectl get pods -n kube-system -l k8s-app=kube-dns
Node troubleshooting Not using systemctl status kubelet Always check kubelet status first on NotReady nodes
RBAC Confusing Role vs ClusterRole Role = namespaced, ClusterRole = cluster-wide
Certificates Not knowing cert locations Default: /etc/kubernetes/pki/

Practice Questions

These are “find the mistake” scenarios. Each one contains an error — find it.

Question 1: Spot the Error

A candidate runs this to create an RBAC setup:

kubectl create role pod-reader --verb=get,list --resource=pods -n team-blue
kubectl create rolebinding read-pods --role=pod-reader --user=jane

The candidate tests with kubectl auth can-i get pods --as jane -n team-blue and gets “no.” What went wrong?

Show Answer

The RoleBinding was created in the default namespace. The candidate forgot -n team-blue on the RoleBinding command.

Correct:

kubectl create rolebinding read-pods --role=pod-reader --user=jane -n team-blue

A RoleBinding must be in the same namespace as the Role it references.

Question 2: Spot the Error

A candidate’s etcd backup command fails:

ETCDCTL_API=3 etcdctl snapshot save /opt/backup.db \
  --cacert=/etc/kubernetes/pki/ca.crt \
  --cert=/etc/kubernetes/pki/etcd/server.crt \
  --key=/etc/kubernetes/pki/etcd/server.key
Show Answer

Wrong CA certificate path. The command uses /etc/kubernetes/pki/ca.crt (the Kubernetes API CA), but etcd requires its own CA at /etc/kubernetes/pki/etcd/ca.crt.

Also missing --endpoints=https://127.0.0.1:2379.

Correct:

ETCDCTL_API=3 etcdctl snapshot save /opt/backup.db \
  --cacert=/etc/kubernetes/pki/etcd/ca.crt \
  --cert=/etc/kubernetes/pki/etcd/server.crt \
  --key=/etc/kubernetes/pki/etcd/server.key \
  --endpoints=https://127.0.0.1:2379

Question 3: Spot the Error

A candidate tries to create a NetworkPolicy to allow ingress from Pods with label app=frontend:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-frontend
  namespace: secure
spec:
  podSelector:
    matchLabels:
      app: frontend
  policyTypes:
  - Ingress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: frontend

But Pods with label app=backend in the secure namespace can still receive all traffic. Why?

Show Answer

The podSelector targets the wrong Pods. The spec.podSelector selects Pods with app=frontend, meaning this policy only applies TO frontend Pods. Backend Pods are not selected by any NetworkPolicy, so they allow all traffic by default.

Fix — target backend Pods and allow ingress from frontend:

spec:
  podSelector:
    matchLabels:
      app: backend
  policyTypes:
  - Ingress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: frontend

Question 4: Spot the Error

After upgrading a worker node, the candidate runs:

kubectl uncordon worker-1
kubectl get nodes

The node shows Ready,SchedulingDisabled. What happened?

Show Answer

The uncordon command might have been run before kubelet was restarted. After upgrading kubeadm and kubelet packages, you must restart kubelet:

systemctl daemon-reload
systemctl restart kubelet

If kubelet isn’t running correctly, the node may not properly respond to the uncordon. Check:

systemctl status kubelet

Also ensure that kubeadm upgrade node was executed on the worker node before restarting kubelet.

Question 5: Spot the Error

A candidate creates a static Pod manifest at /etc/kubernetes/manifests/nginx.yaml on worker-1, but the Pod never appears. All other static Pods on the controlplane work fine. What’s the issue?

Show Answer

Static Pods are managed by the kubelet on each node. The manifest must be placed on the node where you want the Pod to run. The correct path depends on the kubelet’s --pod-manifest-path configuration on that specific node.

Check the kubelet configuration on worker-1:

ssh worker-1
cat /var/lib/kubelet/config.yaml | grep staticPodPath

The staticPodPath might be different from /etc/kubernetes/manifests/ on worker nodes, or the directory might not exist. Also verify kubelet is running:

systemctl status kubelet

Next: Mock Exam — Part 1 →

Updated: