Build Kubernetes Pod Networking by Hand to Understand CNI

A hands-on walkthrough wires up Kubernetes-style pod networking with raw Linux tools, showing exactly what a CNI plugin automates.

MiHiR SEN
MiHiR SEN
·4 min read

The Container Network Interface, or CNI, sits at the bottom of every Kubernetes cluster's stack, quietly moving every packet, yet most engineers who run clusters daily have never looked inside it. A recent hands-on tutorial builds pod networking entirely by hand, using raw Linux kernel primitives, to make that black box legible.

Kubernetes Has No Built-In Networking at All

A freshly created cluster with no CNI installed shows every node stuck in a NotReady state, with kubelet reporting explicitly that its container runtime network isn't ready because no network plugin has initialized. The control plane, scheduler, and etcd can all be healthy while the cluster remains completely unusable, a pointed illustration that Kubernetes itself has zero built-in capability to move a packet between containers.

Starting With a Single Virtual Cable

The walkthrough begins with two isolated Linux network namespaces, each acting like an island with no interfaces, no IP address, and no route to anywhere. A veth pair, a virtual network cable where anything entering one end immediately appears at the other, connects them directly, and a successful ping between the two proves the basic mechanism. But veth pairs are strictly point-to-point, so connecting more than two namespaces this way scales terribly, the same reason data centers don't run individual cables between every pair of servers.

From Cables to a Software Switch

The fix is a Linux bridge, a software Layer 2 switch that learns MAC addresses and forwards frames across every attached interface. Wiring three namespaces into a shared bridge lets all three communicate freely using nothing but plain ARP resolution, no routing rules required, since every namespace lives in the same subnet on the same virtual switch. This single-host model is essentially how older, simpler CNI plugins operated.

Where the Trick Breaks: Crossing a Machine Boundary

The tutorial then deliberately breaks the model by standing up two separate virtual machines, each with its own bridge and its own pod subnet, and pinging across them. The packet gets dropped completely, and a packet capture confirms it leaves the first machine but never arrives at the second: each host's default route sends the packet to its ordinary LAN gateway, which has no idea the other machine's pod subnet even exists.

The Fix Is a Single Static Route

Resolving the cross-node failure requires nothing more than telling each host one missing fact: the other node's pod subnet sits behind the other node's physical IP address. Adding that single static route on each side, without touching any of the previously built bridges or namespaces, restores connectivity completely, with the packet now correctly hopping from pod to bridge to physical NIC to the other machine and back.

What a CNI Actually Automates

The exercise is meant to make one point land: everything just done by hand, namespace creation, veth pairing, bridge attachment, subnet assignment, and route propagation, is exactly what a CNI plugin performs automatically every time a pod is scheduled, at a scale where doing it manually across a thousand nodes would be flatly impossible. A CNI's three core jobs are creating the network plumbing for each pod, handing out unique non-colliding IP addresses across nodes, and programming routes so every node knows how to reach pods on every other node.

Why Cloud Providers Force More Advanced CNIs

The manual direct-routing approach that works cleanly in a bare-metal lab fails outright in a public cloud, since providers don't allow arbitrary IP addresses to roam freely across their network fabric; pod traffic that isn't explicitly registered gets treated as illegitimate and dropped. Advanced CNIs like Cilium address this by encapsulating pod packets inside ordinary node-to-node UDP traffic through VXLAN or Geneve overlays, making pod traffic look like normal host traffic to the cloud provider, and by using compiled eBPF programs loaded directly into the kernel instead of routing every packet through a full Linux bridge pipeline, delivering both compatibility with cloud network restrictions and near line-rate performance.