Kubernetes requires every pod to have its own IP address on a flat network. What exactly does that model require, and how do containers inside a single pod reach each other?
answer
- IP per pod, no NAT, any node
- pause sandbox holds the netns
- containers share localhost + port space
- veth pair into node namespace
- pod IP is ephemeral — Services exist for that
basics
~20 sEvery pod gets its own IP. Any pod can reach any other pod's IP directly, on any node, with no NAT. Containers inside one pod share a single network namespace, so they talk over localhost and share one port space.
solid answer
~50 sKubernetes ships no pod networking itself; it defines a contract a plugin must satisfy. The contract: each pod gets a unique IP from a cluster-wide range; every pod can reach every other pod's IP on any node **without NAT**; a pod sees its own address as the same one others use to reach it; node agents can reach pods on their node. The pod, not the container, is the network unit. The runtime creates a sandbox (the `pause` container) that holds the network namespace, and every app container joins it. So containers in one pod share the IP, loopback and port space — they talk over `127.0.0.1`, and two of them cannot both bind `:8080`. Pod IPs are ephemeral: a rescheduled pod gets a new one, which is exactly why Services exist. `hostNetwork: true` opts a pod out — it uses the node's namespace and IP.
code
bash · 6 lineskubectl get pods -o wide
# NAME READY STATUS IP NODE
# api-0 1/1 Running 10.244.2.17 node-b
kubectl run probe --rm -it --image=nicolaka/netshoot --restart=Never -- \
curl -s http://10.244.2.17:8080/healthzgo deeper
State the four rules plainly and demonstrate the shared-namespace point: sidecars reach the app on localhost, and two containers cannot bind the same port.
Add the mechanism — sandbox/pause container, veth pair, per-node IPAM slice of the cluster CIDR — and explain why no-NAT matters for peer-to-peer and identity.
Tie the model to failure signatures you have debugged (same-node works, cross-node fails) and to what the model deliberately does not give you: isolation, encryption, IP stability.
Frame it as an interface decision: Kubernetes chose a minimal contract so the datapath could be swapped, which is why plugin choice becomes an address-space, performance and upgrade decision rather than an application one.
## What the model requires Kubernetes implements no pod networking of its own. It specifies a contract and requires whichever plugin you install to satisfy it. Four clauses: 1. Every pod gets its own IP address from a cluster-wide address space. 2. Every pod can reach every other pod's IP directly, on any node, **without network address translation (NAT)** — no rewriting of source or destination addresses along the path. 3. Agents on a node (kubelet, node daemons) can reach all pods on that node. 4. A pod sees its own IP as the same address other pods use to reach it. This is often called the "IP-per-pod flat network" model. "Flat" means one address space with no translation boundaries inside it, not that everything is on one L2 segment. ## Why no-NAT matters Contrast the classic single-host container setup, where containers share the host IP and are exposed by port mapping with source NAT. That forces a distributed port-allocation problem, breaks any protocol that carries addresses in the payload, and makes a service register itself under an address it cannot see. Under the Kubernetes model a pod is addressable exactly like a small VM: it binds whatever port it likes, tells peers the IP it sees on its own interface, and that address works cluster-wide. Peer-to-peer systems (Cassandra, Kafka, etcd), gossip protocols and mTLS identity all depend on this. ## The pod as a network unit — the sandbox When the kubelet asks the container runtime to start a pod, the runtime first creates a **sandbox**: a container whose only job is to hold the pod's namespaces alive. Historically this is the `pause` container. The network plugin is invoked once, against the sandbox's network namespace. Every application container in the pod is then started joined to that same namespace. Consequences you must be able to state: - All containers in a pod share one IP and one loopback interface — a sidecar can reach the app on `localhost:8080`. - They share one port space; two containers binding the same port is a startup crash, not an isolation boundary. - They see the same routing table and the same `/etc/resolv.conf`. - Because the plugin runs once for the sandbox, adding a sidecar costs no extra IP. This is precisely what makes the sidecar pattern (proxies, log shippers, adapters) work without any networking configuration. ## How a packet actually leaves The plugin typically creates a **veth pair**: one end becomes `eth0` inside the pod namespace, the other lands in the node's root namespace, attached to a bridge or addressed directly by a host route. The node then forwards to the destination node — either by wrapping the packet (encapsulation) or by a plain route the underlay knows about. Address assignment (IPAM) is usually per node: each node holds a slice of the cluster CIDR and hands out IPs from it, which keeps routing summarisable. ## What the model does not promise - **Not isolation.** Flat means every pod can reach every pod by default. Restricting that requires policy objects and a plugin that enforces them. - **Not encryption.** Pod-to-pod traffic is plaintext unless the plugin or a mesh adds it. - **Not stability.** A pod IP dies with the pod. Never store it, never configure a client with it. Services and DNS exist to give a stable name. - **Service ClusterIPs are not pod IPs.** They are virtual addresses that never live on an interface; they are translated to a pod IP before delivery. - **`hostNetwork: true` is the escape hatch.** The pod runs in the node's network namespace, uses the node IP, and competes for the node's ports. It is used for node-level agents and breaks the model deliberately. ## Recognising it in practice `kubectl get pods -o wide` shows the pod IP and node. From a debug pod, `curl <podIP>:<port>` should work regardless of which nodes the two pods sit on. The classic failure signature is *same-node traffic works, cross-node traffic hangs* — that points at the node-to-node part of the datapath (encapsulation or routing), not at the application.
- If pods get real routable IPs, why do Services exist at all?Because pod IPs are ephemeral and plural. A pod that is rescheduled, scaled or rolled gets a new IP, so no client can hold one. A Service gives a stable virtual IP and DNS name in front of the current set of ready pod IPs, and spreads traffic across them. The flat network is what makes the Service's translation to a pod IP work from any node.
- What changes for a pod that sets hostNetwork: true?It skips the pod network entirely and runs in the node's network namespace, so it has the node's IP and sees the node's interfaces. Any port it binds is a port on the node, which means real conflicts with other host processes and other such pods. It is appropriate for node-level agents like CNI daemons or metrics collectors, and it also changes DNS behaviour unless dnsPolicy is set to ClusterFirstWithHostNet.
A pod is a small VM with one NIC. The containers inside are processes on that VM: same IP, same localhost, same port space — and if two processes want port 8080, one of them loses.
saying these in an interview costs you the question
- Saying containers in a pod each get their own IP and talk to each other over the pod network
- Believing pod IPs are stable enough to configure clients or store in a database
- Claiming Kubernetes itself implements pod networking, with no mention of a plugin
- Assuming the flat network means pods are isolated by default — it means the opposite
- Confusing a Service ClusterIP with a pod IP, or thinking traffic to a pod IP is load balanced