Prerequisites: kubernetes
iptables is the long-standing system Linux uses to filter and rewrite packets from lists of rules held in the kernel. It is not a Kubernetes thing; it predates it by years. It matters here because it is the mechanism a clusterip traditionally works by. The rules are organised into chains, and the kernel walks the relevant chain for each packet.
The specific trick a ClusterIP relies on is DNAT, destination network address translation: taking a packet addressed to a virtual ClusterIP and rewriting its destination to a real pod address before it is forwarded. You can see real DNAT rules in a throwaway kube-proxy cluster. A kind node is just a Docker container, so you can read the rules directly:
docker exec kproxy-control-plane iptables-save -t nat | grep <a Service ClusterIP>You will see chains named KUBE-SERVICES, KUBE-SVC-..., and KUBE-SEP-..., ending in a rule that DNATs the Service’s ClusterIP to a backend pod. Every Service in the cluster adds more of these rules, and that growing pile is the scaling problem that motivated the ebpf replacements. If your kind runs kube-proxy in nftables mode the same rules appear via nft list table ip kube-proxy: the newer format, the identical idea.
Reference: netfilter/iptables, virtual IPs and Service proxies.