Have you ever wondered what routing protocol Kubernetes actually uses to move traffic around?
If you come from a networking background, this one probably itches at you. You know OSPF, BGP, static routes, iptables — but in Kubernetes, pods just… talk to each other. Nobody SSHes in to configure a routing table. Nobody (seemingly) runs a routing protocol. It just works. And “it just works” is exactly the kind of thing that keeps a network engineer up at night.
And if you don’t come from a networking background? You’ve probably never had to think about it. You deploy your app, the pods come up, traffic flows, and life is good. Honestly, that’s fine — if all you want is to ship an app into a pod and keep it running, you can stop reading here and nothing bad will happen.
But if you’re the kind of person who can’t move forward without understanding what’s underneath — if “it just works” isn’t a good enough answer for you — then this one’s for you. Because networking is such a foundational part of the DevOps journey that, sooner or later, you simply can’t skip it. A broken DNS lookup, a pod that can’t reach a service, a mysterious latency spike — the day one of these lands on your desk, “it just wrks” turns into “why doesn’t it work,” and suddenly the basics aren’t optional anymore.
So this blog is a look under the hood at how Kubernetes networking actually moves your packets from one pod to the next — smoothly enough that most of us never stop to ask what’s carrying them. We’ll start with plain old networking — the stuff network engineers already know and the stuff everyone else has been quietly relying on — and build our way up to Cilium and eBPF, the tech that’s rewriting how Kubernetes moves traffic.
Let’s start by getting the basics straight: how routing worked in traditional network design, long before Kubernetes came along
Part 1: How networking worked before Kubernetes
Before we can understand the clever stuff, we need the basics. Don’t worry — we’ll keep it simple.
Every machine has an address (IP)
Every computer on a network has an IP address. Think of it like a home address. If one computer wants to send data to another, it needs to know the other one’s address.
Data doesn’t travel as one big chunk. It’s broken into small pieces called packets. Each packet is like a single envelope with a “from” address and a “to” address written on it.
The address underneath: MAC
Here’s a piece people often miss. An IP address can change — it’s assigned, and it can be reassigned. But every network card also has a second, more permanent address burned into the hardware: the MAC address. Think of the IP address as the name written on a package, and the MAC address as the actual physical mailbox the package gets dropped into.
Why do we need two? Because IP addresses are how machines find each other across the whole network, but the final hand-off — actually dropping the data into the right machine sitting next to you — happens using the MAC address.
Finding your neighbor: ARP
So imagine Machine A knows Machine B’s IP address and they’re on the same local network. A still needs B’s MAC address to actually deliver the data. How does it get it?
It shouts. A sends out a message to everyone on the local network asking: “Who has this IP address? Tell me your MAC.” This shout-to-the-room is called ARP (Address Resolution Protocol). The machine that owns that IP answers back with its MAC, and now A can deliver the data. A even remembers the answer for a while so it doesn’t have to ask again.
Keep ARP in mind — when two pods on the same machine talk, this exact “who has this IP?” shout is happening quietly underneath. We’ll see it in the animation.
Kubernetes networking · concept: ARP
ARP: how a machine finds its neighbor
—
Switches vs routers
Two devices do the heavy lifting of moving data, and they work at different levels:
- A switch connects machines on the same local network. It works with MAC addresses. Think of it as the wiring inside one building — it just needs to know which mailbox is which.
- A router connects different networks together. It works with IP addresses. Think of it as the post office that moves mail between different cities.
Networking people call these “Layer 2” (switches, MAC) and “Layer 3” (routers, IP). You don’t need the jargon — just remember: switch = local, router = between networks.
How a packet finds its way across networks
Sending a letter across cities, you drop it in a mailbox and the postal system figures out the route, passing it office to office until it arrives. Networks do the same, and the “post offices” are the routers.
Each router keeps a routing table — a list of directions that says “if a packet is going there, send it this way.” A packet hops from router to router, each one reading the address and pushing it one step closer, until it reaches the right machine.
Who fills in all those directions?
Here’s the question that matters for our whole story: who writes the routing tables?
For a tiny network, a human can type the directions in by hand — these are static routes. But real networks are huge and always changing, so instead, routers talk to each other and share directions automatically, using routing protocols like OSPF and BGP.
To know more about these routing protocol check below animation –
Networking basics · routing protocols
How routers learn the way: OSPF vs BGP
The two most famous routing protocols — and they solve the problem very differently.
—
Picture routing protocols as routers gossiping: “Hey, I can reach this network, pass it along.” Over time, every router learns how to reach everywhere. This gossip is why the internet keeps working without anyone updating it by hand. Remember this — it comes back in a big way later.
One more thing: NAT
Sometimes a machine’s real address gets swapped for a different one as a packet passes through — for example, when many devices in your home share one public internet address. This swapping is called NAT (Network Address Translation). It’s useful, but it also hides who’s really talking to whom. Hold on to this word — Kubernetes makes a very specific promise about NAT that we’re about to see.
And rules on the machine itself
Once a packet reaches a machine, that machine can have its own rules about what to allow, block, or change. On Linux, these are handled by iptables. Keep that word in your pocket — it’s going to come back and cause us trouble later.
So the classic picture is: IP and MAC addresses, ARP to find neighbors, switches and routers, routing tables, protocols like OSPF and BGP, NAT, and iptables rules on each machine. For decades, this is how everything talked to everything — and all of it lived on physical boxes you configured by hand.
That last part is about to change completely.
Part 2: SDN — when the network became software
Everything in Part 1 traditionally lived in hardware. If you wanted a new network, you ran cables. If you wanted a new route, you logged into a physical router and typed it in. The network was a physical thing you touched.
Then came a huge shift: Software-Defined Networking (SDN).
The idea is simple but powerful: what if the network wasn’t physical boxes, but software? What if switches, routers, and cables could be virtual — created, changed, and destroyed by a program in seconds, instead of a person with a screwdriver?
That’s SDN. The network becomes software you can command. You can spin up a virtual switch, connect virtual machines to it, apply rules, and tear it all down — all in code, no hardware touched.
And this is the single most important idea behind everything that follows. Kubernetes networking is SDN. When a pod gets its own address, when a virtual switch appears inside a machine, when traffic gets routed between pods automatically — that’s all software building and running a network on the fly. Nobody plugs in a cable. Nobody configures a physical router.
This is exactly why your opening feeling was right: it does feel like magic. It’s because the entire network turned into software that quietly builds and rebuilds itself, without you ever seeing it. Now let’s see what that software actually promises to do.
Part 3: The one promise Kubernetes makes
Here’s the surprising part. Kubernetes does not force you to use any specific routing protocol. It doesn’t say “you must use BGP” or “you must use OSPF.” Instead, it only makes a few simple promises about how the network must behave, and then lets someone else figure out how to keep those promises.
The main promises are:
- Every pod gets its own IP address. (A pod is just the small box your app runs inside.)
- Every pod can talk to every other pod directly — even pods on different machines — without NAT. Remember NAT, the address-swapping from Part 1? Kubernetes promises it won’t happen between pods. A pod sees the real address of the pod it’s talking to, not a swapped-out fake one.
- Every machine can reach every pod too.
Put simply: Kubernetes gives you the feeling of one big, flat network where everyone can reach everyone honestly, as if they were all plugged into the same giant switch — no matter which machine they’re actually on.
But that’s only a promise about behavior. Kubernetes doesn’t do the actual work itself. It hands that job to a helper called a CNI plugin (“Container Network Interface” — a fancy name for “the thing that wires up pod networking”). Different CNI plugins keep the promise in different ways. Cilium, which we’ll meet later, is one of them.
So when someone asks “what routing protocol does Kubernetes use?”, the honest answer is: Kubernetes itself doesn’t pick one — the CNI plugin does. That’s the reveal our whole blog is building toward.
Part 4: A quick word to avoid confusion
Before we go deeper, let’s clear up one word that trips everybody up: namespace.
In Kubernetes, a “namespace” is just a folder for organizing your stuff — a way to group apps so they don’t get mixed up. That’s it.
But Linux has its own thing also called a network namespace, and it means something totally different. A Linux network namespace is like giving a pod its own private networking world — its own address, its own routing table, its own view of the network, walled off from everyone else. It’s how each pod gets to feel like its own little computer.
These two “namespaces” have nothing to do with each other. Same word, different meaning. When we talk about the networking magic below, we mean the Linux kind.
Part 5: How a packet actually moves inside a machine
Okay, let’s open the box and see the real plumbing. (The animation for this section shows every step moving — read this, then watch it.)
The pipe between the pod and the machine
Each pod lives in its own little private networking world (its own Linux network namespace). But it still needs a way to reach the outside. So Kubernetes builds a virtual cable between the pod and the machine it lives on.
This virtual cable is called a veth pair. Picture a pipe with two open ends: one end sits inside the pod, and the other end sits on the machine. Whatever goes in one end comes out the other — like a tin-can telephone connecting the pod to its host. This is pure SDN: a “cable” made entirely of software.
The virtual switch
A single machine usually runs many pods. So how do they all talk to each other?
The machine creates a virtual switch (often a bridge named cni0). Think of it like a power strip: every pod plugs the outside end of its pipe into this switch. Once they’re all on the same switch, any pod can reach any other pod on that machine — using ARP to find each other, exactly like real machines on a real switch.
So for two pods on the same machine, the trip is short: pod → veth pipe → virtual switch → veth pipe → other pod. Nice and simple.
Kubernetes networking · packet walk 1 of 3
Same node: pod A → pod B on one machine
—
But what about a pod on a different machine?
This is the hard part, and it’s the heart of our original question. When a pod wants to reach a pod on another machine, the packet has to leave the machine entirely and travel across the real network — the physical cables and routers.
And here’s the problem: the real network out there has never heard of your pod addresses. Those pod addresses only make sense inside Kubernetes. To the physical routers, they look like nonsense.
So how do we get a pod’s packet across a network that doesn’t know pod addresses exist? Two main answers — coming up next. (This is the second animation.)
Part 6: Two ways to cross between machines
This is where we finally answer the question from the very start of the blog.
Way 1: Wrap the packet (Overlay)
The first trick is to hide the pod packet inside another packet.
Imagine you want to mail a letter, but the address on it isn’t one the postal system recognizes. So you put your whole letter inside a bigger envelope, and on that bigger envelope you write an address the postal system does understand — the destination machine’s real address. The postal system happily delivers the big envelope. When it arrives, the other machine opens it up and finds your original letter inside.
This “envelope inside an envelope” trick is called an overlay, and the wrapping is called encapsulation. Common names are VXLAN and IP-in-IP. The big advantage: the real network never has to learn anything about pod addresses. It just delivers machine-to-machine envelopes, and the pods hide inside. The small cost: wrapping and unwrapping every packet takes a little extra work.
Kubernetes networking · packet walk 2 of 2
Different nodes: pod A → pod B across the network
—
Way 2: Just tell the real routers (Native routing + BGP)
The second trick is more direct: instead of hiding pod addresses, we teach the real network about them.
Remember routing protocols from Part 1 — routers gossiping to share directions? We use that here. The Kubernetes machines speak BGP to your real routers and announce: “These pod addresses live over here on me — send their traffic to me.” Now the real routers know how to reach pods directly, no envelopes needed.
And there it is — the routing protocol we’ve been hunting since the first line of this blog. It was BGP all along — but only if your CNI plugin chooses to use it. A network engineer feels right at home here, because it’s the same BGP they already know.
So, to finally answer the opening question: Kubernetes doesn’t run one fixed routing protocol. Depending on the CNI plugin, your pod traffic might be riding inside VXLAN envelopes, or announced with BGP like any normal route.
Kubernetes networking · packet walk 3 of 3
Different nodes, no envelope: native routing with BGP
—
Part 7: Services and kube-proxy — the part that surprises people
We’re almost at Cilium. One more piece — and it’s the one that causes the pain Cilium fixes.
Why we need Services
Pods are not permanent. They die and get replaced constantly, and each new pod gets a brand-new IP address. So if your app talked to another app using its pod address, it would break all the time — the address keeps changing underneath it.
To fix this, Kubernetes gives you a Service: a stable front door. One fixed address and name that always points to whatever pods are currently alive behind it. Pods come and go; the Service address stays put. Your app just talks to the Service.
Flavors:
- ClusterIP — a front door that only works inside the cluster.
- NodePort — opens a specific port on every machine so outside traffic can get in.
- LoadBalancer — asks your cloud provider for a real public address so the world can reach it.
The thing that makes Services work: kube-proxy
But a Service address is fake — a stand-in. Something has to catch traffic aimed at that fake address and forward it to a real, living pod. That something is kube-proxy.
On every machine, kube-proxy writes rules that say “traffic for this Service should actually go to one of these real pods.” And what does it use to write them? Our old friend from Part 1: iptables.
Here’s the catch. Every Service, and every pod behind it, adds more rules to the list. The machine reads this list top to bottom for every single packet. A few Services? No problem. Thousands of Services in a big cluster? The list becomes enormous, and reading it over and over starts to slow everything down. It still works — but you can feel it straining.
And that strain — that giant, ever-growing list of iptables rules — is exactly the problem our next section is about..
Enter eBPF and Cilium — the payoff
Let’s quickly remember the story so far.
We started with normal networking — the stuff like IP addresses, routing tables, and how one machine finds another. Then we saw how Kubernetes builds all of that again, but in software. And we met kube-proxy, the part that makes Services work by writing a big list of rules (called iptables rules) inside the machine.
That big list is exactly where the trouble starts.
Think of iptables rules like a long line of “if this, then that” instructions. The computer reads them one by one, from top to bottom, for every packet. If you only have a few Services, the line is short and nobody notices. But if you have thousands of Services, the line becomes huge. Now the computer has to walk a giant list again and again, and everything slows down. It still works — but you can feel it struggling.
And that’s just the Services. A real cluster needs a lot more:
- Ingress to let outside traffic come in
- A load balancer to spread traffic across pods
- Network policy to decide who is allowed to talk to whom
- A service mesh for things like encryption and retries — which usually adds a sidecar (a helper container) next to every single pod
- Multi-cluster networking if you grow really big
Each one is a separate tool. A separate thing to set up. A separate thing to break at 2 a.m.
There’s a Cilium picture that shows this whole mess perfectly. Take a look:

On the left, you see a crumbling pile of dirt with a shovel stuck in it. Each layer is a networking tool — network policy, multi-cluster, load balancer, ingress, kube-proxy, service mesh, sidecar — all stacked on top of your poor little application at the very bottom. A small voice asks, “Where is my app?” That’s the joke: your actual app is buried under a giant tower of networking tools, each one added to fix the one below it.
On the right, there’s a clean green field, a happy bee, and just two layers: Cilium sitting directly on your application. The bee says “come to the eBPF side.” It’s a Star Wars joke, but the real message is: you can throw away that whole messy tower and replace it with one thing built on eBPF.
Quick honesty check: this is a picture made by Cilium’s own team, so of course they make the left side look terrible. Those older tools actually work fine for many people. But the main idea is true and worth understanding. To get why, you first need to know what eBPF is.
So what is eBPF?
Let me explain it in the simplest way.
Normally, the Linux kernel (the core part of the operating system that handles things like networking) does its job in a fixed way. If you wanted to change how it handles packets, you had two bad choices: rebuild the whole kernel (way too hard), or send every packet through a separate helper program running outside the kernel (too slow).
eBPF is a third, better way. It lets you load tiny, safe mini-programs directly into the kernel and tell them “run right here, the moment a packet arrives.” The kernel first checks that your mini-program can’t crash or get stuck, then runs it super fast, right inside itself.
So instead of changing the kernel or going around it, you’re teaching the kernel new tricks on the spot — safely and quickly.
What Cilium does with it
Cilium is Kubernetes networking built completely on top of eBPF, from scratch. Here are its best moves, in plain terms:
It replaces kube-proxy. Remember that giant list of rules the computer had to read one by one? Cilium gets rid of it. Instead, it uses a fast lookup (like instantly finding a word in a dictionary instead of reading the whole book). It stays fast whether you have 10 Services or 10,000.
It protects traffic by identity, not by IP address. In Kubernetes, pods get new IP addresses all the time, so rules based on IPs are hard to keep correct. Cilium gives each app a steady identity instead, and makes rules like “this app may talk to that app.” Much easier to understand and manage.
It can use real routing and BGP. For readers who wanted an actual routing protocol this whole time — here it is. Cilium can tell your real network routers about your pods using BGP, so pod traffic travels on your normal network like any other traffic.
It lets you see everything, using Hubble. Because Cilium already sits right where the packets flow, it can watch every connection and every blocked packet, and Hubble turns that into a live picture of what is talking to what. Anyone who has tried to figure this out the hard way will love this.
Architecture · Cilium on Kubernetes
How Cilium plugs into Kubernetes — and clears the clutter
Kubernetes declares what the network should do. Cilium makes it happen in the Linux kernel with eBPF — folding kube-proxy, per-pod sidecars, and sprawling iptables rules into one fast datapath.
Kubernetes control plane
Worker nodes
policy → eBPF · identities · health
policy → eBPF · identities · health
✕ The old tower of tools
✓ One eBPF datapath
Read top-to-bottom: Kubernetes declares intent → Cilium Operator + Agents translate it → the eBPF datapath in each kernel actually moves and secures the packets.
The same packet, two worlds
Imagine one pod trying to reach a Service.
The old way: the packet leaves the pod, reaches the machine, walks that long list of rules to find a backend, maybe takes a detour through a sidecar helper and back, and finally goes out. Lots of stops along the way, and the list keeps growing as your cluster grows.
The Cilium way: the packet leaves the pod, and a tiny eBPF program inside the kernel instantly finds the right backend and sends it — often skipping the rule list and the sidecar detour completely.
Same destination. Much less stuff in the middle.
That’s why the bee looks so happy.