Start with the VLANs, Bonding, Bridging. This is part 3 of 3 in the Advanced Networking in Linux series (4 posts in total). Also in this series: VLANs, Bonding, Bridging, Routing and Firewalling, Namespaces and Virtual Links.
Part 3 kept everything on one machine: namespaces as workloads, veth as cables, bridge or macvlan or ipvlan as the attachment. That is enough for a single Docker host.
Two hosts do not share a broadcast domain just because both run Linux. Something has to carry Ethernet (or IP) across the real network between them. VXLAN is one common way to do that. CNI is something else entirely: a contract so Kubernetes (and other runtimes) can plug a pod into whatever network architecture you chose.
CNI does not mean VXLAN. This post teaches both ideas so the title earns its name.
The Mental Model
In part 3, namespaces imitated workloads. Here, namespaces imitate nodes. Each “node” gets a bridge for local workloads and a VXLAN tunnel endpoint (VTEP) that joins those bridges across an underlay.
- Underlay — the real routed network between hosts (or between our fake nodes). Example:
192.0.2.0/24. - Overlay — the virtual Ethernet fabric carried inside underlay packets. VXLAN encapsulates Ethernet frames in UDP (port 4789 by default), tagged with a VNI (VXLAN Network Identifier).
Geneve is a sibling encapsulation used by some cloud and SDN stacks. Same job class; this lab uses VXLAN.
| |
VXLAN Lab: Two Nodes on One Machine
Everything below runs on one Linux host. Network namespaces stand in for Node A and Node B. A veth (or two) in the default namespace can provide the underlay link; the simplest teaching setup uses a bridge in the default namespace as a fake “rack switch” for underlay IPs.
Underlay
| |
Nodes can reach each other on the underlay. Overlay next.
Overlay bridges and VXLAN
Same VNI on both sides. Point each VTEP at the other node’s underlay IP (remote).
| |
Optional: hang a workload namespace off br-overlay with a veth, exactly as in part 3 — that mimics a pod on the node.
Inspect encapsulation:
| |
You should see UDP/4789 on the underlay while ICMP runs on 10.200.0.0/24.
Cleanup:
| |
Production VTEPs often use multicast or a control plane instead of a single remote. The lab’s point is the encapsulation, not a full SDN.
Why CNI Exists
Kubernetes does not hard-code “create this veth, this bridge, this VXLAN” into kubelet for every cluster. When the container runtime creates a pod sandbox, it invokes the configured CNI implementation through a standard contract.
Conceptually:
| |
On ADD, the plugin is told about the pod’s network namespace and expected to leave an interface, address, and routes ready. On DEL, it tears that down. CHECK is for consistency. The JSON details are in the CNI specification; you do not need to implement a plugin to use the idea.
Docker’s built-in bridge and overlay drivers do the same job without speaking CNI JSON: create interfaces in a container namespace and attach them to a network architecture. Kubernetes standardized the handoff so any compliant plugin can provide the architecture.
CNI Is the Contract, Not the Architecture
| |
Map those shapes onto this series:
| Architecture | What it reuses from this series | Example names (not a vendor bake-off) |
|---|---|---|
| Host-local / bridge | Part 1 bridges + part 3 veth/netns | Simple bridge CNI, Docker bridge |
| Routed / BGP-style | Part 2 forwarding and routes | Calico in routed modes |
| Overlay | This post (VXLAN or Geneve) | Flannel VXLAN, Docker overlay |
Cilium and others may use eBPF datapaths; that is still “an implementation behind the same contract,” not a reason to confuse CNI with one tunnel type.
CNI does not mean VXLAN. A cluster can be CNI-compliant with no overlay at all.
Docker and Kubernetes in Product Form
Once the primitives click:
- Introduction to Docker — containers and the default bridge network as a product UI over netns + veth + bridge.
- Getting Started with Kubernetes — pods as networked units; the cluster network is whoever your CNI plugin is.
Beyond Kubernetes is the next orchestration layer: CRDs, Operators, Istio, scheduling, and security. It assumes pods already have connectivity. Istio does not replace CNI. A service mesh sits above the pod network; it does not create the interface in the pod netns.
Verification and Common Mistakes
For the lab:
| |
Watch for:
- VNI mismatch — both ends must agree on the VXLAN ID.
- Underlay MTU vs overlay MTU — encapsulation costs header space; lower the overlay MTU or raise the underlay MTU consistently.
- Treating the overlay as “just a VLAN” — VLANs are usually switch-local tags; VXLAN is UDP across an IP underlay.
- Assuming every cluster uses VXLAN — many use pure routing or cloud VPC networking.
- Conflating CNI with VXLAN — CNI is the plugin contract; VXLAN is one optional data plane.
- Expecting Istio (or any mesh) to replace CNI — different layers.
Further Reading
- Linux VXLAN (kernel networking docs)
- CNI specification
- Kubernetes networking concepts
Conclusion
Part 1 stacked L2 on a host. Part 2 routed between L3 domains. Part 3 isolated stacks with namespaces and virtual links. This part stretched a virtual L2 across an underlay with VXLAN, then separated that implementation from CNI, the contract that lets Kubernetes plug pods into bridge, routed, or overlay networks without baking one design into kubelet.
From here, read the Docker and Kubernetes posts on the Systems path as product views of the same primitives — then Beyond Kubernetes when you care about CRDs, Operators, and the mesh above a working pod network.
This series stops at the network boundary on purpose. Orchestration is the next shelf, not another tunneling mode.