Kubernetes ClusterIP Service Behavior
Kubernetes ClusterIP Services expose applications internally via a static IP, enabling secure and stable communication within a cluster.
Kubernetes ClusterIP Service Behavior refers to the precise mechanics of how a ClusterIP-type Service allocates its virtual IP, routes traffic to backing pods, and interacts with the cluster's networking layer, distinguishing it from the higher-level configuration concerns of when and why to choose the type in the first place. Understanding this behavior at the packet and control-plane level is necessary to diagnose routing failures that a purely declarative view of the Service object cannot explain.
Virtual IP Allocation
Allocation From a Reserved Range
A ClusterIP is allocated from a reserved address range configured at cluster creation, distinct from the pod network range, meaning ClusterIPs are not routable addresses in the traditional sense — no single network interface owns them — but are instead virtual addresses recognized and intercepted by every node's networking component.
kubectl get service ledger-api -o jsonpath='{.spec.clusterIP}'
Stability Across Pod Churn
The ClusterIP remains fixed for the lifetime of the Service object regardless of how many times backing pods are created, rescheduled, or replaced, which is the core behavior that makes ClusterIP suitable as a stable internal endpoint: consumers bind to the Service's address once and never need to react to pod-level churn.
Traffic Interception and Routing
kube-proxy's Role
Traffic destined for a ClusterIP is intercepted and redirected by kube-proxy, a component running on every node, which programs the node's packet filtering rules to rewrite ClusterIP destination addresses into one of the Service's actual backing pod addresses. This interception happens below the application layer, entirely transparent to both the client and the receiving pod.
iptables Mode
In iptables mode, kube-proxy installs a chain of NAT rules per Service, each backing pod represented by a rule with an associated random-selection probability, so that traffic is distributed approximately evenly across available endpoints purely through iptables' native probabilistic matching, without kube-proxy participating in each individual connection.
iptables -t nat -L KUBE-SVC-LEDGERAPI -n
IPVS Mode
In IPVS mode, kube-proxy instead programs the Linux kernel's IP Virtual Server subsystem, which maintains a proper load-balancing table supporting multiple scheduling algorithms (round-robin, least connection, and others), offering better performance at high Service and endpoint counts than the linear iptables rule chains.
ipvsadm -L -n -t <clusterIP>:80
Endpoint Membership Behavior
Continuous Reconciliation
The set of pods backing a ClusterIP Service is not static; the endpoint controller continuously watches for pods matching the Service's selector and updates the corresponding EndpointSlice as pods become ready, fail their readiness probe, or are deleted, and kube-proxy on every node reacts to these updates by reprogramming its local routing rules accordingly.
Readiness Gating
Only pods currently passing their readiness probe are included as active endpoints; a pod that is running but not yet ready, or that has become unready due to a failing dependency, is excluded from ClusterIP routing until it passes the probe again, which is the mechanism that prevents traffic from being sent to a pod not yet prepared to serve it.
readinessProbe:
httpGet:
path: /healthz
port: 8080
periodSeconds: 5
Session and Load Distribution Behavior
Default Per-Connection Distribution
With sessionAffinity: None, the default, each new connection to the ClusterIP is independently load-balanced, meaning two separate connections from the same client pod may land on two different backing pods, which is the expected behavior for stateless workloads.
ClientIP Affinity Behavior
When sessionAffinity: ClientIP is configured, kube-proxy tracks the source IP of incoming connections and pins subsequent connections from the same source to the same backing pod for the configured timeout, implemented as an additional layer of rule matching ahead of the standard load-balancing rules.
Behavior Under Failure Conditions
All Endpoints Unready
If every backing pod simultaneously fails its readiness probe, the Service's EndpointSlice becomes empty, and kube-proxy has no valid destination rule to route traffic to, causing connections to the ClusterIP to fail immediately rather than queue or retry, since routing failure at this layer is not distinguished from routing to a healthy-but-overloaded pod.
DNS Caching Interaction
Because the ClusterIP itself remains stable even as endpoints churn, DNS caching of the Service name has no bearing on endpoint freshness — a stale DNS cache still resolves to the correct, unchanged ClusterIP, and the actual routing to fresh endpoints happens entirely at the kube-proxy layer beneath DNS.