CKA (CNCF) cheat sheet
CKA · Keep the key ideas within reach.
Cluster Architecture, Installation & Configuration
kubeadm init --pod-network-cidr=10.244.0.0/16 sets the pod IP range; the CNI plugin must be configured with the same CIDR, otherwise pods are scheduled but receive no routes.
Static pod manifests live in /etc/kubernetes/manifests; the kubelet watches that directory, so adding or editing a YAML there starts, restarts or removes the mirrored static pod automatically.
Cluster PKI lives under /etc/kubernetes/pki (ca, apiserver, front-proxy, etcd); kubeadm certs check-expiration reports remaining validity and kubeadm certs renew all reissues the certificates.
The admin kubeconfig is written to /etc/kubernetes/admin.conf; copying it to $HOME/.kube/config grants kubectl access with cluster-admin rights.
RBAC: Role and RoleBinding are namespaced, ClusterRole and ClusterRoleBinding are cluster-scoped; a RoleBinding may reference a ClusterRole to grant those permissions inside a single namespace.
kubectl auth can-i --as -n issues a SubjectAccessReview, so permissions can be tested without the subject's credentials.
Upgrade order: kubeadm upgrade apply on the first control-plane node, kubeadm upgrade node on the others, then drain and upgrade kubelet and kubectl packages on each node before uncordoning.
A worker joins with kubeadm join :6443 --token <id.secret> --discovery-token-ca-cert-hash sha256:; bootstrap tokens expire after 24 hours and are listed with kubeadm token list.
kubelet configuration is read from /var/lib/kubelet/config.yaml and the systemd drop-in /etc/systemd/system/kubelet.service.d/10-kubeadm.conf.
Workloads & Scheduling
Requests are what the scheduler uses to find a node with sufficient allocatable resources; limits are what the cgroups enforce at runtime, so a container without limits can consume the whole node.
QoS classes: Guaranteed requires requests equal to limits for CPU and memory on every container, BestEffort requires no requests or limits at all, and everything else is Burstable; eviction order is BestEffort, then Burstable, then Guaranteed.
nodeSelector is an exact label match; nodeAffinity supports operators (In, NotIn, Exists, Gt, Lt) plus requiredDuringScheduling versus preferredDuringScheduling semantics.
Taint effects are NoSchedule, PreferNoSchedule and NoExecute; a toleration must match key, value and effect, and omitting the effect tolerates every effect for that key.
Topology spread constraints use maxSkew, topologyKey, labelSelector and whenUnsatisfiable (DoNotSchedule for a hard filter, ScheduleAnyway for a scoring hint).
DaemonSet pods receive automatic tolerations for not-ready, unreachable, disk-pressure, memory-pressure, pid-pressure and unschedulable, so they still run on cordoned or pressured nodes.
RollingUpdate defaults to maxSurge 25% and maxUnavailable 25%; setting both to 0 deadlocks the rollout, and Recreate terminates every pod before starting new ones.
A pod whose priorityClassName has a higher value can preempt lower-priority pods on a node when the PriorityClass has preemptionPolicy PreemptLowerPriority.
HorizontalPodAutoscaler requires metrics-server; autoscaling/v2 computes CPU utilisation as a percentage of the container's resource request, so containers without requests never scale on that metric.
Services & Networking
Service types: ClusterIP gets only a virtual IP, NodePort also allocates 30000-32767 on every node, LoadBalancer adds an external load balancer on top of NodePort, and ExternalName returns a CNAME without proxying.
A Service selects pods by label; EndpointSlices (and the legacy Endpoints object) list only Ready pods, so a failing readiness probe removes the pod from load balancing.
port is the Service port and targetPort is the container port; a mismatched targetPort yields connection refused while the Service object itself still looks healthy.
A headless Service (clusterIP: None) allocates no virtual IP and returns one A record per pod, which StatefulSets use for stable names like ...svc.cluster.local.
Cluster DNS is CoreDNS in kube-system, exposed as Service kube-dns (default 10.96.0.10); names resolve as ..svc.cluster.local or as bare inside the same namespace.
NetworkPolicy rules are additive allow-lists; an empty podSelector with policyTypes Ingress denies all ingress in that namespace, and a CNI that ignores policy (plain Flannel) enforces nothing.
Ingress needs an IngressClass and a running controller (nginx, traefik); the ingressClassName field or the default-class annotation decides which controller reconciles the object.
kube-proxy runs in iptables or ipvs mode; ipvs requires the ip_vs kernel modules and keeps constant-time lookup as the number of Services grows.
CNI binaries live in /opt/cni/bin and configs in /etc/cni/net.d; the pod CIDR must not overlap the node network or the Service CIDR.
Storage
emptyDir is deleted when the pod is removed from the node; hostPath maps a directory on the node and ties the data to that specific node.
Access modes: ReadWriteOnce mounts read-write on one node, ReadOnlyMany on many nodes read-only, ReadWriteMany on many nodes read-write, and ReadWriteOncePod on exactly one pod cluster-wide.
PV reclaim policies are Retain (volume and data kept in Released state until manually cleaned), Delete (backing storage destroyed) and the deprecated Recycle.
A PVC binds to a PV when PV capacity is at least the request, the access modes cover the request, storageClassName matches, and any selector labels match.
volumeBindingMode: WaitForFirstConsumer delays provisioning and binding until a pod using the PVC is scheduled, so zone- or node-constrained volumes land in the right place.
Dynamic provisioning comes from the CSI provisioner named in the StorageClass; with no matching StorageClass and no default class the PVC stays Pending.
StatefulSet volumeClaimTemplates create one PVC per replica named --, and those PVCs persist after the pod is deleted.
Resizing a PVC requires allowVolumeExpansion: true on the StorageClass plus driver support; requests may grow but never shrink.
A subPath mount mounts a path inside a volume rather than the whole volume, and subPath mounts of a ConfigMap do not receive later ConfigMap updates.
Troubleshooting
kubectl describe pod prints Events last; scheduling failures such as Insufficient cpu, node affinity mismatch or unbound PVC appear there rather than in container logs.
CrashLoopBackOff means the container starts and exits repeatedly; kubectl logs --previous shows the crashed instance's output, and exit code 137 indicates SIGKILL, commonly an OOM kill.
ImagePullBackOff and ErrImagePull point to a wrong image name or tag, a missing imagePullSecrets, or a node that cannot reach the registry.
Pending with no events usually means unsatisfiable scheduling constraints; the message about unbound immediate PersistentVolumeClaims points to storage rather than capacity.
For Node NotReady, run systemctl status kubelet and journalctl -u kubelet on the node, and verify the runtime endpoint in /var/lib/kubelet/kubeadm-flags.env.
When kubectl cannot reach the API server, inspect control-plane static pods with crictl ps -a and crictl logs against containerd, and read the manifests in /etc/kubernetes/manifests.
From a control-plane node: etcdctl --endpoints=https://127.0.0.1:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=... --key=... endpoint health verifies the etcd cluster.
A Service with no traffic: kubectl get endpointslices -l kubernetes.io/service-name= shows backing IPs; an empty list means the selector does not match Ready pods or the port mapping is wrong.
Expired-certificate symptoms such as x509: certificate has expired are confirmed by kubeadm certs check-expiration and fixed with kubeadm certs renew all plus a control-plane static pod restart.