What Kubernetes Actually Specifies
A colleague says Kubernetes handles the networking. It does not. It states four requirements and hands the entire implementation to something you installed separately, and almost every confusing thing about Kubernetes networking traces back to that handoff.
Here is a question worth sitting with before we start. Your pods can reach each other across nodes. Which component makes that work?
If the answer that comes to mind is "Kubernetes," this lesson is the most useful twenty five minutes in the course, because the answer is that Kubernetes has no idea. It never sent a packet. It stated a requirement and something else satisfied it, and until you know which something, you will keep reading the wrong documentation.
What is actually happening
The Kubernetes network model is four requirements. Not a protocol, not an implementation, not a set of components. Four statements about what must be true, with no instruction whatsoever about how.
Every pod gets its own IP address. Not a shared address with port mapping, not an address borrowed from the node. Its own, from a range the cluster controls.
Pods can communicate with all other pods without NAT. A pod on one node reaches a pod on another node directly, and the destination sees the real source address.
Nodes can communicate with all pods without NAT, and pods can reach nodes the same way. This is what lets the kubelet reach a pod to run a health probe.
The IP a pod sees itself as is the IP others see it as. Run hostname -i inside the pod and the answer is the address the rest of the cluster uses to reach it.
That is the whole model. Read it again and notice what is absent: nothing about how addresses are allocated, nothing about how packets cross a node boundary, nothing about encryption, nothing about policy, nothing about performance, nothing about what happens when you run out of addresses.
The fourth requirement is the one people skim, and it is doing the most work. "The IP a pod sees itself as is the IP others see" is what makes the whole model usable, because it means an application can advertise its own address to a peer and that address will work. It is also the requirement that rules out the entire class of solutions that would otherwise be easiest: port mapping, address translation between pods, anything where a pod's identity depends on where you are standing when you look at it.
The reason these are phrased as requirements rather than as a design is deliberate. Kubernetes runs on cloud VPCs, on bare metal with real routers, on a laptop, and inside another Kubernetes cluster. No single networking implementation is correct across all of those. So the project specified the contract and left the implementation open.
That decision is why Kubernetes networking is portable. It is also why it is confusing.
The Kubernetes model versus the CNI's choice
Everything not in those four requirements is delegated to the Container Network Interface plugin, which you install separately and which most teams inherit from whatever their cluster provisioner chose.
The split looks like this:
| Kubernetes requires | Your CNI decides |
|---|---|
| Every pod has an IP | Which address, from which range, allocated how |
| Pods reach pods without NAT | Whether that happens by encapsulation or native routing |
| Nodes reach pods without NAT | What the host side of the pod interface attaches to |
| A pod's address is consistent | Everything about performance and MTU |
| Whether NetworkPolicy is enforced at all | |
| What you can observe, and how | |
| Encryption between nodes, if any |
Look at the right hand column. Address exhaustion, MTU failures, policy that silently does nothing, traffic you cannot see: those are the problems you will actually have, and none of them are Kubernetes problems. They belong to a component the Kubernetes documentation does not describe.
How it works in practice
The practical skill is a habit: before investigating anything, decide which side of the line it is on. That decision tells you which documentation to open, which is usually the difference between an hour and an afternoon.
Start by finding out what your cluster actually runs, because a surprising number of engineers do not know:
# What is providing the network? Look for the CNI's own workloads.
kubectl get daemonset -n kube-system
NAME DESIRED CURRENT READY AGE
kube-proxy 6 6 6 284d
<your-cni-agent> 6 6 6 284d
Then look at what it decided about addresses:
# The per-node pod range, assigned by the control plane or by the CNI
kubectl get nodes -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.podCIDR}{"\n"}{end}'
node-01 10.244.0.0/24
node-02 10.244.1.0/24
node-03 10.244.2.0/24
And how packets actually get between those ranges, which you can only see from a node:
# On a node. The answer here is entirely your CNI's choice.
ip route | grep 10.244
10.244.1.0/24 via 10.0.1.12 dev eth0 # native routing, next hop is another node
10.244.2.0/24 dev <tunnel-interface> # or an overlay, via a tunnel device
Those three commands tell you more about how your cluster networks than any amount of reading about Kubernetes, because two of the three are showing you decisions Kubernetes never made.
Get in the habit of asking one question before you search for anything: is this behaviour required by the model, or chosen by the plugin? "Pods on different nodes can reach each other" is required, so if it is broken, something is violating a guarantee. "Pods on different nodes reach each other with a 1450 byte MTU" is chosen, so if that is causing trouble, the Kubernetes documentation will not mention it and the answer is in your plugin's documentation instead.
Common failure modes
Reading the wrong documentation. Someone hits an MTU problem, searches the Kubernetes documentation, finds nothing about MTU, and concludes the problem must be their application. MTU is not in the model. It was never going to be there.
Assuming portability the model does not provide. A team writes NetworkPolicy manifests, tests them on a cluster whose plugin enforces them, and ships to a cluster whose plugin does not. The manifests apply cleanly on both. On one of them they do nothing at all, silently, because the API is Kubernetes and the enforcement is not.
Expecting the model to explain a performance difference. Two clusters, same version, same manifests, measurably different throughput. Nothing in the model addresses throughput, so nothing in the model can explain the difference. The explanation is on the other side of the line.
Debugging a plugin problem as a Kubernetes problem. This is the expensive one, because it sends you down a path where every answer you find is about the wrong system, and each answer looks plausible enough to try.
A team spent two days on pods that could not reach a service in another namespace. They read the Service documentation, the DNS documentation, and the NetworkPolicy documentation. They checked selectors, endpoints, and resolution, repeatedly, and all of it was correct. The cluster had been provisioned with a plugin configured for a smaller address range than the cluster had grown into, and one node's pod range overlapped with a range used elsewhere in the network. Packets were leaving and being routed somewhere unintended. Nothing in the Kubernetes documentation would ever have described this, because address allocation is not something Kubernetes does. The first question that would have helped was not about Services. It was "which component assigns pod addresses here, and what did it assign?"
What people get wrong
"Kubernetes handles the networking." It states four requirements. Something you installed satisfies them. The sentence is not slightly imprecise, it is pointing at the wrong component entirely.
Treating the model as a floor and a ceiling. The four requirements are a floor. Plugins routinely provide much more: policy, encryption, observability, load balancing, multi-cluster reachability. None of that is guaranteed anywhere, so a manifest that depends on it is not portable even though it is valid Kubernetes YAML.
Believing all clusters network alike because they all pass the same conformance. Conformance tests the four requirements. Two conforming clusters can differ in every way that will actually affect you.
Skipping the fourth requirement. People remember "every pod gets an IP" and forget "and the pod agrees about what it is." The second half is what makes peer to peer protocols, service registration, and anything where a workload advertises its own address work at all.
Two clusters run the same Kubernetes version and the same manifests. Pod to pod throughput across nodes is measurably lower in one of them, and large payloads occasionally fail there. Where should you look first?
The one habit to take from this lesson: when something about networking surprises you, decide which side of the line it is on before you do anything else. Four requirements are Kubernetes. Everything else, including almost everything that will page you, belongs to a component the Kubernetes documentation does not describe.
What does the Kubernetes network model actually require, and what does it leave entirely to the CNI? Give an example of behaviour engineers commonly attribute to Kubernetes that is really their CNI's choice.