In the previous article we saw how kubelet orchestrates storage, network, and compute resources to bring a Pod to life. Now let's trace what happens when that Pod actually sends and receives data — following packets hop by hop through virtual ethernet devices, CNI bridges, and Flannel overlays.
Network solution context: Kubernetes supports multiple CNI plugins (Calico, Cilium, Flannel, Weave Net, Contiv-VPP, Kube-router). This article uses Flannel as the reference implementation — it's the most representative for understanding the underlying data flow.
Overview: 6 Traffic Scenarios
| # | Scenario | Crosses host boundary? | Crosses cluster boundary? |
|---|---|---|---|
| 1 | Container → Container (same Pod) | ❌ | ❌ |
| 2 | Pod → Pod (same host) | ❌ | ❌ |
| 3 | Host → Pod (same host) | ❌ | ❌ |
| 4 | Pod → Pod (different hosts) | ✅ | ❌ |
| 5 | External app → Pod | ✅ | ✅ |
| 6 | Pod → External app | ✅ | ✅ |
Scenario 1: Container → Container (Same Pod)
All containers in a Pod share one network namespace — they communicate via the shared Linux network stack, never touching the host.
Container 0 Container n
┌──────────────┐ ┌──────────────┐
│ App │ │ App │
│ Veth0 │ │ Veth0 │
└──────┬───────┘ └──────┬───────┘
│ │
Vethx ◄──── Pod Shared ────► Vethy
Network Stack
(shared netns)
Step-by-step:
① Container 0 sends request via its Veth0
② Veth0's peer Vethx receives data
→ passes through Pod's shared network stack
③ Vethy (peer of Container n's Veth0) receives data
→ forwards to Container n's Veth0
④ Container n receives the request ✅
Response follows the reverse path.
Key insight: Intra-Pod communication is essentially localhost traffic. Containers share the same IP and communicate via port numbers, just like processes on the same machine.
Scenario 2: Pod → Pod (Same Host)
When two Pods are on the same node, traffic flows through the CNI0 bridge — a virtual Layer 2 switch that connects all Pods on the node.
Source Host
┌──────────────────────────────────────────────────────────┐
│ │
│ Source Pod CNI0 Bridge Target Pod │
│ ┌──────────┐ ┌─────────┐ ┌──────────┐ │
│ │Container0│ │ Vethc │ │Container0│ │
│ │ Veth0 │ │ Vethd │ │ Veth0 │ │
│ └────┬─────┘ └────┬────┘ └────┬─────┘ │
│ │ │ │ │
│ Vetha bridge Vethf │
│ (shared netns) (L2 switch) (shared netns) │
│ Vethb ──────────► Vethc Vethe │
│ Vethd ──────────► Vethe │
│ Vethf │
└──────────────────────────────────────────────────────────┘
Step-by-step:
① Container 0 (src) sends via Veth0
② Veth0's peer Vetha receives → passes through src Pod shared netns
③ Vethb sends data out of src Pod netns
④ Vethc (Vethb's peer on CNI0 bridge) receives
→ CNI0 bridge forwards to target Pod direction
⑤ Vethd on CNI0 bridge sends toward target Pod
⑥ Vethe (Vethd's peer in target Pod netns) receives
⑦ Vethf (peer of target Container 0's Veth0) forwards data
⑧ Target Container 0's Veth0 receives ✅
Response follows the reverse path.
Scenario 3: Host → Pod (Same Host)
When the node itself needs to communicate with a Pod running on it (e.g., kubelet health checks, host-level monitoring):
Host Network Stack
┌──────────────────────────────────────────────────────────┐
│ │
│ Host Process │
│ │ │
│ ▼ │
│ Host routing table │
│ │ (route to Pod CIDR → Flannel.1) │
│ ▼ │
│ Flannel.1 (virtual bridge) │
│ │ │
│ Vetha ──────────────────────────────────────────────► │
│ │
│ CNI0 Bridge │
│ Vethb (Vetha's peer) ──► Vethc │
│ │
│ Target Pod netns │
│ Vethd (Vethc's peer) │
│ Vethe │
│ Target Container 0's Veth0 ✅ │
└──────────────────────────────────────────────────────────┘
Step-by-step:
① Host process initiates request to target Pod IP
② Host routing table: Pod CIDR → next hop via Flannel.1
③ Request enters Flannel.1 virtual bridge → exits via Vetha
④ CNI0 bridge's Vethb (Vetha's peer) receives → bridge forwards
⑤ CNI0 bridge's Vethc sends toward target Pod
⑥ Vethd (Vethc's peer in Pod netns) receives → forwards
⑦ Vethe in Pod netns forwards to Container 0's Veth0
⑧ Target Container 0 receives ✅
Response follows the reverse path.
Scenario 4: Pod → Pod (Different Hosts)
Cross-host Pod communication requires Flannel's overlay network — the flanneld daemon encapsulates packets and routes them through the underlying physical network.
Source Host Target Host
┌──────────────────────────┐ ┌──────────────────────────┐
│ Source Pod │ │ Target Pod │
│ Container 0 │ │ Container 0 │
│ Veth0 → Vetha │ │ Vethg ← Veth0 │
│ (src Pod netns) │ │ (tgt Pod netns) │
│ Vethb → Vethc (CNI0) │ │ Vethf ← Vethe (CNI0) │
│ Vethd → Vethe (CNI0) │ │ Vethd ← Vethc (CNI0) │
│ Flannel.1 virtual bridge│ │ Flannel.1 virtual bridge│
│ flanneld intercepts │ │ flanneld decapsulates │
│ Vethf (host NIC) ──────────────► Vethg (host NIC) │
│ │ UDP │ │
│ physical network │ │
└──────────────────────────┘ └──────────────────────────┘
Step-by-step:
Source side:
① Container 0 (src) sends via Veth0
② Vetha (peer) receives → src Pod shared netns
③ Vethb sends out of src Pod netns
④ Vethc (CNI0 bridge peer of Vethb) receives
→ CNI0 bridge: destination is on another host
⑤ Vethd on CNI0 bridge sends toward Flannel.1
⑥ Vethe (Flannel.1 peer of Vethd) receives
→ enters Flannel.1 virtual bridge
Flannel overlay:
⑦ flanneld intercepts packet leaving Flannel.1
→ looks up destination IP in routing table
→ destination is on a different host
⑧ flanneld encapsulates packet (VXLAN/UDP)
→ sends via host NIC Vethf to target host
Target side (reverse of source):
⑨ Target host NIC Vethg receives encapsulated packet
→ flanneld decapsulates
→ Flannel.1 → CNI0 bridge → target Pod netns
→ Target Container 0's Veth0 receives ✅
Flannel's role:
flanneldmaintains a distributed routing table (backed by etcd) mapping Pod CIDRs to host IPs. When a packet needs to cross hosts, it wraps the original packet in a UDP/VXLAN envelope addressed to the target host's physical IP.
Scenario 5: External App → Cluster Pod
Traffic from outside the cluster must enter through a gateway node, then be routed through Flannel to the target Pod.
External App
│
▼
Gateway Node
┌──────────────────────────────────────────────────────────────┐
│ Gateway service intercepts request │
│ Looks up route to target Pod IP │
│ Sends via Vetha (gateway NIC) → physical network │
└──────────────────────────────────────────────────────────────┘
│ (physical network)
▼
Target Pod's Host
┌──────────────────────────────────────────────────────────────┐
│ Vethb (host NIC) receives packet │
│ Host routing: → Flannel process │
│ Flannel processes packet → Flannel.1 virtual bridge │
│ Flannel.1 → Vethc → CNI0 bridge │
│ CNI0: Vethd → Vethe → target Pod netns │
│ Pod netns: Vethf → Vethg → target Container 0's Veth0 ✅ │
└──────────────────────────────────────────────────────────────┘
Step-by-step:
① External app sends request to cluster Service/NodePort IP
② Gateway service intercepts the request
③ Gateway looks up route to target Pod's host
④ Request sent via gateway NIC Vetha → physical network
⑤ Target host NIC Vethb receives packet
⑥ Host routing table → Flannel process handles packet
Flannel → Flannel.1 virtual bridge
⑦ Flannel.1 sends via Vethc
⑧ CNI0 bridge's Vethd (Vethc's peer) receives → bridge forwards
⑨ CNI0 bridge's Vethe sends toward target Pod
⑩ Pod netns Vethf (Vethe's peer) receives → forwards
⑪ Pod netns Vethg forwards to Container 0's Veth0
⑫ Target Container 0 receives ✅
Response follows the exact reverse path back to external app.
Scenario 6: Cluster Pod → External App
This is simply Scenario 5 in reverse. The packet originates from the container, travels through Pod netns → CNI0 → Flannel.1 → flanneld → host NIC → physical network → gateway → external app.
Target Container 0's Veth0
→ Pod netns (Vethg → Vethf)
→ CNI0 bridge (Vethe → Vethd → Vethc)
→ Flannel.1 (Vethb)
→ flanneld (encapsulate for external routing)
→ Host NIC
→ Physical network
→ Gateway node
→ External app ✅
The Full Network Stack: Component Roles
| Component | Layer | Role |
|---|---|---|
| Veth0 (in container) | Container | Virtual NIC inside each container |
| Veth pair (Vethx/Vethy) | Pod netns | Connect container to Pod's shared network namespace |
| Pod shared netns | Pod | Shared network stack — all containers in a Pod share one IP |
| CNI0 bridge | Node | Layer 2 virtual switch connecting all Pods on the same node |
| Flannel.1 | Node | Virtual bridge for Flannel overlay network entry/exit point |
| flanneld | Node | Daemon that encapsulates/decapsulates cross-host packets |
| Host NIC | Node | Physical network interface — carries encapsulated overlay traffic |
| Gateway service | Cluster edge | Entry point for external traffic into the cluster |
Summary: Traffic Path by Scenario
Scenario 1 (same Pod):
Container → Veth0 → Vethx → Pod netns → Vethy → Veth0 → Container
Scenario 2 (same host, diff Pod):
Container → Veth0 → Pod netns → CNI0 bridge → Pod netns → Veth0 → Container
Scenario 3 (host → Pod):
Host process → routing → Flannel.1 → CNI0 bridge → Pod netns → Container
Scenario 4 (diff host):
Container → Pod netns → CNI0 → Flannel.1 → flanneld → host NIC
──[physical network]──►
host NIC → flanneld → Flannel.1 → CNI0 → Pod netns → Container
Scenario 5 (external → Pod):
External → gateway → physical network → host NIC → Flannel → CNI0 → Pod
Scenario 6 (Pod → external):
Pod → CNI0 → Flannel → host NIC → physical network → gateway → external
Understanding these 6 traffic paths gives you a complete mental model of Kubernetes networking — from the veth pair inside a single container all the way to traffic crossing physical datacenter boundaries.
Next in this series: Multi-Cloud & Hybrid Cloud: Kubernetes Federation and Multi-Cluster Use Cases (Part 7)
Follow the series for more deep dives into Kubernetes internals.
Top comments (0)