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:

  1. Create a network interface (eth0) inside the Pod.
  2. Assign it an IP address.
  3. 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

  1. Kubelet calls CNI: When scheduling a Pod, Kubelet looks at /etc/cni/net.d/.
  2. Binary Execution: It executes the CNI binary (e.g., /opt/cni/bin/bridge) with commands like ADD, DEL, or CHECK.
  3. 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).
  4. 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

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
}