Description
A StatefulSet uses the headless Service named by serviceName to provide stable per-Pod network names. Create that Service separately in the same namespace, with a selector matching the StatefulSet Pod labels. Specifying a name does not create the Service automatically or guarantee DNS and connectivity.
Potential impact
- Per-Pod name resolution or communication between members can fail.
- A Service selector pointing to other Pods can disrupt connections to the intended workload.
Remediation
- Provide a headless Service with clusterIP: None in the same namespace and match serviceName to its name. Check its selector, Pod labels and actual listening ports.
- Plan replacement and connectivity effects before converting an existing ordinary Service to headless. After applying the configuration, check EndpointSlices, Pod readiness, per-Pod DNS and actual connections.
Examples
These existing nginx excerpts use the app namespace, which must be provided separately. 10.0.0.20 must be an available address in the cluster’s Service range. Converting an ordinary Service to headless may require recreating the Service.
Before
apiVersion: v1
kind: Service
metadata:
name: nginx
namespace: app
spec:
clusterIP: 10.0.0.20
selector:
app: other
ports:
- port: 80
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
namespace: app
spec:
serviceName: nginx
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.25
The ordinary ClusterIP Service also has a selector that differs from the StatefulSet Pod labels. It does not provide the required per-Pod headless Service connection.
After
apiVersion: v1
kind: Service
metadata:
name: nginx
namespace: app
spec:
clusterIP: None
selector:
app: nginx
ports:
- port: 80
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
namespace: app
spec:
serviceName: nginx
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.25
The same nginx Service name is configured as headless, with a selector matching the Pod labels. Verify actual DNS and connectivity in light of readiness and cluster networking.