DEV Community

The Cyber Sidekick
The Cyber Sidekick

Posted on

2026 CKA Exam - Scenario 8 Install a CNI and fix the flannel pod-CIDR mismatch (CKA Services & Networking)

Install a CNI and fix the pod-CIDR mismatch

The cluster is running, but every node is NotReady, because no network plugin is installed. The exam gives you a flannel manifest and asks you to install and configure a CNI. Let's apply it, watch it fail, find out why, and fix it.

🎥 Watch the video: https://www.youtube.com/watch?v=wzFE66kfRl4

This is a CKA Services & Networking walkthrough. Every command below is real output from a live cluster, and you can reproduce the whole thing yourself (scripts at the end).

The scenario

Here is the setup. A fresh cluster has no CNI, so its nodes are NotReady and CoreDNS is stuck Pending. You are handed a flannel manifest and told to install a network plugin of your choice. The catch, which you only discover after applying, is that the manifest's network does not match the cluster's pod CIDR.

  • A fresh cluster with NO CNI: nodes NotReady, CoreDNS Pending
  • You're handed a flannel manifest and told to install a CNI
  • The manifest's Network (10.244.0.0/16) != the cluster pod CIDR (192.168.0.0/16)
  • Install it, fix the mismatch, and prove pods can talk

How flannel and CNIs work

A CNI plugin is what gives pods IP addresses and wires up pod-to-pod routing; without one the kubelet reports the node NotReady. flannel runs as a DaemonSet, one pod per node, and reads its settings from a ConfigMap called kube-flannel-cfg. The important field is net-conf.json Network, the address space flannel hands out. Because flannel runs with kube-subnet-mgr, it also reads each node's assigned podCIDR, and it refuses to start if that podCIDR is not inside its configured Network. Match those two and it works.

No CNI: nodes NotReady

Start by confirming the starting state. Every node is NotReady, the classic symptom of a missing CNI. And in kube-system, CoreDNS is Pending because it has no pod network to join yet. Everything else the control plane needs is up, so this really is just the network plugin that's missing.

$ kubectl get nodes
NAME                          STATUS     ROLES           AGE   VERSION
cka-scenario8-control-plane   NotReady   control-plane   8d    v1.36.1
cka-scenario8-worker          NotReady   <none>          8d    v1.36.1

$ kubectl get pods -n kube-system -o wide
NAME                                                  READY   STATUS    RESTARTS   AGE   IP            NODE                          NOMINATED NODE   READINESS GATES
coredns-589f44dc88-8m6kd                              1/1     Running   0          8d    192.168.1.4   cka-scenario8-worker          <none>           <none>
coredns-589f44dc88-shgqb                              1/1     Running   0          8d    192.168.1.3   cka-scenario8-worker          <none>           <none>
etcd-cka-scenario8-control-plane                      1/1     Running   0          8d    172.18.0.13   cka-scenario8-control-plane   <none>           <none>
kube-apiserver-cka-scenario8-control-plane            1/1     Running   0          8d    172.18.0.13   cka-scenario8-control-plane   <none>           <none>
kube-controller-manager-cka-scenario8-control-plane   1/1     Running   0          8d    172.18.0.13   cka-scenario8-control-plane   <none>           <none>
kube-proxy-gkw9p                                      1/1     Running   0          8d    172.18.0.14   cka-scenario8-worker          <none>           <none>
kube-proxy-nxbwr                                      1/1     Running   0          8d    172.18.0.13   cka-scenario8-control-plane   <none>           <none>
kube-scheduler-cka-scenario8-control-plane            1/1     Running   0          8d    172.18.0.13   cka-scenario8-control-plane   <none>           <none>
Enter fullscreen mode Exit fullscreen mode

Apply flannel (it CrashLoops)

Now install flannel by applying the manifest. It creates the kube-flannel namespace, the ConfigMap, and the DaemonSet. But when you look at the pods a few seconds later, they are not Running: they're in CrashLoopBackOff or Error. Applying the manifest was necessary, but on this cluster it is not sufficient.

$ kubectl apply -f kube-flannel.yml
namespace/kube-flannel created
serviceaccount/flannel created
clusterrole.rbac.authorization.k8s.io/flannel unchanged
clusterrolebinding.rbac.authorization.k8s.io/flannel unchanged
configmap/kube-flannel-cfg created
daemonset.apps/kube-flannel-ds created

$ kubectl -n kube-flannel get pods -o wide
NAME                    READY   STATUS   RESTARTS     AGE   IP            NODE                          NOMINATED NODE   READINESS GATES
kube-flannel-ds-6mhjm   0/1     Error    1 (9s ago)   12s   172.18.0.13   cka-scenario8-control-plane   <none>           <none>
kube-flannel-ds-jq4n7   0/1     Error    1 (9s ago)   12s   172.18.0.14   cka-scenario8-worker          <none>           <none>
Enter fullscreen mode Exit fullscreen mode

Read the lease error

Don't guess, read the logs. The flannel pod says it failed to acquire a lease, because the node's pod subnet, a slice of 192.168.0.0/16, is not inside the flannel net configuration of 10.244.0.0/16. That's the whole problem in one line: the manifest ships a default Network that does not match how this cluster was built. The cluster's pod CIDR is authoritative, so flannel is the thing that has to change.

$ kubectl -n kube-flannel logs <flannel-pod>
...
I0710 11:54:49.724901       1 kube.go:163] Node controller sync successful
I0710 11:54:49.724926       1 main.go:252] Created subnet manager: Kubernetes Subnet Manager - cka-scenario8-control-plane
I0710 11:54:49.724929       1 main.go:255] Installing signal handlers
I0710 11:54:49.725064       1 main.go:534] Found network config - Backend type: vxlan
I0710 11:54:49.726846       1 kube.go:737] List of node(cka-scenario8-control-plane) annotations: map[string]string{"flannel.alpha.coreos.com/backend-data":"{\"VNI\":1,\"VtepMAC\":\"76:f3:d3:22:ef:55\"}", "flannel.alpha.coreos.com/backend-type":"vxlan", "flannel.alpha.coreos.com/kube-subnet-manager":"true", "flannel.alpha.coreos.com/public-ip":"172.18.0.13", "node.alpha.kubernetes.io/ttl":"0", "volumes.kubernetes.io/controller-managed-attach-detach":"true"}
I0710 11:54:49.726881       1 match.go:211] Determining IP address of default interface
I0710 11:54:49.727126       1 match.go:269] Using interface with name eth0 and address 172.18.0.13
I0710 11:54:49.727151       1 match.go:291] Defaulting external address to interface address (172.18.0.13)
I0710 11:54:49.727200       1 vxlan.go:128] VXLAN config: VNI=1 Port=0 GBP=false Learning=false DirectRouting=false
I0710 11:54:49.728578       1 kube.go:704] List of node(cka-scenario8-control-plane) annotations: map[string]string{"flannel.alpha.coreos.com/backend-data":"{\"VNI\":1,\"VtepMAC\":\"76:f3:d3:22:ef:55\"}", "flannel.alpha.coreos.com/backend-type":"vxlan", "flannel.alpha.coreos.com/kube-subnet-manager":"true", "flannel.alpha.coreos.com/public-ip":"172.18.0.13", "node.alpha.kubernetes.io/ttl":"0", "volumes.kubernetes.io/controller-managed-attach-detach":"true"}
I0710 11:54:49.728602       1 vxlan.go:199] Interface flannel.1 mac address set to: 76:f3:d3:22:ef:55
E0710 11:54:49.729096       1 main.go:381] Error registering network: failed to acquire lease: subnet "10.244.0.0/16" specified in the flannel net config doesn't contain "192.168.0.0/24" PodCIDR of the "cka-scenario8-control-plane" node
I0710 11:54:49.729142       1 main.go:514] Stopping shutdownHandler...
Enter fullscreen mode Exit fullscreen mode

Fix the CIDR in the ConfigMap

Fix it in the ConfigMap. kubectl edit opens the live kube-flannel-cfg object in vi. Inside net-conf.json, Network is set to 10.244.0.0/16, the manifest's default. Change it to 192.168.0.0/16 so it matches the cluster's pod CIDR, then save and quit. kubectl pushes the edit back to the API server the moment you write the file. Nothing else in the ConfigMap changes.

$ kubectl -n kube-flannel edit configmap kube-flannel-cfg
Enter fullscreen mode Exit fullscreen mode
- "Network": "10.244.0.0/16",
+ "Network": "192.168.0.0/16",
Enter fullscreen mode Exit fullscreen mode

Restart, then nodes go Ready

A ConfigMap change does not restart pods on its own, so the flannel pods keep crashing on the old config until you cycle them. Delete the flannel pods and the DaemonSet recreates them, this time reading the corrected Network. Now they come up Running, and within a few seconds the nodes flip to Ready and CoreDNS schedules. The CNI is installed and configured.

$ kubectl -n kube-flannel delete pod -l app=flannel
pod "kube-flannel-ds-6mhjm" deleted from kube-flannel namespace
pod "kube-flannel-ds-jq4n7" deleted from kube-flannel namespace

$ kubectl -n kube-flannel get pods -o wide
NAME                    READY   STATUS    RESTARTS   AGE   IP            NODE                          NOMINATED NODE   READINESS GATES
kube-flannel-ds-5c2pb   1/1     Running   0          3s    172.18.0.13   cka-scenario8-control-plane   <none>           <none>
kube-flannel-ds-fntnk   1/1     Running   0          3s    172.18.0.14   cka-scenario8-worker          <none>           <none>

$ kubectl get nodes
NAME                          STATUS   ROLES           AGE   VERSION
cka-scenario8-control-plane   Ready    control-plane   8d    v1.36.1
cka-scenario8-worker          Ready    <none>          8d    v1.36.1
Enter fullscreen mode Exit fullscreen mode

Prove pod-to-pod connectivity

Finish by proving it actually networks, not just that the pods are green. Create two pods on different nodes and list them wide: each has an IP from 192.168.0.0/16, on a different host. Ping one from the other and the packets ride the vxlan overlay between nodes. Replies come back, so the CNI is doing its job end to end.

$ kubectl apply -f connectivity-test.yaml
pod/test1 created
pod/test2 created

$ kubectl get pods -o wide -l app=conn-test
NAME    READY   STATUS    RESTARTS   AGE   IP            NODE                          NOMINATED NODE   READINESS GATES
test1   1/1     Running   0          1s    192.168.1.8   cka-scenario8-worker          <none>           <none>
test2   1/1     Running   0          1s    192.168.0.5   cka-scenario8-control-plane   <none>           <none>

$ kubectl exec test1 -- ping -c 3 <test2-ip>
PING 192.168.0.5 (192.168.0.5): 56 data bytes
64 bytes from 192.168.0.5: seq=0 ttl=62 time=0.507 ms
64 bytes from 192.168.0.5: seq=1 ttl=62 time=0.096 ms
64 bytes from 192.168.0.5: seq=2 ttl=62 time=0.151 ms

--- 192.168.0.5 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.096/0.251/0.507 ms
Enter fullscreen mode Exit fullscreen mode

Exam tips

A few traps. NotReady nodes plus Pending CoreDNS almost always means no CNI, so install one first. After you apply a CNI, always check its pods are actually Running, don't assume the apply worked. When flannel logs failed to acquire a lease, that is a pod CIDR versus Network mismatch: make flannel's Network match the cluster, since the cluster CIDR is fixed. And remember a ConfigMap edit needs a pod restart to take effect.

  • NotReady nodes + Pending CoreDNS => no CNI installed
  • After applying a CNI, verify its pods are Running (don't assume)
  • 'failed to acquire lease' = flannel Network must match the cluster pod CIDR
  • A ConfigMap edit needs a pod restart to take effect

Recap

  • No CNI => NotReady; install flannel from the manifest
  • CrashLoop => logs => flannel Network must match the cluster pod CIDR
  • Fix net-conf.json, restart the pods, nodes go Ready
  • Prove it with a cross-node ping; subscribe + dev.to writeup

Reproduce this yourself

The entire scenario is scripted on a throwaway kind cluster: https://github.com/The-Cyber-Sidekick/TCS_CKA_2026_Exam_Scenarios

git clone https://github.com/The-Cyber-Sidekick/TCS_CKA_2026_Exam_Scenarios.git
cd TCS_CKA_2026_Exam_Scenarios/learning/scenarios/scenario8-cni-flannel-install
./setup.sh        # creates the cluster AND arms the scenario
# solve it by hand, or:
./solution.sh     # apply the answer key and verify
Enter fullscreen mode Exit fullscreen mode

If this helped, subscribe to The Cyber SideKick on YouTube for more CKA drills, and grab the newsletter at https://thecybersidekick.beehiiv.com.

Top comments (0)