A Kubernetes Service with ten healthy backend Pods can still send most of the workload to just one or two of them. This often looks like a broken load balancer, but the usual cause is simpler: the Service distributes network connections, while the application sends many requests through each connection.

Consider an HTTP client that opens one TCP connection to a Service and keeps it alive. The first connection is directed to one backend Pod. Every HTTP request subsequently carried over that connection continues to reach the same Pod. Kubernetes does not reconsider the destination for each request inside the established connection.

This distinction matters because one connection may represent very different amounts of work. A short command-line request might create a connection, receive a response, and close it. A reverse proxy, application server, or gRPC client may keep a small pool of connections open for hours and send thousands of requests through them. If such a client maintains four connections to a Service backed by twenty Pods, at most four Pods may receive its traffic at any given moment. Random backend selection cannot compensate for having so few opportunities to choose.

The exact Service data path depends on the cluster’s networking configuration. Implementations based on iptables, nftables, IPVS, or eBPF differ internally, but the important behavior is generally the same: backend selection occurs when a new flow is established. Linux connection tracking then preserves that decision so packets belonging to the flow continue toward the selected backend. Reassigning packets midway through a TCP connection would break the connection’s state.

HTTP/2 makes the imbalance more visible. Multiplexing allows many concurrent requests to share one TCP connection. gRPC commonly uses this feature, so a busy client can direct a large volume of independent calls to a single Pod despite addressing a Service with many endpoints. Adding more Pods may therefore improve capacity without immediately changing the observed traffic distribution.

The useful diagnostic is connection distribution, not merely request counts. Check how many long-lived connections clients create, which Pods terminate those connections, and whether a small number of clients generate most of the load. Kubernetes session affinity can make concentration stronger, but uneven traffic does not require it; ordinary connection reuse is sufficient.

Possible remedies belong at the layer that understands the workload. Clients can create larger connection pools or periodically recycle connections. A proxy or service mesh can perform request-aware balancing, provided it receives enough independent requests to make new routing decisions. For gRPC, client-side load balancing can maintain connections to multiple endpoints instead of sending every call through one persistent channel.

A Kubernetes Service can distribute new connections effectively and still produce highly uneven request counts. When traffic appears stuck to a Pod, the first question should be how many connections exist and how long they live.