Skip to main content

Container Network Interface (CNI) in Kubernetes

Kubernetes Header

A Kubernetes cluster's networking isn't implemented by Kubernetes itself: it's delegated to a CNI plugin (Container Network Interface). The kubelet knows a very simple contract — "set up the network for this pod" — and lets the plugin do the work: create virtual interfaces, assign IPs, program routes and apply policies.

Understanding where that configuration lives helps you diagnose network problems that otherwise look like "magic".

Where the configuration lives​

On every node, the CNI configuration sits in:

/etc/cni/net.d/

There you'll find one or more *.conf or *.conflist files holding the configuration of the installed plugin (Calico, Cilium, Flannel, Weave, AWS VPC CNI, etc.). For example:

ls /etc/cni/net.d/
# 10-calico.conflist
# calico-kubeconfig

And the plugin binaries live in:

/opt/cni/bin/

If either of these directories is empty or corrupted, new pods will get stuck in ContainerCreating with network plugin is not ready.

How the plugin is invoked​

When the kubelet is about to start a pod:

  1. It creates the pod sandbox (a pause container with its own network namespace).
  2. It reads the first valid config in /etc/cni/net.d/ (lexical order).
  3. It runs the corresponding CNI binary from /opt/cni/bin/, passing data over stdin.
  4. The plugin assigns an IP, creates the interface inside the namespace and returns the result.

That's why kubectl get pod may show a pod as Pending or ContainerCreating for a few seconds: it's waiting for the CNI to return the IP.

Quick checks when "networking doesn't work"​

From the affected node:

# Is there config?
ls -l /etc/cni/net.d/

# Do the binaries exist?
ls /opt/cni/bin/

# What does the kubelet say?
journalctl -u kubelet -n 200 --no-pager | grep -i cni

From the cluster:

# Is the CNI pod running?
kubectl get pods -n kube-system -l k8s-app=calico-node # adjust the label to your plugin
kubectl describe pod <cni-pod> -n kube-system
kubectl logs <cni-pod> -n kube-system

If the CNI pod is down on a node, that node won't be able to schedule new pods even if it has free CPU and memory.

Things worth remembering​

  • The config in /etc/cni/net.d/ is usually installed by the plugin's DaemonSet. Don't edit it by hand unless you know what you're doing; the DaemonSet will overwrite it.
  • Only the first file is used (lexical order). That's why plugins are named 10-…, 20-…, etc.
  • Switching CNI on a production cluster is a delicate operation: it requires draining nodes and typically restarting pod networking.
  • NetworkPolicies only work if the plugin implements them. Plain Flannel, for example, doesn't; Calico and Cilium do.

Knowing /etc/cni/net.d/ looks like a minor detail, but it's the first place to look when an otherwise healthy node stops accepting pods.