← all cheat sheets
FUNDAMENTALS · MECHANISM WALKTHROUGH

Kubernetes Service to Pod
What Really Happens, Step by Step

a Service's ClusterIP isn't a real, listening address — here's the kube-proxy/iptables mechanism that makes it work anyway.
CLIENT REQUEST ClusterIP (VIRTUAL) KUBE-PROXY RULES DNAT TO POD IP POD RECEIVES RESPONSE
01 The Full Sequence — Worked Example
1

A Client Pod Resolves the Service Name

A Pod calls http://payments-svc. Cluster DNS (CoreDNS) resolves this to the Service's ClusterIP — a stable virtual IP allocated when the Service was created.

DNS
2

The ClusterIP Is Not a Real, Listening Address

No process anywhere is actually bound to the ClusterIP — no network interface owns it. It exists purely as an entry in packet-filtering rules on every node. This is the single most important fact about how Services work.

Virtual IP
3

The Endpoints Controller Maintains the Real Pod List

Independently, the Endpoints controller continuously watches which Pods match the Service's label selector and are currently Ready, and maintains an EndpointSlice — the up-to-date list of actual Pod IP:port pairs backing this Service.

Endpoints
4

Checkpoint — kube-proxy Programs the Rules

On every node, kube-proxy watches Services and EndpointSlices, and continuously writes local packet-filtering rules (iptables or IPVS) that say, in effect: "packets to ClusterIP:port → rewrite destination to one of these Pod IP:ports." This is the entire mechanism — there is no central load balancer process.

Checkpoint
5

Client Sends the Packet

The calling Pod sends a packet addressed to the ClusterIP. It leaves the Pod's network namespace completely normally — as far as the client's TCP/IP stack is concerned, it's just sending to a regular IP address.

Send
6

Node's Netfilter Rules Intercept It

Before the packet is routed anywhere, the Linux kernel's netfilter hooks on the node evaluate the rules kube-proxy programmed in step 4, and match this packet against the ClusterIP:port.

Intercept
7

DNAT — Destination Rewritten to a Pod IP

The rule performs DNAT (Destination Network Address Translation), rewriting the packet's destination from the virtual ClusterIP to one specific, real Pod IP — chosen essentially at random (iptables mode) or via a configured algorithm (IPVS mode, which supports real load-balancing policies).

DNAT
8

Packet Routed to the Real Pod

Now that the destination is a genuine Pod IP, normal cluster networking (the CNI plugin's routes/overlay) delivers it — potentially to a Pod on a completely different node than either the client or the packet's current location.

Route
9

Pod Receives It as a Normal Direct Connection

From the destination Pod's perspective, this looks exactly like a direct connection — it has no visibility into the ClusterIP or the DNAT rewrite that happened upstream. The application never needs to know Services exist at all.

Receive
10

Return Traffic Is Un-DNAT'd Automatically

Netfilter's connection tracking (conntrack) remembers the original DNAT, so the response packet gets its source address rewritten back to the ClusterIP before reaching the client — the client never sees the real Pod IP either.

Return
02 How to Explain This in an Interview
03 Follow-Up / Gotcha Questions
Q If I ping a Service's ClusterIP, does it respond?
A No — ICMP isn't handled by the Service's DNAT rules the same way TCP/UDP traffic to the defined port is; a ClusterIP typically won't answer plain pings even though it accepts traffic on its configured Service port.
Q A Service has healthy-looking Pods but Endpoints is empty — why?
A Almost always a label selector mismatch between the Service and the Pods, or the Pods are Running but not yet Ready (failing their readiness probe) — the Endpoints controller only includes Ready Pods.
Q Does traffic to a ClusterIP ever leave the node it originated on before DNAT happens?
A No — the DNAT rewrite happens locally, on the sending Pod's own node, before the packet is routed anywhere. The destination Pod could be local or remote, but the translation decision itself is always local.
Q What's different about a headless Service (clusterIP: None)?
A No ClusterIP is allocated at all, and DNS returns the individual Pod IPs directly instead of a single virtual address — kube-proxy's DNAT mechanism is bypassed entirely, and the client does its own load balancing (or connects to a specific Pod by name, common for StatefulSets).
Q Why does killing kube-proxy on a node break Service traffic from that node, but not cluster-wide?
A Because the DNAT rules are programmed per-node — each node's kube-proxy independently maintains its own local rule set. Other nodes' kube-proxy instances and rules are entirely unaffected.
Q Is load balancing across Pods session-aware by default?
A No — by default each new connection can land on a different Pod essentially at random (or per IPVS's algorithm). Session affinity (sessionAffinity: ClientIP) must be explicitly configured on the Service if that's required.
04 Quick-Fire Glossary
TermMeaning
ClusterIPStable virtual IP for a Service — not bound to any real interface, exists only as filter rules
kube-proxyPer-node agent that programs local packet-filtering rules implementing Service routing
EndpointSliceController-maintained list of actual, ready Pod IP:port pairs backing a Service
DNATDestination Network Address Translation — rewrites a packet's destination address
iptables modekube-proxy backend using Linux netfilter rules, roughly random Pod selection
IPVS modekube-proxy backend supporting real load-balancing algorithms (least-conn, etc.)
conntrackKernel connection tracking that lets return traffic be automatically un-translated
CoreDNSCluster DNS server resolving Service names to ClusterIPs
Headless ServiceService with clusterIP: None — DNS returns individual Pod IPs instead
sessionAffinityOptional Service setting to pin a client to the same backing Pod