CNI Plugins
[!NOTE] This module explores the core principles of CNI Plugins, deriving solutions from first principles and hardware constraints to build world-class, production-ready expertise.
1. The Problem: Connecting Containers
Kubernetes itself does not implement networking. It offloads this task to plugins. When a Pod starts, Kubernetes needs something to:
- Create a network interface (eth0) inside the Pod.
- Assign it an IP address.
- Connect it to the rest of the network.
2. The Solution: CNI (Container Network Interface)
CNI is a standard specification (maintained by CNCF) that defines how orchestrators (like K8s) interact with networking plugins.
The CNI Flow
- Kubelet calls CNI: When scheduling a Pod, Kubelet looks at
/etc/cni/net.d/. - Binary Execution: It executes the CNI binary (e.g.,
/opt/cni/bin/bridge) with commands likeADD,DEL, orCHECK. - Wiring: The plugin creates a veth pair. One end goes into the Pod’s namespace (
eth0), the other attaches to a bridge on the host (cni0). - IPAM: The plugin calls an IPAM (IP Address Management) module to get an IP.
3. Interactive: CNI Simulator
Visualize the steps a CNI plugin takes to wire up a Pod.
Node Network Namespace
Bridge (cni0)
Pod Namespace
eth0
4. Popular CNI Plugins
| Plugin | Mechanism | Pros | Cons |
|---|---|---|---|
| Flannel | VXLAN Overlay | Simple, works everywhere | Higher overhead (encapsulation) |
| Calico | BGP (Layer 3) | High performance, Network Policies | Complex setup on some networks |
| Cilium | eBPF | Super fast, advanced security/observability | Requires newer kernel |
Overlay Networks (VXLAN)
Flannel creates a “Network overlay”. It wraps packets in UDP packets to send them across nodes.
- Pod IP: 10.244.1.5
- Node IP: 192.168.1.10
- The packet from the Pod is encapsulated inside a UDP packet sent to the destination Node IP.
5. Code Example: Minimal CNI Plugin (Go)
A simplified view of what a CNI plugin binary looks like.
package main
import (
"fmt"
"github.com/containernetworking/cni/pkg/skel"
"github.com/containernetworking/cni/pkg/version"
)
func main() {
skel.PluginMain(cmdAdd, cmdCheck, cmdDel, version.All, "my-cni")
}
// cmdAdd is called when a Pod starts
func cmdAdd(args *skel.CmdArgs) error {
fmt.Printf("Adding networking for container: %s\n", args.ContainerID)
// 1. Parse config (IP range, bridge name)
// 2. Setup IPAM (Get an IP)
// 3. Create veth pair
// 4. Move one end to container NS, rename to eth0
// 5. Attach other end to bridge
// 6. Set routes
return nil
}
func cmdDel(args *skel.CmdArgs) error {
fmt.Printf("Removing networking for container: %s\n", args.ContainerID)
// Cleanup resources
return nil
}
func cmdCheck(args *skel.CmdArgs) error {
return nil
}