This is Level 1 of our Kubernetes networking series. In Level 0, we built a foundation of core Linux networking concepts — IP addresses, ports, network namespaces, veth pairs, and bridges. Now it's time to connect that foundation directly to Kubernetes.
The central question for this article is deceptively simple:
When Kubernetes creates a Pod, how does that Pod actually get a network interface and an IP address?
By the end of this guide, you'll be able to trace the full journey — from kubectl run to a running Pod with a working eth0 — and understand exactly which component is responsible for each step.
Table of Contents
- The Problem Kubernetes Has
- The Solution: CNI
- Every Pod Gets Its Own Network Namespace
- Inspecting the Pod's eth0
- Where Does eth0 Connect? The veth Pair
- Why We Need the veth Pair
- Multiple Pods on One Node
- Where Does the Pod IP Come From?
- Understanding Pod CIDR
- Node CIDR vs Pod CIDR
- The Complete Pod Networking Stack
- What Happens When a Pod Is Created
- The Pause Container: Kubernetes' Hidden Detail
- Multiple Containers, One Network Namespace
- Port Collisions Inside a Pod
- Pod-to-Pod Communication (Same Node)
- Pods on Different Nodes
- The Kubernetes Networking Model
- What CNI Actually Does: A Preview
- Hands-On: Inspecting a Real Pod
- Level 1 Mental Model
- Level 1 Checkpoint
- What's Next: Pod-to-Pod Communication
The Problem Kubernetes Has
Picture a bare Kubernetes Node with no Pods running yet:
Node
┌─────────────────────────────────────┐
│ Kubernetes Node │
│ ??? │
└─────────────────────────────────────┘
Now Kubernetes wants to run a Pod:
Pod
┌─────────────────┐
│ nginx │
│ eth0 │
│ 10.244.1.5 │
└─────────────────┘
Here's the catch: who creates eth0? Who assigns the Pod its IP, 10.244.1.5? And who connects that interface to the Node's network?
Linux doesn't do any of this automatically just because Kubernetes decided to create a Pod. We need a dedicated networking component to make it happen.
The Solution: CNI
This is where the Container Network Interface (CNI) comes in. Think of CNI as:
The component responsible for connecting a newly created Pod to the network.
Simplified, the flow looks like this:
Kubernetes
| "I created a Pod."
↓
Container Runtime
| "Pod needs networking."
↓
CNI
├── Create network namespace
├── Create veth pair
├── Put one side inside the Pod
├── Connect the other side to the Node
├── Assign an IP
└── Configure routes
We'll go much deeper into CNI implementations later in this series (Level 7). For now, just remember its role: CNI is what gives Pods networking.
Every Pod Gets Its Own Network Namespace
Remember network namespaces from Level 0? A Kubernetes Pod gets its own network namespace, giving it an isolated networking environment:
Node
┌─────────────────────────────────────────┐
│ Pod Network Namespace │
│ ┌───────────────────────────────┐ │
│ │ eth0 │ │
│ │ 10.244.1.5 │ │
│ └───────────────────────────────┘ │
└─────────────────────────────────────────┘
This isolation is exactly what allows dozens of Pods to run on the same Node without their networking colliding.
Inspecting the Pod's eth0
Inside a running Pod, running:
ip addr
typically shows something like:
1: lo
2: eth0@if123
inet 10.244.1.5/24
The important takeaway: the Pod has its own network interface (eth0) and its own IP address (10.244.1.5).
Where Does eth0 Connect? The veth Pair
This is where our Level 0 knowledge pays off. A Pod's eth0 is typically connected to the Node using a veth pair — the same mechanism we covered earlier.
Kubernetes Node
┌─────────────────────────────────────────────┐
│ Pod namespace │
│ ┌────────────────────┐ │
│ │ eth0 │ │
│ │ 10.244.1.5 │ │
│ └─────────┬──────────┘ │
│ │ │
│ veth │
│ ║ │
│ veth │
│ │ │
│ ↓ │
│ Node network │
└─────────────────────────────────────────────┘
Think of it as a virtual cable: one end (eth0) lives inside the Pod, and the other end (veth) lives on the Node.
Why We Need the veth Pair
The Pod is isolated inside its own network namespace, which means it has no natural connection to the Node's namespace:
Pod namespace
|
| ???
|
Node namespace
The veth pair bridges that gap:
Pod namespace
|
eth0
|
veth
║
veth
|
Node namespace
In short, the veth pair is the virtual cable that connects an isolated Pod to the rest of the Node's networking stack.
Multiple Pods on One Node
Now imagine three Pods running on the same Node:
Pod A → 10.244.1.5
Pod B → 10.244.1.6
Pod C → 10.244.1.7
Conceptually, the Node might look like this:
Node
┌────────────────────────────────────────────┐
│ Pod A (10.244.1.5) │
│ │ │
│ veth ───────────┐ │
│ ↓ │
│ Bridge │
│ ↑ │
│ veth ───────────┘ │
│ │ │
│ Pod B (10.244.1.6) │
│ │
│ Pod C (10.244.1.7) │
└────────────────────────────────────────────┘
The exact implementation varies by CNI plugin, but the mental model stays consistent:
Pod → eth0 → veth → Node networking
Where Does the Pod IP Come From?
Who decided Pod A should get 10.244.1.5? The networking implementation allocates IPs from a defined address range.
For example, a cluster might use a Pod CIDR of 10.244.0.0/16, split into smaller ranges per Node:
Node 1: 10.244.1.0/24
Node 2: 10.244.2.0/24
Node 3: 10.244.3.0/24
So on Node 1:
Pod A → 10.244.1.5
Pod B → 10.244.1.6
Pod C → 10.244.1.7
This is just one example architecture — different CNIs and cluster configurations allocate ranges differently, so don't memorize these exact numbers.
Understanding Pod CIDR
A Pod CIDR is the IP address range allocated for all Pods in the cluster. For example, 10.244.0.0/16 represents a large address space reserved specifically for Pod IPs:
Cluster
└── Pod Network
├── 10.244.1.x
├── 10.244.2.x
├── 10.244.3.x
└── ...
Again, actual ranges vary by cluster and CNI plugin — what matters is understanding the concept.
Node CIDR vs Pod CIDR
This distinction trips up a lot of beginners. Consider:
Node IP: 192.168.1.10
Pod IP: 10.244.1.5
These belong to entirely different networks:
Node Network: 192.168.1.0/24
↓
Pod Network: 10.244.0.0/16
Don't assume a Pod's IP belongs to the same subnet as its Node's IP — in most Kubernetes setups, it doesn't. This is one of the key ideas that unlocks the rest of Kubernetes networking.
The Complete Pod Networking Stack
Putting it all together:
Kubernetes Node
┌───────────────────────────────────────────────┐
│ Pod Network Namespace │
│ ┌───────────────────────────┐ │
│ │ Container │ │
│ │ Application │ │
│ │ ↓ │ │
│ │ eth0 (10.244.1.5) │ │
│ └────────────┬──────────────┘ │
│ │ │
│ veth │
│ ║ │
│ veth │
│ │ │
│ ↓ │
│ Node networking │
│ │ │
│ ↓ │
│ Physical NIC │
└───────────────┼───────────────────────────────┘
↓
Network
What Happens When a Pod Is Created
Let's walk through the sequence triggered by:
kubectl run nginx --image=nginx
- Kubernetes receives the request.
- The Pod gets scheduled onto a Node.
- The container runtime prepares the Pod.
- Networking gets configured:
Pod created
↓
Network namespace created
↓
CNI called
↓
veth pair created
↓
Pod gets eth0
↓
IP assigned
↓
Routes configured
↓
Pod networking ready
↓
Container starts
This sequence is one of the most important things to internalize in this article.
The Pause Container: Kubernetes' Hidden Detail
Here's a subtlety many tutorials skip: Kubernetes doesn't give every container its own network namespace — it gives every Pod one shared namespace, owned by a special pause container.
Pod
┌─────────────────────────────────┐
│ Pause container │
│ └── Pod network namespace │
│ │
│ nginx container │
│ sidecar container │
└─────────────────────────────────┘
Every container in the Pod shares the Pod's:
- network namespace
- IP address
- network interfaces
- ports
Multiple Containers, One Network Namespace
Consider a Pod with three containers:
Pod
┌────────────────────────────────────┐
│ Container A │
│ Container B │
│ Container C │
│ │
│ Shared network namespace │
│ eth0 → 10.244.1.5 │
└────────────────────────────────────┘
All three containers share 10.244.1.5 and can talk to each other over localhost:
Container A → localhost:8080 → Container B
...provided Container B is actually listening on that port.
Port Collisions Inside a Pod
Because containers in a Pod share a network namespace, this can happen:
Container A → :8080
Container B → :8080 ❌
This is a real conflict — two processes can't simultaneously own 10.244.1.5:8080. This is a great example of why understanding raw Linux networking (from Level 0) directly explains real Kubernetes behavior.
Pod-to-Pod Communication (Same Node)
Now suppose Pod A (10.244.1.5) and Pod B (10.244.1.6) are on the same Node:
Pod A (10.244.1.5)
↓
veth
↓
Node networking
↓
veth
↓
Pod B (10.244.1.6)
The exact mechanism depends on the CNI plugin in use — we'll dig into specific implementations in Level 2 and Level 7.
Pods on Different Nodes
Here's where things get genuinely interesting. Consider two Pods on two different Nodes:
Node 1 Node 2
Pod A: 10.244.1.5 Pod B: 10.244.2.5
Pod A wants to reach Pod B directly by IP:
┌──────────── Node 1 ────────────┐
│ Pod A (10.244.1.5) │
└──────────────┬─────────────────┘
│
│ Network
│
┌──────────────▼─────────────────┐
│ Node 2 │
│ Pod B (10.244.2.5) │
└────────────────────────────────┘
This raises a critical question: how does traffic from Pod A reach a Pod IP living on a completely different machine? That question is exactly where Level 2 of this series picks up.
The Kubernetes Networking Model
Kubernetes enforces an important networking guarantee:
Pod A → (direct Pod IP) → Pod B
Pods must be able to communicate across Nodes without the application needing to know or care which Node they're running on. The underlying networking implementation is responsible for making this transparent, typically using one of:
- Overlay networking
- Routing-based networking
- Encapsulation (e.g., VXLAN)
- Cloud-native networking
- eBPF-based networking
We'll explore each of these approaches later in the series.
What CNI Actually Does: A Preview
By now you have a much clearer picture of what "CNI" really means. When a Pod is created, the CNI plugin handles:
CNI
├── Network namespace
├── veth pair
├── Pod interface
├── IP address
├── Routes
└── Connectivity
Don't worry about specific CNI implementations yet — that's reserved for Level 7. For now: CNI is the mechanism that gives Pods networking.
Hands-On: Inspecting a Real Pod
Let's verify everything we've learned with real commands.
Create a Pod:
kubectl run nginx --image=nginx
Check its IP and Node:
kubectl get pod -o wide
NAME READY STATUS IP NODE
nginx 1/1 Running 10.244.1.5 node-1
You now have a direct mapping: Pod name → Pod IP → Node.
Check the interface inside the Pod:
kubectl exec -it nginx -- ip addr
lo
eth0@if...
inet 10.244.1.5/...
This confirms the chain: Pod → network namespace → eth0 → Pod IP.
Check the Pod's routing table:
kubectl exec -it nginx -- ip route
default via ...
10.244.1.0/24 dev eth0
The exact output depends on your CNI plugin, but the key question the routing table answers is always the same: where does the Pod send traffic when it wants to reach something?
Note: At this point you might come across implementation-specific interfaces like
docker0,cni0,flannel.1,vxlan.calico,cilium_host, orcilium_net. Don't let these confuse you — they're all specific implementations of the same abstraction:Pod → namespace → eth0 → veth → Node networking → CNI.
Level 1 Mental Model
You should now be able to visualize a Node running multiple Pods like this:
NODE
┌────────────────────────────────────────────┐
│ Pod A │
│ ┌─────────────────────────────┐ │
│ │ Network Namespace │ │
│ │ eth0 (10.244.1.5) │ │
│ └─────────────┬───────────────┘ │
│ │ │
│ veth │
│ ║ │
│ ↓ │
│ Node networking │
│ │
│ Pod B │
│ ┌─────────────────────────────┐ │
│ │ Network Namespace │ │
│ │ eth0 (10.244.1.6) │ │
│ └─────────────┬───────────────┘ │
│ │ │
│ veth │
│ ║ │
│ ↓ │
│ Node networking │
└────────────────────────────────────────────┘
The core chain to remember:
Pod → Network Namespace → eth0 → veth pair → Node networking → CNI
And two important corollaries:
- Each Pod gets its own IP.
- Containers within the same Pod share that Pod's network namespace, IP, and can talk to each other via
localhost.
The fundamental communication model in Kubernetes is simply:
Pod A → Pod IP → Pod B
Level 1 Checkpoint
Before moving to Level 2, make sure these all make sense to you:
Q1. Who gives a Pod its networking?
→ The CNI (networking implementation).
Q2. Does a Pod have its own IP?
→ Yes.
Q3. Does each container in a Pod get its own IP?
→ No — containers in the same Pod share the Pod's network namespace and IP address.
Q4. What connects the Pod's network namespace to the Node?
→ Commonly, a veth pair.
Q5. Where does eth0 exist?
→ Inside the Pod's network namespace.
Q6. Why do we need CNI at all?
→ Kubernetes needs a networking implementation to create and configure Pod networking and provide connectivity between Pods.
What's Next: Pod-to-Pod Communication
In Level 2, we'll tackle the most important networking question in this series so far:
Pod A has
10.244.1.5. Pod B has10.244.2.5. They're on different Nodes. How does a packet actually travel from A to B?
We'll trace the packet hop by hop:
Pod A → eth0 → veth → Node 1 → routing → CNI network → Node 2 → veth → Pod B
...and compare same-node versus cross-node Pod communication in detail.
Conclusion
Pod networking is where Kubernetes and Linux networking truly meet. Every Pod gets its own network namespace and eth0 interface, connected to the Node via a veth pair, with an IP address allocated from the cluster's Pod CIDR — all orchestrated by the CNI plugin. Containers within a Pod share that networking environment entirely, which is why they can talk to each other over localhost but must be careful about port collisions.
The best way to cement these concepts is to try it yourself: spin up a Pod, run kubectl get pod -o wide, then kubectl exec in and inspect ip addr and ip route. Seeing the abstraction match real output is what makes the model stick.
Found this useful? Follow along for Level 2, where we trace a packet's full hop-by-hop journey between Pods on different Nodes. Drop a comment with your questions, and share this with someone still mixing up Pod CIDR and Node CIDR — let's keep demystifying Kubernetes networking together. 🚀
Top comments (1)
Great source 👏
Well explained