Skip to main content
In this lesson we explain how Kubernetes uses the Container Network Interface (CNI) to attach pods to a cluster network. We recap the role CNI plays, where Kubernetes expects plugin binaries and configurations to live, and how the kubelet coordinates with the container runtime to invoke the appropriate plugin when a pod is created. Quick recap from previous lessons:
  • Container runtimes create network namespaces for containers.
  • CNI defines how a plugin should be invoked to attach that namespace to a network.
  • Kubernetes delegates the work of creating the pod network namespace and invoking CNI plugins to the kubelet (which coordinates with runtimes such as containerd or CRI-O).
A dark presentation slide titled "Container Network Interface" listing two checked items about container networking ("Container Runtime must create network namespace" and "Identify the network the container must attach to"). A Kubernetes logo is shown at the lower right.

How Kubernetes wires up CNI plugins

Per the CNI specification, the component that creates the container (or pod) network namespace must invoke the appropriate plugin binary and pass the configuration. In Kubernetes:
  • The kubelet creates the pod’s network namespace (via the container runtime).
  • After the namespace is created, the kubelet calls the configured CNI plugin binary to attach the pod to the desired network.
  • The plugin creates veth pairs, attaches interfaces to host bridges or overlays, assigns IP addresses, sets up routes, and configures NAT rules if requested.
Common CNI plugin examples include Flannel, Calico, Weave, Cilium, Canal, and many others. Modern Kubernetes nodes typically run containerd as the CRI runtime (Docker historically used containerd internally).

Where to place plugin binaries and configs

Kubernetes (via the kubelet) relies on two filesystem locations on each node to find CNI plugins and their configuration: Representative output from a node:
The kubelet reads the configuration files in /etc/cni/net.d to decide which plugin configuration to apply. If there are multiple files, the kubelet (and many CNI implementations) selects the configuration using lexical (alphabetical) ordering and uses the first applicable configuration file.
Place plugin configuration files in /etc/cni/net.d. The runtime chooses the configuration based on filename ordering (typically the lowest-numbered or lexically-first file). Some systems use .conflist files when chaining multiple plugins; others use .conf.

Example network configuration (bridge plugin)

A typical CNI config file is JSON and follows the CNI schema. Here is a representative bridge plugin configuration:
Key fields explained:
  • cniVersion: Target CNI specification version.
  • name: Logical network name for this configuration.
  • type: Plugin type to invoke (e.g., bridge, flannel, calico).
  • bridge: Host bridge interface to use (e.g., cni0).
  • isGateway: When true, the bridge gets an IP and can act as gateway for pods.
  • ipMasq: When true, applies SNAT (iptables masquerade) for pod egress to non-cluster destinations.
  • ipam: IP Address Management configuration:
    • type: Allocation method; host-local stores allocation state on the node. dhcp can be used for external allocation.
    • subnet: CIDR used for pod IP assignments.
    • routes: Additional routes to add in the pod namespace (e.g., default route {"dst":"0.0.0.0/0"}).

What happens when a pod starts

  1. Kubelet asks the container runtime to create the container and its network namespace.
  2. Once the pod network namespace exists, the kubelet reads /etc/cni/net.d to pick a configuration file (first by lexical order).
  3. Kubelet executes the chosen plugin binary from /opt/cni/bin and provides the configuration and environment variables as required by the CNI spec.
  4. The plugin sets up the pod interface (veth), attaches it to the host network (bridge, vlan, overlay), assigns an IP, configures routes, and applies NAT rules if requested.
  5. Kubelet reports the allocated IP and network state back to Kubernetes components.

Troubleshooting checklist

  • Verify plugin binaries exist: ls /opt/cni/bin
  • Check configuration files: ls /etc/cni/net.d and inspect the JSON or .conflist content
  • Confirm filename ordering if multiple config files are present (the first file wins)
  • Match cniVersion and plugin versions to avoid incompatibilities
Try inspecting /opt/cni/bin and /etc/cni/net.d on a cluster node and open a CNI config file to see these fields and behavior firsthand.

Watch Video

Practice Lab