DEV Community

Cover image for Kubernetes Networking [Level-9: Kubernetes Networking Internals]
ADITYA RAJ
ADITYA RAJ

Posted on

Kubernetes Networking [Level-9: Kubernetes Networking Internals]

This is Level 9 of our Kubernetes networking series — and it's where everything we've learned finally converges into a single story. In earlier levels, we mostly viewed networking from the outside:

Pod → Service → Pod
Enter fullscreen mode Exit fullscreen mode

Now we're going inside the Node, following one packet through the actual Linux kernel:

Network namespace
   ↓
veth
   ↓
Linux kernel
   ↓
routing
   ↓
iptables / eBPF / IPVS
   ↓
conntrack / NAT
   ↓
veth
   ↓
destination Pod
Enter fullscreen mode Exit fullscreen mode

The goal of this article is simple: understand what actually happens to a packet inside a Kubernetes Node.

Table of Contents

  1. The Complete Picture, First
  2. Network Namespaces, Revisited
  3. The veth Pair
  4. Why eth0 Is Confusing
  5. Pod → Node: The Core Diagram
  6. Linux Routing Inside the Pod
  7. Routing Is a Decision, Not Magic
  8. Same-Node Pod Communication
  9. The Linux Bridge
  10. What Happens When the Packet Reaches the Node
  11. Direct Pod Traffic vs Service Traffic
  12. Netfilter: Linux's Packet-Processing Framework
  13. Where iptables Fits In
  14. NAT, Revisited With a Real Example
  15. Why NAT Needs State
  16. conntrack: Connection Tracking
  17. Why conntrack Matters in Production
  18. A Simplified Linux Packet Path
  19. There's No Single Universal Packet Path
  20. Pod-to-Pod, Same Node
  21. Pod-to-Pod, Different Nodes
  22. Overlay Internals
  23. Why Overlays Exist
  24. Routing-Based Networking
  25. Why BGP Sometimes Appears
  26. CNI vs the Linux Kernel
  27. eBPF in the Internal Path
  28. NetworkPolicy in the Packet Path
  29. Service + NetworkPolicy Together
  30. Why Services Don't Have Network Interfaces
  31. Node IP vs Pod IP vs Service IP
  32. Why Pod IPs Aren't Directly Routable from the Internet
  33. A Full External Traffic Example
  34. The Complete Kubernetes Networking Stack
  35. A Real Packet Journey, Start to Finish
  36. Return Traffic
  37. What Can Break
  38. The Most Important Troubleshooting Principle
  39. Direct Pod IP vs Service IP: The Best Diagnostic Test
  40. Useful Linux Commands
  41. Interview Traps Worth Knowing
  42. The Entire Series So Far
  43. Level 9 Checkpoint
  44. The Most Important Lesson From This Article
  45. What's Next: Production Troubleshooting

The Complete Picture, First

Let's set up a running example. A Frontend Pod (10.244.1.10) calls backend.default.svc.cluster.local. DNS resolves this to 10.96.120.50. The backend Pods are 10.244.1.20, 10.244.2.20, and 10.244.3.20.

The logical path looks simple:

Frontend Pod (10.244.1.10)
      ↓
Service IP (10.96.120.50)
      ↓
Service dataplane
      ↓
Backend Pod (10.244.2.20)
Enter fullscreen mode Exit fullscreen mode

But physically, inside Linux, there's a lot more going on — and that's exactly what this article unpacks.

Network Namespaces, Revisited

A Pod gets its own network namespace — think of it as a completely separate networking world inside Linux, with its own interfaces, IP addresses, routes, and network state:

Pod network namespace
┌─────────────────────────┐
│ eth0                    │
│ 10.244.1.10             │
│ route table             │
└─────────────────────────┘
Enter fullscreen mode Exit fullscreen mode

The Node itself lives in its own, separate network namespace:

Node network namespace
┌─────────────────────────┐
│ eth0                    │
│ cni interfaces          │
│ routes                  │
│ iptables/eBPF           │
└─────────────────────────┘
Enter fullscreen mode Exit fullscreen mode

The key takeaway: Pod namespace ≠ Node namespace. They're isolated from each other by design.

The veth Pair

How do these two isolated worlds talk to each other? Commonly, through a veth pair — a virtual Ethernet cable:

Pod namespace                 Node namespace

┌──────────────┐             ┌──────────────┐
│    eth0      │=============│   vethXXXX   │
└──────────────┘             └──────────────┘
                    ↑
                 veth pair
Enter fullscreen mode Exit fullscreen mode

One end lives inside the Pod's namespace; the other lives inside the Node's namespace.

Why eth0 Is Confusing

Inside the Pod, ip addr shows eth0 at 10.244.1.10. But on the Node itself, you generally won't find another interface also called eth0 representing that same Pod. Instead, the Node-side end typically has an implementation-specific name, like vethabc123:

Pod:  eth0
Node: vethabc123
Enter fullscreen mode Exit fullscreen mode

These two differently-named ends form a single virtual Ethernet connection between the two namespaces.

Pod → Node: The Core Diagram

The simplest possible mental model, and one of the most important diagrams in all of Kubernetes networking:

Pod → eth0 → veth → Node
Enter fullscreen mode Exit fullscreen mode

Linux Routing Inside the Pod

Once a packet is inside the Pod, with source = 10.244.1.10 and destination = 10.244.2.20, the Pod's network namespace needs to decide: where should this go? Linux answers that using its routing table, viewable with:

ip route
Enter fullscreen mode Exit fullscreen mode

Conceptually:

Destination       Next hop
10.244.1.0/24      local
default            ...
Enter fullscreen mode Exit fullscreen mode

The exact contents depend entirely on your CNI implementation.

Routing Is a Decision, Not Magic

Think of the routing table as a map:

Packet destination (10.244.2.20)
        ↓
Routing table
        ↓
Which route matches?
        ↓
Which interface/next hop?
Enter fullscreen mode Exit fullscreen mode

The core principle: Linux always chooses the most specific matching route.

Same-Node Pod Communication

Suppose Pod A (10.244.1.10) and Pod B (10.244.1.20) are both on Node 1:

Pod A → eth0 → veth → Node networking → veth → eth0 → Pod B
Enter fullscreen mode Exit fullscreen mode

There might be a Linux bridge, straightforward routing, eBPF processing, or something else entirely in the middle — it depends on the CNI. Don't memorize "every Kubernetes cluster uses a bridge" — that's simply false. The correct mental model is: the CNI/networking implementation provides a path between the Pod namespaces, using whatever mechanism it's designed around.

The Linux Bridge

A common Linux networking component is the bridge — think of it as a virtual Layer-2 switch:

             Linux bridge
          ┌───────────────┐
          └─┬─────┬─────┬─┘
            │     │     │
          veth   veth   veth
            │     │     │
          Pod A Pod B Pod C
Enter fullscreen mode Exit fullscreen mode

A bridge can connect multiple interfaces at Layer 2. But again — not every CNI uses a Linux bridge as its main datapath. Some rely on routing, overlays, cloud-native networking, or eBPF instead.

What Happens When the Packet Reaches the Node

Suppose Pod A (10.244.1.10) sends a packet destined for 10.244.2.20. The packet exits through eth0 and arrives at the Node's networking stack — and this is exactly where Level 8 becomes relevant again. From here, the packet may pass through routing, iptables, IPVS, eBPF, conntrack, and/or NAT, depending on the implementation.

Direct Pod Traffic vs Service Traffic

It's worth comparing two very different packets side by side.

Direct Pod-to-Pod:

Pod A → Pod B
Destination: 10.244.2.20
Enter fullscreen mode Exit fullscreen mode

Service traffic:

Pod A → Service → Pod B
Destination (initially): 10.96.120.50
Enter fullscreen mode Exit fullscreen mode

The second path requires Service handling — the Service dataplane has to translate 10.96.120.50 → 10.244.2.20 before normal Pod-to-Pod delivery can even begin. This is exactly why Service traffic is more involved than plain Pod-to-Pod traffic.

Netfilter: Linux's Packet-Processing Framework

Now for a foundational Linux concept: Netfilter. Netfilter is Linux's framework of packet-processing hooks — tools and features like iptables, NAT, and conntrack all interact with this underlying infrastructure:

Packet
   ↓
Linux networking stack
   ↓
Netfilter hooks
   ↓
filter / NAT / connection tracking
   ↓
routing / forwarding
Enter fullscreen mode Exit fullscreen mode

Modern systems may use nftables underneath familiar iptables tooling depending on the environment, but the conceptual Linux packet-processing framework — Netfilter — remains the important idea to hold onto.

Where iptables Fits In

From Level 8, we know: Service → iptables → backend. Now we can place it precisely within the kernel's processing pipeline:

Packet → Linux kernel → Netfilter → iptables rules → NAT / filtering / Service handling
Enter fullscreen mode Exit fullscreen mode

Kubernetes programs networking rules directly into this pipeline on each Node.

NAT, Revisited With a Real Example

Let's revisit NAT concretely. A client sends SRC = 10.244.1.10, DST = 10.96.120.50:80. The Service dataplane selects a backend, say 10.244.2.20:80:

10.96.120.50:80
        ↓
      DNAT
        ↓
10.244.2.20:80
Enter fullscreen mode Exit fullscreen mode

The destination changes — that's Destination NAT in action.

Why NAT Needs State

Now suppose Client → Service → Backend, and the response needs to travel Backend → Client. The kernel needs to remember the original translation to correctly map the response back. That's exactly what conntrack provides.

conntrack: Connection Tracking

conntrack is short for connection tracking — Linux's mechanism for maintaining state about active network connections. Given Client (10.244.1.10:50000) → Service (10.96.120.50:80) → Backend (10.244.2.20:80), the kernel tracks the relevant connection and NAT state:

Connection → conntrack → NAT state → return traffic handled correctly
Enter fullscreen mode Exit fullscreen mode

Why conntrack Matters in Production

This is a major real-world troubleshooting topic. You can end up in situations where new connections start failing, or existing connections start behaving unexpectedly — both can trace back to connection tracking / NAT state. At scale, conntrack itself becomes a resource with real limits. Watch for: conntrack table exhaustion, dropped connections, NAT failures, and intermittent connectivity. We'll dig into these production failure modes much more deeply in Level 10.

A Simplified Linux Packet Path

For a packet entering a Node, a simplified path looks like:

Network interface
       ↓
Linux kernel
       ↓
packet processing
       ↓
routing decision
       ↓
forwarding / local delivery
       ↓
destination interface
Enter fullscreen mode Exit fullscreen mode

For Kubernetes specifically, additional processing frequently includes iptables, conntrack, NAT, eBPF, NetworkPolicy enforcement, and Service load balancing — depending entirely on the networking implementation in use.

There's No Single Universal Packet Path

This point is critical enough to repeat explicitly: there is no single universal Kubernetes packet path. Clusters can use iptables, IPVS, eBPF, plain routing, overlays, cloud-native networking, or entirely different CNIs — and each combination produces a genuinely different path. The right approach is: learn the conceptual packet path first, then learn the implementation-specific path for your actual cluster. This is precisely how experienced engineers troubleshoot Kubernetes networking in the real world.

Pod-to-Pod, Same Node

The easiest case: Pod A (10.244.1.10) and Pod B (10.244.1.20) on the same Node.

┌────────── Pod A ──────────┐
│ eth0 (10.244.1.10)        │
└────────────┬──────────────┘
             │
           veth
             │
             ↓
       Node networking
             │
             ↓
           veth
             │
┌────────────┴──────────────┐
│ eth0 (10.244.1.20)        │
└────────── Pod B ──────────┘
Enter fullscreen mode Exit fullscreen mode

The exact middle processing depends entirely on the CNI implementation.

Pod-to-Pod, Different Nodes

Now Pod A (10.244.1.10) is on Node 1 and Pod B (10.244.2.20) is on Node 2:

Pod A → veth → Node 1 → Node-to-Node network → Node 2 → veth → Pod B
Enter fullscreen mode Exit fullscreen mode

The Node-to-Node portion can be implemented via routing, an overlay, a cloud provider's native network, or eBPF — again, entirely dependent on the CNI.

Overlay Internals

Suppose the CNI uses an overlay. The inner packet is Pod A → Pod B, and it gets wrapped inside an outer packet Node 1 → Node 2:

┌───────────────────────────────┐
│ Outer packet: Node1 → Node2   │
│                               │
│   ┌─────────────────────────┐ │
│   │ Inner packet:           │ │
│   │ Pod A → Pod B           │ │
│   └─────────────────────────┘ │
└───────────────────────────────┘
Enter fullscreen mode Exit fullscreen mode

Node 2 strips off the outer wrapper and delivers the inner packet toward Pod B. That's the basic idea behind overlay networking, made concrete.

Why Overlays Exist

Imagine your physical network only knows about Node 1 (192.168.1.10) and Node 2 (192.168.1.20) — it has no idea about 10.244.1.10 or 10.244.2.20. The physical network doesn't need to know about every individual Pod route; instead, the overlay carries the Pod network inside the Node network — literally, a network running over another network.

Routing-Based Networking

An alternative to overlays: teach the physical network how to reach each Pod CIDR directly. Given Node 1 → 10.244.1.0/24 and Node 2 → 10.244.2.0/24, Node 1 can simply have a route: 10.244.2.0/24 → Node 2. Then:

Pod A → Node 1 → route → Node 2 → Pod B
Enter fullscreen mode Exit fullscreen mode

No encapsulation required at all.

Why BGP Sometimes Appears

If many Nodes each own different Pod CIDRs, you need a way to distribute all those routes across the cluster. Some networking implementations use BGP (Border Gateway Protocol) for exactly this:

Node 1 (10.244.1.0/24) ↔ BGP ↔ Node 2 (10.244.2.0/24)
Enter fullscreen mode Exit fullscreen mode

This is exactly why BGP comes up so often in discussions of Calico and Kubernetes networking.

CNI vs the Linux Kernel

An important distinction: the CNI/networking implementation doesn't replace Linux networking — it configures and uses it.

CNI → configure → Linux networking → interfaces / routes / kernel dataplane
Enter fullscreen mode Exit fullscreen mode

For example: CNI → create veth → Linux kernel, or CNI → configure routes → Linux kernel, or CNI → load eBPF programs → Linux kernel. The CNI is the orchestrator; the kernel is what actually does the work.

eBPF in the Internal Path

Connecting Level 8 back to Level 9: with an eBPF-based CNI, packet processing might conceptually look like:

Pod → veth → Linux kernel → eBPF program → routing / policy / load balancing → destination
Enter fullscreen mode Exit fullscreen mode

The exact hook points and processing path depend on the specific implementation. The core concept to hold onto: eBPF lets a networking implementation inject programmable packet-processing logic directly into the Linux kernel.

NetworkPolicy in the Packet Path

Suppose a NetworkPolicy states frontend → backend:8080 = ALLOW. The networking implementation has to enforce that somewhere along the path:

Packet → network dataplane → NetworkPolicy check → ALLOW → Backend
Enter fullscreen mode Exit fullscreen mode

or, alternatively:

Packet → NetworkPolicy check → DENY → ✗
Enter fullscreen mode Exit fullscreen mode

The exact enforcement point in the kernel depends on the implementation.

Service + NetworkPolicy Together

Now combine Service and NetworkPolicy. The Service selects backend Pods; NetworkPolicy applies restrictions to those Pods:

Frontend → Service IP → Service dataplane → Backend Pod → NetworkPolicy enforcement
Enter fullscreen mode Exit fullscreen mode

The exact ordering within the kernel can vary by implementation — don't treat this as a strict, universal literal sequence. The important conceptual point: the Service selects and forwards toward backend Pods; NetworkPolicy controls what Pod traffic is actually allowed.

Why Services Don't Have Network Interfaces

An excellent interview question. You might assume the Service IP 10.96.120.50 must correspond to some eth0 somewhere — but that's usually the wrong way to think about it. A ClusterIP is a virtual IP implemented by the Service dataplane, not a physical interface:

ClusterIP (10.96.120.50) → virtual service → backend endpoints
Enter fullscreen mode Exit fullscreen mode

It simply doesn't need to be — and usually isn't — a physical network interface anywhere.

Node IP vs Pod IP vs Service IP

By Level 9, you should be completely comfortable distinguishing:

Node IP    (192.168.1.10)  → physical/VM host networking
Pod IP     (10.244.1.10)   → workload networking
Service IP (10.96.120.50)  → virtual service endpoint
Enter fullscreen mode Exit fullscreen mode

Three distinct layers, each solving a different problem.

Why Pod IPs Aren't Directly Routable from the Internet

A Pod's IP, like 10.244.1.10, is generally an internal cluster address — an internet router has no idea how to reach 10.244.1.0/24. That's exactly why external access normally has to go through a LoadBalancer, NodePort, Ingress, Gateway, NAT, or some form of cloud-native networking, depending on your architecture.

A Full External Traffic Example

Internet
    ↓
Public IP
    ↓
Load Balancer
    ↓
Node
    ↓
Service dataplane
    ↓
Pod
Enter fullscreen mode Exit fullscreen mode

Zooming into the Node itself: Node → iptables/IPVS/eBPF → Pod. And zooming into the Pod: Pod namespace → eth0 → veth → Node. Now you can see exactly how all these layers connect into one continuous path.

The Complete Kubernetes Networking Stack

This is the single diagram worth remembering from this entire article:

                         INTERNET
                            |
                            ↓
                    LoadBalancer / Ingress
                            |
                            ↓
                         Node
                            |
                ┌───────────┴───────────┐
                │ Linux kernel          │
                │                       │
                │ Service dataplane     │
                │ iptables / IPVS /     │
                │ eBPF                  │
                │                       │
                │ conntrack / NAT       │
                │                       │
                │ routing               │
                └───────────┬───────────┘
                            |
                          veth
                            |
                     Pod namespace
                            |
                           eth0
                            |
                           Pod
Enter fullscreen mode Exit fullscreen mode

And across Nodes: Pod → veth → Node 1 → Node-to-Node network → Node 2 → veth → Pod.

A Real Packet Journey, Start to Finish

Let's trace one complete, concrete example. We have Frontend Pod 10.244.1.10, Backend Service 10.96.120.50:80 (with port: 80, targetPort: 8080), and Backend Pod 10.244.2.20:8080. The frontend runs curl http://backend.

Step 1 — DNS: backend → 10.96.120.50.

Step 2 — TCP connection: the frontend creates a packet with SRC = 10.244.1.10:<ephemeral-port>, DST = 10.96.120.50:80.

Step 3 — Pod namespace routing: the packet leaves through the Pod's eth0 and crosses the veth pair.

Step 4 — Node kernel: the Node's networking stack now processes it — potentially involving routing, conntrack, the Service dataplane, NetworkPolicy, and NAT, depending on the implementation and packet path.

Step 5 — Service translation: the Service dataplane knows 10.96.120.50:80 should map to 10.244.2.20:8080, and performs that translation.

Step 6 — Route to backend: the networking layer determines how to actually reach 10.244.2.20 — if the backend lives on another Node, this involves Node 1 → Node network → Node 2.

Step 7 — Backend Node: Node 2 receives the packet, processes it through its own networking implementation, and delivers it: veth → Pod namespace → eth0 → backend application.

Return Traffic

The backend responds: Backend (10.244.2.20:8080) → Frontend (10.244.1.10:<port>). The Linux networking stack's NAT and connection-tracking state ensures the response correctly maps back through the original Service connection. Crucially, the frontend application never needs to know the backend Pod's real IP was 10.244.2.20 — it only ever knew it connected to backend:80. That abstraction is the entire point.

What Can Break

We're now firmly in production troubleshooting territory. This full packet journey can fail at many distinct points:

DNS → Service → EndpointSlice → Service dataplane → routing → CNI → NetworkPolicy → Pod → application
Enter fullscreen mode Exit fullscreen mode

Possible failure modes include: DNS not resolving, a Service with no endpoints, a wrong targetPort, incorrect iptables/IPVS/eBPF state, a missing route, a broken veth, a Pod with no IP, a CNI failure, NetworkPolicy blocking traffic, conntrack problems, a Node-level firewall, a cloud network ACL or security group, or simply an application that isn't listening. This is exactly why Level 10 will feel much more approachable after this article.

The Most Important Troubleshooting Principle

Don't ask: "Kubernetes networking is broken — what command should I run?" Instead ask:

"At which hop did the packet actually stop?"

For example, if DNS works, the Service exists, the endpoint exists, and the Pod IP is directly reachable — but the Service IP specifically fails — that strongly points toward the Service dataplane, not CNI. Alternatively, if Pod IP → Pod IP fails outright, that points much more toward CNI, routing, or NetworkPolicy.

Direct Pod IP vs Service IP: The Best Diagnostic Test

This single comparison is one of the most valuable troubleshooting techniques in Kubernetes networking. Test Pod A → Pod B IP directly, then test Pod A → Service IP.

If the Pod IP works but the Service IP fails: the likely culprit is the Service, its EndpointSlice, or the Service dataplane (kube-proxy/eBPF).

If both the Pod IP and the Service IP fail: investigate lower layers instead — CNI, routing, veth, NetworkPolicy, or Node networking.

This simple two-step comparison narrows down the problem space dramatically before you touch a single low-level command.

Useful Linux Commands

Inside a Pod:

ip addr    # interfaces/IPs
ip route   # routes
ss -lntp   # listening TCP sockets
Enter fullscreen mode Exit fullscreen mode

On a Node:

ip addr
ip route
ip link
Enter fullscreen mode Exit fullscreen mode

These commands together help you understand exactly what interfaces, addresses, and routes actually exist at each layer.

Seeing veth Interfaces

On a Node, ip link may reveal interfaces belonging to Pod networking — often named veth... or something CNI-specific. Don't assume any particular naming pattern always maps to a specific CNI; interface naming is implementation-dependent.

Seeing Routes

ip route on a Node may show entries like 10.244.1.0/24 ... and 10.244.2.0/24 ..., telling Linux exactly where Pod traffic should be directed. Again, the actual routes present depend entirely on your CNI.

Seeing iptables

If your cluster uses an iptables-based dataplane:

iptables-save
Enter fullscreen mode Exit fullscreen mode

This can reveal a large volume of Kubernetes-related networking state, including Kubernetes-specific chains. Don't worry about memorizing chain names yet — just understand conceptually that iptables rules → Service / NAT / filtering behavior.

Seeing IPVS

If your cluster uses IPVS:

ipvsadm -L
Enter fullscreen mode Exit fullscreen mode

This may show virtual services and their backend destinations, conceptually:

10.96.120.50:80
       +--- 10.244.1.20:80
       +--- 10.244.2.20:80
       +--- 10.244.3.20:80
Enter fullscreen mode Exit fullscreen mode

Seeing eBPF

If your cluster uses an eBPF-based implementation like Cilium, its own tooling can show endpoints, routes, service maps, policy state, and connectivity — the exact commands vary by implementation. The key Level 9 lesson here: don't inspect iptables just because you happen to know iptables — first determine which dataplane your cluster actually uses.

Interview Traps Worth Knowing

"Does every Kubernetes cluster use kube-proxy?"
No. Many clusters do, but alternative networking dataplanes can implement Kubernetes Service functionality without it — an eBPF-based implementation can provide full kube-proxy replacement.

"Does every CNI use a Linux bridge?"
No. Possible approaches include bridging, routing, overlays, cloud-native networking, and eBPF — the implementation determines the actual datapath.

"Is the Service IP configured on a Pod?"
No. A ClusterIP is a virtual Service address implemented by the Service dataplane; backend Pods each have their own separate, real IPs.

"Does the CNI forward Service traffic?"
The precise answer: CNI/networking provides Pod networking, while Kubernetes Service traffic is implemented by a separate Service dataplane — kube-proxy/iptables/IPVS, or an eBPF-based networking implementation. The exact packet path depends on the cluster. That's a far better answer than simply saying "CNI handles everything."

The Entire Series So Far

We can now connect all nine levels into one continuous story:

LEVEL 0 — Linux networking      → interfaces / routes / namespaces / NAT
LEVEL 1 — Pod networking        → Pod namespace / eth0 / veth
LEVEL 2 — Pod-to-Pod            → routing / node networking
LEVEL 3 — Services              → ClusterIP / endpoints
LEVEL 4 — DNS                   → Service name → ClusterIP
LEVEL 5 — Ingress / Gateway     → external HTTP/HTTPS → Service
LEVEL 6 — NetworkPolicy         → allowed network traffic
LEVEL 7 — CNI                   → Pod network implementation
LEVEL 8 — Service dataplane     → kube-proxy / iptables / IPVS / eBPF
LEVEL 9 — Internals             → Linux kernel packet path
Enter fullscreen mode Exit fullscreen mode

Level 9 Checkpoint

1. What is a network namespace?
An isolated Linux networking environment with its own interfaces, addresses, routes, and network state.

2. What is a veth pair?
A pair of virtual Ethernet interfaces commonly used to connect a Pod's network namespace to the Node.

3. What is a Linux bridge?
A virtual Layer-2 switch that can connect multiple interfaces together.

4. Does every CNI use a bridge?
No.

5. What is routing?
The process of deciding where a packet should be sent, based on its destination address.

6. What is DNAT?
Changing a packet's destination address/port — the common Kubernetes example is Service IP → backend Pod IP.

7. What is SNAT?
Changing a packet's source address/port — a common example is Pod IP → Node IP when traffic leaves the cluster, depending on configuration.

8. What is conntrack?
Linux's connection tracking mechanism, which maintains state about network flows, including NAT state.

9. What is an overlay?
A virtual network carried on top of another underlying network — a Pod network riding over a Node network.

10. Why can BGP be used?
To distribute routing information, such as routes to individual Pod CIDRs, across Nodes.

11. Why doesn't every Kubernetes cluster have the same packet path?
Because networking implementations and dataplanes genuinely differ from cluster to cluster.

12. How should you troubleshoot?
Find the first hop where the packet actually stops.

The Most Important Lesson From This Article

Don't memorize: "packets always go through iptables → bridge → veth." That's far too simplistic and, frankly, often wrong. Instead, memorize the general shape:

Pod namespace
     ↓
Pod interface
     ↓
Node networking
     ↓
Service dataplane (if Service traffic)
     ↓
routing / NAT / policy / kernel dataplane
     ↓
destination network
Enter fullscreen mode Exit fullscreen mode

Then always ask: "Which implementation is my cluster actually using?" That single question determines the real, concrete path your packets take.

What's Next: Production Troubleshooting

In Level 10, we stop learning isolated components and start diagnosing real failures: a Pod that can't reach another Pod, a Pod that can't reach a Service, a Service with no endpoints, DNS that works while curl still fails, an Ingress returning 502/504, a NetworkPolicy that accidentally broke DNS, traffic that only fails across Nodes, a single misbehaving Node, intermittent connection failures, conntrack exhaustion, MTU problems, and outright CNI failures. That's where this entire 0-to-9 journey turns into a genuinely practical troubleshooting methodology.


Conclusion

Kubernetes networking internals aren't actually magic — they're Linux networking primitives (namespaces, veth pairs, routing tables, Netfilter, conntrack) orchestrated by a CNI and a Service dataplane. The single biggest shift in this article is moving from "Pod talks to Pod" as an abstraction to actually tracing a packet through real kernel mechanisms: crossing a veth pair, hitting a routing decision, potentially getting DNAT'd by a Service dataplane, and having its connection state tracked by conntrack the entire way.

The most valuable habit from this entire article: when something breaks, don't guess at commands — ask "at which hop did the packet actually stop?" and use the Pod-IP-vs-Service-IP test to instantly narrow down whether you're dealing with a CNI-layer problem or a Service-layer problem.

Enjoyed this deep dive? Follow along for Level 10, where we turn this entire series into a hands-on production troubleshooting methodology. Drop your questions in the comments, and share this with a teammate who's still treating Kubernetes networking as an unexplainable black box. Let's finish building this Kubernetes networking roadmap together. 🚀

Top comments (0)