Review the StatefulSet headless Service connection

Check that serviceName, the actual headless Service and Pod selectors agree.

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

yaml
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

yaml
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.

References