A headless Service behaves completely differently for DNS resolution — what's different, and when do you need it?
Short Answer
A normal Service's DNS name resolves to one virtual IP (the ClusterIP), with kube-proxy handling load-balancing to backend pods behind that single address. A headless Service has no ClusterIP at all — its DNS name instead resolves directly to the individual IP addresses of every backing pod (an A/AAAA record per pod), giving clients direct visibility into and connectivity with each specific pod, which is exactly what's needed for a StatefulSet, where each pod's individual identity (not just "any healthy backend") matters.
Detailed Explanation
A normal Service's DNS resolves to a single stable virtual IP: my-service.namespace.svc.cluster.local resolves to one ClusterIP, and kube-proxy (via iptables/IPVS rules) transparently load-balances connections to that IP across whichever backend pods are currently ready — clients never see individual pod IPs at all, which is exactly the abstraction most stateless workloads want.
A headless Service's DNS resolves directly to each pod's IP: setting clusterIP: None tells Kubernetes not to allocate a virtual IP at all — CoreDNS instead returns multiple A/AAAA records, one per backing pod, when the Service's name is queried. There's no load-balancing virtual IP in the middle; a client resolving the name gets a list of actual pod IPs directly.
StatefulSet pods each get their own individually-addressable DNS name via a headless Service: when a StatefulSet is paired with a headless Service, each pod additionally gets its own stable DNS name in the form <pod-name>.<service-name>.<namespace>.svc.cluster.local (e.g., db-0.db-headless.default.svc.cluster.local) — this is what lets a client (or another pod in the same StatefulSet) address a specific replica directly, rather than "any one of the replicas," which matters enormously for a workload where pod identity carries meaning (a specific database replica's role, a specific shard).
This is the DNS-level counterpart to why StatefulSets need stable network identity at all: a StatefulSet's whole value proposition (stable, predictable per-pod identity across restarts) would be undermined if the only way to reach a specific pod was through a load-balanced virtual IP that could route to any replica — headless Service DNS is the mechanism that actually exposes that per-pod identity at the network/naming layer, completing what StatefulSet provides at the pod-identity layer.
Client-side load-balancing becomes the client's responsibility with a headless Service: since there's no virtual IP doing load-balancing, an application that wants to distribute requests across all the pods behind a headless Service needs to do its own client-side selection among the returned addresses (or use a library/driver that already knows how to do this, which is common for database clients that need to distinguish primary from replica addresses anyway) — this is a deliberate trade-off, not a limitation to work around, since it's exactly the control a StatefulSet-based client typically needs.
When you don't need it: for a stateless workload where any healthy replica is equally valid to handle a request, a normal (non-headless) Service's built-in load balancing is simpler and is almost always what you actually want — headless Services solve a specific problem (needing to address individual pod identity) that most workloads don't have.
Interview Follow-Up Questions
- How would a client application discover and connect specifically to a StatefulSet's primary replica, using headless Service DNS, if the primary can change over time?
- What happens to a headless Service's DNS records when a StatefulSet pod is being rescheduled — is there a window where the old and new records briefly conflict or overlap?
- How does this compare to using `ExternalName` or a `Endpoints`/`EndpointSlice` object directly, for cases needing similarly granular addressing outside of a StatefulSet context?
Key Takeaways
- A normal Service's DNS resolves to one virtual IP with kube-proxy load-balancing behind it; a headless Service's DNS resolves directly to each backing pod's individual IP.
- Headless Services paired with StatefulSets additionally give each pod its own stable, individually-addressable DNS name (
<pod-name>.<service-name>...). - This is the network-naming counterpart to StatefulSet's stable pod identity — without it, per-pod identity would exist at the pod level but not be reachable at the DNS level.
- With a headless Service, load-balancing across pods becomes the client's own responsibility, since there's no virtual IP performing it centrally.
References
Related Questions
Last updated August 22, 2026 · Last reviewed August 22, 2026