This episode brings Flannel to real scale: a three-node kubeadm cluster, verification of routing and the overlay, simulating failure domains when a node goes down, and assessing Flannel's scale limits and the signs that it's time to switch to a more advanced CNI.

So far you've been playing in a small cluster. Now it's time to scale: build a three-node kubeadm cluster and observe how Flannel behaves in a more realistic environment.
Episode 10 tests Flannel at real scale. You will build a three-node cluster, verify routing and the overlay, simulate node failure, and assess how far Flannel can be used before your team needs a more advanced CNI.
Start with one control plane node and two workers. Initialize the control plane with Flannel's default CIDR:
sudo kubeadm init --pod-network-cidr=10.244.0.0/16After init finishes, kubeadm shows the join command. Run it on each worker node:
sudo kubeadm join 192.168.1.10:6443 --token <token> --discovery-token-ca-cert-hash sha256:<hash>The kubeadm join command above connects a worker to the control plane. After all nodes join, install Flannel as in episode 3 and wait for all kube-flannel Pods to be Running.
kubectl get nodes -o wide
kubectl get pods -n kube-flannel -o wideThree nodes Ready and three kube-flannel Pods Running mean every node has a flanneld with its own subnet lease.
Go into one of the nodes and inspect the route table:
ip route | grep flannelThe output of ip route | grep flannel shows routes to other nodes' subnets: 10.244.1.0/24 via node-2's IP, and 10.244.2.0/24 via node-3's IP. This is proof that lease synchronization is working perfectly.
Deploy a workload with anti-affinity so the Pods are spread out, then test the connection:
kubectl create deployment nginx --image=nginx --replicas=3
kubectl get pods -o wide
kubectl exec -it <pod-node-1> -- ping -c 3 <ip-pod-node-2>When a ping from a Pod on node-1 to a Pod on node-2 succeeds, the VXLAN overlay works across the whole cluster.
Test Flannel's resilience by taking down one worker node in a planned manner:
kubectl cordon worker-2
kubectl drain worker-2 --ignore-daemonsets
kubectl get nodesWhen node-2 is in the cordoned state, its Pods move to other nodes. Flannel needs no extra configuration because node-2's subnet lease remains as long as it hasn't expired.
If worker-2 is down longer than the lease validity period, its subnet can be reallocated to a new node. This is automatic and safe, but needs to be understood: the IP addresses of restarted Pods can differ. Applications must always use a Service, not a raw Pod IP.
kubectl get lease -n kube-systemThe kubectl get lease -n kube-system command shows the still-active leases. The lease of a dead node will disappear after it expires.
All lease and route updates go through the API server. In very large clusters, for example hundreds of nodes with high Pod churn, the API server can become a bottleneck because every subnet update must pass through kubelet and the CNI. Flannel also doesn't distribute routes globally like BGP; every node stores all routes on its own.
There are clear signs: the need for per-namespace NetworkPolicy, thousands of nodes, or Pod traffic that must follow an optimal path without an overlay. When those appear, consider a CNI with richer features. A thorough comparison between Flannel, Calico, and Cilium is in episode 22.
Episode 10 proved Flannel works at three-node scale: routes are synchronized, the overlay is healthy, and node failure can be simulated safely. You also now know the scale limits to watch out for.
Key takeaways:
In the next episode, episode 11, we will dissect Flannel's integration with CNI plugins — the roles of bridge, portmap, and bandwidth in /opt/cni/bin, the contents of 10-flannel.conflist, and Flannel's integration with Multus for multiple network interfaces.