Headless Services
A regular Service provides a single stable virtual IP (ClusterIP) that load-balances across all matching Pods. You send traffic to the ClusterIP, and kube-proxy distributes it. Individual Pods are hidden behind the virtual IP.
A headless Service has clusterIP: None. There is no virtual IP. Instead, DNS returns the actual IP addresses of each matching Pod directly. For StatefulSets, DNS returns one record per Pod, using the Pod’s stable name. This enables direct Pod-to-Pod addressing that survives restarts.
Creating a headless Service
The only difference from a regular Service is clusterIP: None:
apiVersion: v1kind: Servicemetadata: name: web-headlessspec: clusterIP: None selector: app: web ports: - port: 80 name: webkubectl get service web-headlessThe CLUSTER-IP column shows None. There is no virtual IP for this service.
DNS for StatefulSet Pods
When a headless Service is paired with a StatefulSet via serviceName, each Pod gets its own DNS A record:
<pod-name>.<service-name>.<namespace>.svc.cluster.localFor our web StatefulSet with serviceName: web-headless in the default namespace:
web-0.web-headless.default.svc.cluster.localresolves to the IP ofweb-0web-1.web-headless.default.svc.cluster.localresolves to the IP ofweb-1web-2.web-headless.default.svc.cluster.localresolves to the IP ofweb-2
Test DNS resolution from inside a Pod:
kubectl exec web-0 -- nslookup web-1.web-headless.default.svc.cluster.localThis returns the actual IP of web-1. If web-1 restarts and gets a new IP, the DNS record updates to the new IP automatically. The DNS name web-1.web-headless... remains stable even as the underlying IP changes.
A StatefulSet Pod restarts and gets a new IP address. Another Pod was communicating with it using the Pod-specific DNS name. Does the other Pod need to reconnect or update its DNS cache?
Reveal answer
It needs to re-resolve the DNS name (which happens naturally if the DNS TTL expires). The DNS name web-1.web-headless.default.svc.cluster.local still works, but it now points to the new IP. TCP connections established before the restart are broken and must be re-established. DNS-based reconnection works because the name is stable even though the IP changed.
DNS for the entire StatefulSet
A DNS query for just the Service name (without a Pod prefix) on a headless Service returns all Pod IPs:
kubectl exec web-0 -- nslookup web-headlessThis returns multiple A records, one for each ready Pod. This is useful for initial cluster discovery: a new node can find all existing members by querying the service name, then communicate with specific members by their individual names.
This contrasts with a regular ClusterIP Service, where nslookup web-regular returns only the single ClusterIP, hiding the individual Pods.
Regular Service alongside headless Service
StatefulSets often use both types of Services:
- Headless Service (used as
serviceName): provides stable per-Pod DNS, used by cluster members to communicate with each other - Regular ClusterIP or NodePort Service: provides a load-balanced endpoint for clients that do not need to reach a specific Pod (e.g., read traffic to any replica)
# Regular Service for client access (routes to any ready Pod)apiVersion: v1kind: Servicemetadata: name: webspec: selector: app: web ports: - port: 80With both Services, clients connect to web (load-balanced), while cluster nodes communicate via web-0.web-headless, web-1.web-headless, etc.
The headless Service must exist before the StatefulSet is created, or the DNS records will not be set up. If the Service is created after the StatefulSet, the existing Pods do not automatically get DNS entries. In practice, always define the headless Service in the same manifest file, before the StatefulSet, to ensure correct ordering on kubectl apply.
You have a headless Service db-headless for a StatefulSet db. A client Pod queries db-headless. What does it receive?
Reveal answer
A list of A records, one for each ready Pod in the StatefulSet. For a 3-replica StatefulSet, the DNS response contains three IP addresses (db-0’s IP, db-1’s IP, db-2’s IP). The client can then choose which to connect to, or connect to all of them for replication setup.
The headless Service is the bridge between the StatefulSet’s stable Pod names and stable network addressing. The next lesson covers how StatefulSets manage persistent storage with dedicated PVCs for each Pod.