CKA study materials
CKA study resources

CKA (Other exams) common mistakes

CKA · Understand the traps and how to avoid them.

Mistake 1

Editing a running object in place with `kubectl edit` during a task and losing track of what the file originally contained, then being unable to revert or confirm the change applied.

Candidates are used to imperative editing from daily work, but the exam rewards reproducible, declarative changes; kubectl edit opens an ephemeral buffer and a malformed YAML save silently leaves the object unchanged or half-applied.

What to do instead

Generate or save manifests to disk (kubectl get -o yaml > obj.yaml or --dry-run=client -o yaml), edit the file, then kubectl apply -f obj.yaml. Verify with kubectl diff -f obj.yaml before applying and kubectl get -o yaml after.

Mistake 2

Creating a Pod or Deployment without the required node placement and watching it stay Pending, then moving on to the next task without resolving it.

Scheduling constraints (nodeSelector, affinity, taints/tolerations, resource requests) are easy to omit when writing a manifest from memory, and a Pending pod does not produce an error at creation time.

What to do instead

Always run kubectl get pods -o wide and kubectl describe pod after creating a workload; read the Events section for FailedScheduling messages. Add the missing toleration, nodeSelector, or lower the requests to fit allocatable capacity, then confirm the pod reaches Running.

Mistake 3

Writing a NetworkPolicy that selects the target pods but forgets that an empty `podSelector` in `ingress.from` or a missing `namespaceSelector` changes the meaning to allow-all or same-namespace-only.

NetworkPolicy semantics are inverted from intuition: an empty selector matches everything, and the absence of an ingress stanza means deny-all for selected pods. Candidates copy a skeleton and mis-scope the peers.

What to do instead

State the intent explicitly: use podSelector: {matchLabels: {...}} with concrete labels, add namespaceSelector when cross-namespace traffic is required, and remember egress rules are separate. Test with kubectl exec and nc/curl from a pod on each side, and confirm the CNI plugin actually enforces policy.

Mistake 4

Mounting a PersistentVolumeClaim into a pod without checking that the PVC is Bound, then debugging the pod instead of the claim.

A pod referencing an unbound or Pending PVC stays in ContainerCreating with a vague event, and candidates focus on the container image or command rather than storage provisioning.

What to do instead

Run kubectl get pvc first; if Pending, kubectl describe pvc shows why (no matching PV, wrong storageClassName, WaitForFirstConsumer, capacity mismatch). Fix access modes, storage class, or capacity, confirm Bound, then recheck the pod.

Mistake 5

Running `kubeadm init` and then leaving the control plane without a working CNI, so CoreDNS and the API server's pod networking never become Ready.

kubeadm does not install a network plugin; candidates see the control plane come up and assume the cluster is finished, then fail later tasks that depend on pod-to-pod or service DNS.

What to do instead

Install a CNI plugin immediately after init (for example a manifest applied with kubectl apply -f), then verify kubectl get pods -n kube-system shows CoreDNS Running and kubectl run a test pod that can resolve a Service name with nslookup.

Mistake 6

Joining a worker with a stale or expired bootstrap token, or reusing a token after the 24-hour TTL, and not reading the join error.

Tokens generated by kubeadm token create expire and the join command embeds the CA cert hash; candidates paste an old command from notes or a previous attempt.

What to do instead

On the control plane run kubeadm token create --print-join-command to get a fresh command including the correct --discovery-token-ca-cert-hash, then run it on the node and confirm with kubectl get nodes that it reports Ready.

Mistake 7

Exposing a Deployment with a Service whose `selector` does not match the pod template labels, then assuming the Service is broken because `kubectl get endpoints` is empty.

Labels are typed twice (in the Deployment template and the Service selector) and a typo or extra label breaks the link silently; the Service still gets a ClusterIP so it looks healthy.

What to do instead

Compare kubectl get pods --show-labels with kubectl describe svc <name>; fix the selector to match exactly. Confirm kubectl get endpoints <name> lists the pod IPs, then test with kubectl run tmp --rm -it --image=busybox -- wget -qO- <svc>:<port>.

Mistake 8

Diagnosing a failing node by restarting kubelet or the container runtime before reading logs and the node conditions.

Troubleshooting tasks reward evidence gathering, and a restart can clear the very state (CrashLoopBackOff, NotReady reason, eviction events) needed to answer the question.

What to do instead

Follow a fixed order: kubectl get nodes and kubectl describe node for conditions and taints, journalctl -u kubelet -n 200 on the node, crictl ps -a and crictl logs for container state, and df -h/free -m for disk and memory pressure. Fix the root cause, then verify the node returns to Ready.

Mistake 9

Creating a PV/PVC pair with mismatched `storageClassName`, `accessModes`, or capacity and expecting the binder to reconcile them.

Static binding requires an exact match on capacity (PV at least as large), access modes, and storage class; an empty storageClassName on the PVC only matches PVs with no class.

What to do instead

Inspect the PV with kubectl get pv -o yaml and set the PVC to the same class and a request no larger than the PV capacity. For dynamic provisioning, create a StorageClass or use the cluster default and let the PVC bind.

Mistake 10

Running a privileged or hostPath pod without setting the required securityContext, or forgetting to apply a namespace-scoped change in the namespace the task names.

Tasks specify namespace, service account, and security contexts precisely; candidates default to default namespace or omit securityContext.privileged: true and the pod is rejected or runs with the wrong identity.

What to do instead

Include metadata.namespace in every manifest and pass -n <namespace> to kubectl. For privileged workloads add securityContext: {privileged: true} and the correct serviceAccountName; verify with kubectl get pod -o yaml that the fields persisted and the pod is Running.