This is Level 7 of our Kubernetes networking series — and one of the most important installments so far. Back in Level 1, we learned the shape of Pod networking:
Pod → Network Namespace → eth0 → veth → Node networking
But we deliberately left one big question unanswered the entire time: who actually creates all of this? The answer is CNI, and this article finally opens that box.
Table of Contents
- The Problem: Something Has to Wire the Pod's Network
- What Is CNI?
- Why We Need CNI
- CNI Is Not One Particular Product
- The Pod Creation Flow
- What CNI Is Actually Responsible For
- CNI and IPAM
- Why Pod CIDR Matters
- The veth Pair, Revisited
- What Happens to the Pod's IP
- Who Actually Owns the Pod's eth0?
- CNI Handles Both Creation and Deletion
- CNI's Place in the Kubernetes Stack
- CNI vs Service
- CNI vs DNS
- CNI vs NetworkPolicy
- Four Major Networking Approaches
- Common CNI Implementations
- A Closer Look: Calico, Flannel, and Cilium
- Don't Get Lost in Terminology
- What Happens When a Pod Starts
- What Happens During Cross-Node Communication
- What Happens When CNI Is Broken
- A Kubernetes Networking Troubleshooting Ladder
- Useful Commands for CNI Investigation
- CNI and kubelet
- Pod IP vs Service IP vs Node IP
- The Big Picture
- The Key Mental Model
- Level 7 Checkpoint
- What's Next: kube-proxy, iptables, IPVS, and eBPF
The Problem: Something Has to Wire the Pod's Network
Suppose Kubernetes creates a new Pod:
kubectl run nginx --image=nginx
That Pod needs a network namespace, an eth0 interface, an IP address, routes, and connectivity to every other Pod in the cluster. Kubernetes itself doesn't contain one built-in, universal implementation that directly wires all of this up. Instead, it delegates the job to a standardized mechanism: CNI — the Container Network Interface.
What Is CNI?
In the simplest terms:
CNI is a standard interface for configuring container networking.
Think of it as a contract between the container runtime and whatever networking implementation you've chosen:
Container runtime
| "I need networking for this Pod"
↓
CNI
↓
Network plugin
↓
Configure Pod network
The CNI specification defines the contract; CNI plugins are what actually do the networking work.
Why We Need CNI
Without any Pod networking, Pods are isolated islands:
Pod A Pod B
❌ ❌
With a working CNI implementation in place, they can actually reach each other:
Pod A ─────────→ Pod B
Depending on the specific implementation, CNI/network plugins can provide: Pod IPs, Pod network interfaces, routing, general connectivity, and — in some cases — NetworkPolicy enforcement.
CNI Is Not One Particular Product
This is a crucial mental correction if you're new to this space: CNI is not the name of a single networking product. It's an interface, specification, and ecosystem. Multiple different implementations can all satisfy the CNI contract, including Calico, Cilium, Flannel, AWS VPC CNI, Azure CNI, and various GKE networking implementations.
Don't think: CNI = Calico. Instead think:
CNI
↓
standard interface
↓
different networking implementations
The Pod Creation Flow
Let's connect this to everything we've learned. When you run kubectl run nginx --image=nginx, the high-level flow looks like this:
kubectl
↓
API Server
↓
Scheduler
↓
Node selected
↓
Container runtime
↓
Network setup
↓
CNI
↓
Pod gets networking
↓
Container starts
Zooming into just the networking portion:
Pod
↓
Network namespace
↓
CNI invoked
↓
Create/configure network interface
↓
Assign IP
↓
Configure routes
↓
Connect Pod to node network
↓
Pod networking ready
What CNI Is Actually Responsible For
At a high level, CNI answers five key questions for every Pod:
1. What network should this Pod join? → the cluster's Pod network.
2. What IP should it receive? → e.g., 10.244.1.15.
3. How does the Pod connect to the Node? → commonly, a Pod's eth0 connects via a veth pair to the Node.
4. How can it reach other Pods? → the networking implementation configures the necessary connectivity.
5. Can traffic be restricted? → some (not all) implementations also enforce NetworkPolicy.
CNI and IPAM
Here's a term you'll see constantly: IPAM (IP Address Management). When a Pod needs an IP, IPAM is what allocates it:
Pod
↓
"I need an IP"
↓
IPAM
↓
10.244.1.15
IPAM allocates addresses from configured pools. For example, given a Pod network of 10.244.0.0/16, a networking implementation might divide it per Node:
Node 1 → 10.244.1.0/24
Node 2 → 10.244.2.0/24
Node 3 → 10.244.3.0/24
And from there:
Pod A → 10.244.1.10
Pod B → 10.244.1.11
Pod C → 10.244.2.10
These are illustrative example ranges, not universal defaults — actual ranges vary by cluster and CNI configuration.
Why Pod CIDR Matters
Recall from Level 2: Pod A (10.244.1.5) needs to reach Pod B (10.244.2.5) on a different Node. For that to work, the networking system needs to know that 10.244.2.0/24 lives on Node 2. This is exactly where the CNI/networking implementation earns its keep — establishing connectivity between these per-Node Pod networks.
The veth Pair, Revisited
We first saw veth pairs back in Level 0 and Level 1. Now let's understand why CNI specifically cares about them.
A Pod lives in its own isolated network namespace:
Pod network namespace
┌─────────────────────┐
│ eth0 │
│ 10.244.1.10 │
└─────────────────────┘
But it still needs to connect to the Node. A veth pair — a virtual Ethernet cable — is a common way to bridge that gap:
Pod namespace Node
┌──────────────┐ ┌──────────────┐
│ eth0 │=================│ vethXXXX │
│ │ veth pair │ │
└──────────────┘ └──────────────┘
One end lives inside the Pod's namespace; the other lives on the Node. The CNI/network implementation is typically what creates and configures this pairing.
What Happens to the Pod's IP
Inside a running Pod, ip addr might conceptually show:
eth0
inet 10.244.1.10/24
And ip route will show routes that let the Pod communicate beyond its own local subnet. The exact routing table content depends entirely on which networking implementation configured it.
Who Actually Owns the Pod's eth0?
A genuinely useful interview question. The interface itself exists inside the Pod's network namespace, but the setup is performed by the container networking implementation, invoked through CNI. So don't say "the Pod creates eth0" — instead think:
Container runtime
↓
CNI/network plugin
↓
network namespace + interface + IP + routes
CNI Handles Both Creation and Deletion
CNI's job doesn't stop once a Pod is created:
CREATE POD
↓
CNI/network setup
↓
network exists
DELETE POD
↓
network cleanup
↓
IP released
↓
interfaces removed
This cleanup step matters a lot — without it, you could end up accumulating unused interfaces, unreleased IPs, and stale network state over time. The networking implementation is responsible for tidying all of this up.
CNI's Place in the Kubernetes Stack
Kubernetes
| schedules/manages Pods
↓
Container runtime
| runs containers
↓
CNI/network implementation
| configures networking
↓
Pod network
Kubernetes handles orchestration (deciding what should run where). The networking implementation handles the actual mechanics of wiring that Pod onto the network.
CNI vs Service
An important distinction we can now draw crisply:
CNI → Pod networking (connectivity)
Service → stable way to reach a group of Pods
For example:
Pod A (10.244.1.10) → CNI/networking → Pod B (10.244.2.10)
versus:
Client → Service IP → Backend Pod
Two entirely different jobs, working at two different layers.
CNI vs DNS
Also worth separating clearly:
DNS → backend.default.svc.cluster.local → Service IP (name resolution)
CNI → Pod interface/IP/routes → network connectivity (Pod networking)
DNS answers "what IP does this name map to?" CNI answers "how does a Pod actually get onto the network in the first place?"
CNI vs NetworkPolicy
We covered this distinction in Level 6, but it's worth reinforcing here:
NetworkPolicy → "What traffic should be allowed?"
Network implementation → "How is Pod networking provided, and (if supported) how are policies enforced?"
Some networking implementations support NetworkPolicy enforcement and some don't — but either way, CNI ≠ NetworkPolicy. They're related but distinct concerns.
Four Major Networking Approaches
Now let's introduce the major strategies a CNI implementation can use to actually make Pod networking work.
Approach 1 — Routing
Nodes are taught direct routes to each other's Pod networks:
Node 1: Pod CIDR = 10.244.1.0/24
Node 2: Pod CIDR = 10.244.2.0/24
Node 1 simply knows 10.244.2.0/24 → Node 2, so traffic flows: Pod A → Node 1 → Node 2 → Pod B.
Approach 2 — Overlay
A virtual network is built on top of the physical network via encapsulation:
Pod packet
↓
encapsulate
↓
Node 1 → physical network → Node 2
↓
decapsulate
↓
Pod
Think of this as "a network inside another network" — the inner packet (Pod A → Pod B) rides inside an outer packet (Node 1 → Node 2). VXLAN is a common technology used to implement this approach.
Approach 3 — Cloud/VPC Networking
Cloud environments can integrate Pod networking directly with the cloud provider's native network:
Pod → cloud network → VPC/VNet → other resources
For example, AWS's VPC CNI uses actual AWS networking primitives rather than building a generic overlay on top. The exact implementation varies by cloud provider and configuration.
Approach 4 — eBPF-Based Networking
Some modern implementations use eBPF for both networking and policy enforcement:
Pod traffic
↓
Linux kernel
↓
eBPF programs
↓
routing / filtering / load balancing
Cilium is the major example here. We won't go deep into eBPF mechanics yet — that's reserved for Level 8. For now, just recognize that a CNI implementation could be built on eBPF.
Common CNI Implementations
| Implementation | General Idea |
|---|---|
| Calico | Routing / policy, with multiple dataplane options |
| Cilium | eBPF-based networking and security |
| Flannel | Simple Pod networking, commonly overlay-based |
| AWS VPC CNI | Integrates Pods directly with AWS VPC networking |
| Azure networking implementations | Integrate Pods with Azure networking |
Don't try to memorize every implementation detail right now. At this level, the important question to ask about each one is simply: what problem does it solve, and how?
A Closer Look: Calico, Flannel, and Cilium
Calico is widely used for both Pod networking and NetworkPolicy enforcement. It can use routing-based networking and supports multiple dataplane options:
Pod → Calico → network + policy
Flannel is known for providing relatively simple Kubernetes Pod networking:
Pod → Flannel → cluster network
A common Flannel setup uses an overlay like VXLAN — but don't treat "Flannel = VXLAN" as an absolute rule, since configurations can vary.
Cilium leans heavily on eBPF for networking, security, and observability:
Pod traffic → Linux kernel → eBPF → networking + security + observability
We'll compare these implementations in more depth once we reach Level 8.
Don't Get Lost in Terminology
You'll hear phrases like "CNI plugin," "CNI binary," "CNI configuration," "CNI network," and "CNI IPAM" thrown around. Don't let the terminology overwhelm you. At the learning level, this simplified mental model covers the fundamentals well:
CNI
|
┌───────┴────────┐
↓ ↓
Network setup IPAM
↓ ↓
interface IP
routes
connectivity
The real architecture can get more nuanced in production systems, but this model will serve you well as a foundation.
What Happens When a Pod Starts
Putting it all together — suppose Kubernetes schedules Pod A onto Node 1:
Kubernetes
↓
Node 1
↓
Container runtime
↓
Create Pod namespace
↓
CNI
|
┌─────────┼─────────┐
↓ ↓ ↓
veth IP routes
| | |
└─────────┼─────────┘
↓
Pod eth0
↓
Pod networking
At the end of this sequence, Pod A has a working IP (say, 10.244.1.10) and is ready to communicate.
What Happens During Cross-Node Communication
Suppose Pod A (10.244.1.10 on Node 1) needs to reach Pod B (10.244.2.10 on Node 2). The networking implementation provides the actual path:
Pod A → eth0 → veth → Node 1 → networking implementation → Node 2 → veth → eth0 → Pod B
The exact middle section — routing, overlay, cloud networking, or eBPF — depends entirely on which CNI implementation you're running. This is precisely why the choice of CNI matters so much in real clusters.
What Happens When CNI Is Broken
This is where understanding CNI pays off during real troubleshooting. If you see symptoms like:
Pod → no IP
Pod → eth0 missing
Pod A ✗ Pod B
...you should immediately start thinking: could this be a CNI/networking problem? Common symptoms worth watching for include Pods stuck in ContainerCreating, Pods with no IP assigned, an unconfigured Pod network namespace, broken Pod-to-Pod connectivity, broken DNS connectivity, or NetworkPolicy simply not being enforced. Not every one of these symptoms is guaranteed to be a CNI issue, but CNI should always be high on your list of suspects.
A Kubernetes Networking Troubleshooting Ladder
We can now assemble a genuinely useful troubleshooting sequence, built from everything covered across this series:
Pod exists?
↓
Pod has IP?
↓
Pod has eth0?
↓
Pod has routes?
↓
Pod → Pod works?
↓
Service works?
↓
DNS works?
↓
NetworkPolicy works?
CNI sits right near the bottom of this stack:
CNI → Pod networking → Pod-to-Pod → Services → DNS → Ingress
If basic Pod networking is broken at the CNI layer, everything built on top of it can fail too — which is exactly why it's worth checking early rather than last.
Useful Commands for CNI Investigation
Start broad:
kubectl get pods -o wide
This shows you each Pod's IP and the Node it's running on. Then:
kubectl get nodes
Drill into a specific Pod:
kubectl exec -it <pod> -- ip addr
kubectl exec -it <pod> -- ip route
Check networking-related Pods across the whole cluster:
kubectl get pods -A
In many clusters, CNI components run as DaemonSets — typically one networking agent per Node:
kubectl get daemonsets -A
The exact namespace and deployment shape depend heavily on your specific Kubernetes distribution and chosen networking implementation.
Look for the CNI
A useful investigative habit:
kubectl get pods -A
Look for Pod names containing things like calico-node, cilium, kube-flannel, or aws-node. These names give you a strong clue about which networking implementation your cluster is running — though don't assume every cluster follows the same naming conventions.
CNI and kubelet
One more important relationship: the kubelet manages Pods on a given Node. When a Pod's networking needs to be configured, the container runtime and networking stack invoke the configured CNI mechanism:
kubelet
↓
container runtime
↓
CNI
↓
network plugin
↓
Pod network
The precise interaction between the runtime and CNI has evolved across different Kubernetes versions and container runtimes, but this remains the correct conceptual model to hold onto.
Pod IP vs Service IP vs Node IP
Let's clarify one more crucial distinction now that IPAM is fresh in mind. Given a Pod network of 10.244.0.0/16, IPAM might allocate:
Pod 1 → 10.244.1.10
Pod 2 → 10.244.1.11
Pod 3 → 10.244.2.10
When Pod 2 is deleted, 10.244.1.11 can eventually return to the available address pool, depending on the specific IPAM implementation. So: IPAM = who gets which Pod IP, and when it's reclaimed.
By now you should be able to clearly distinguish three different kinds of IPs:
Node IP → identifies a Node (e.g., 192.168.1.10)
Pod IP → identifies a Pod (e.g., 10.244.1.10)
Service IP → stable virtual endpoint (e.g., 10.96.120.50)
CNI is primarily concerned with the Pod IP layer — it has nothing to do with creating Service semantics, which is a separate mechanism entirely (covered in Level 3, and revisited more deeply in Level 8).
The Big Picture
We've now connected almost the entire series into a single diagram:
Kubernetes
↓
Node
↓
Container runtime
↓
CNI
|
┌─────────────┼─────────────┐
↓ ↓ ↓
veth IP routes
\ | /
└────────────┼────────────┘
↓
Pod
↓
Pod IP
↓
Pod-to-Pod network
↓
Service
↓
DNS
↓
Ingress / Gateway
And NetworkPolicy sits across the entire networking path as an overlay of rules:
Pod traffic → NetworkPolicy rules → network implementation → allow / restrict
The Key Mental Model
If you remember only one diagram from this entire article, make it this one:
POD
| eth0
↓
veth pair
↓
NODE
↓
CNI / networking
|
┌─────────┼─────────┐
↓ ↓ ↓
IP routes connectivity
| | |
└─────────┼─────────┘
↓
other Pods
And the single sentence to internalize:
CNI = "How do Pods get onto the network?"
Level 7 Checkpoint
1. What does CNI stand for?
Container Network Interface.
2. Is CNI a single product?
No — it's a standard/interface/ecosystem used by many different networking implementations.
3. What does CNI help configure?
At a high level: the Pod's network namespace, interface, IP address, routes, and connectivity — and, depending on the implementation, NetworkPolicy enforcement and other capabilities.
4. What is IPAM?
IP Address Management — the process of allocating IP addresses to Pods.
5. What commonly connects a Pod's namespace to the Node?
A veth pair is a common mechanism.
6. Is CNI the same as Service?
No. CNI provides Pod networking; Service provides stable access to a group of Pods.
7. Is CNI the same as NetworkPolicy?
No. NetworkPolicy defines what traffic should be allowed; the network implementation provides and (if supported) enforces that behavior.
8. Name some Kubernetes networking implementations.
Calico, Cilium, Flannel, AWS VPC CNI, among others.
9. What are the major networking approaches?
Conceptually: routing, overlay, cloud/VPC networking, and eBPF-based networking.
10. What happens if CNI networking is broken?
Symptoms can include Pods with no IP, Pods with no working interface, broken Pod-to-Pod connectivity, broken DNS connectivity, and cascading failures in higher-level networking.
What's Next: kube-proxy, iptables, IPVS, and eBPF
In Level 8, we'll finally open the black box behind the Service dataplane and answer:
A Service IP exists. How does it actually become a Pod IP?
We'll cover kube-proxy, iptables, IPVS, and eBPF — and how Service traffic is genuinely forwarded under the hood. This is where the whole networking picture starts becoming much more concrete.
Conclusion
CNI is the quiet, foundational layer that makes every other piece of Kubernetes networking possible. It's not a single product but a standardized contract — implemented by tools like Calico, Cilium, and Flannel — for giving every Pod a network namespace, an interface, an IP address, and a path to reach every other Pod in the cluster. Whether that connectivity is achieved through routing, overlays, cloud-native VPC integration, or eBPF depends entirely on which implementation you choose.
The most valuable habit to take away from this article: when something in Kubernetes networking breaks, don't jump straight to blaming Services or DNS. Walk the ladder from the bottom up — Pod IP, Pod interface, Pod-to-Pod connectivity — because a broken CNI layer can quietly break everything built on top of it.
Found this useful? Follow along for Level 8, where we finally crack open kube-proxy, iptables, IPVS, and eBPF to see exactly how a Service IP becomes real Pod traffic. Drop your questions in the comments, and share this with a teammate who still thinks "CNI" and "Calico" are the same thing. Let's keep building this Kubernetes networking roadmap together. 🚀
Top comments (0)