Home

Create DNS Entries for Pods WIthout Load-Balancing with Headless Services

A Problem with Services And Stateful Sets

Pods in a Stateful set get ordinal, stateful, unique names.
Apps "talk to" one another through services.
The services act as load-balancers, passing around traffic around to all nodes in a set.
In a stateful set, such as a master db with slave replica dbs, load-balancing traffic between the master and slaves is not going to work.

Headless Services Provide A DNS Entry Without Load-Balancing

Headless services don't have I.Ps of their own.
Headless services don't do load-balancing.
Headless services create DNS entries for each pod - using pod + subdomain - podname.headless-servicename-namespace.svc.cluster-domain.
With that naming scheme, the "master" pod for a db replica set has a unique name.

Headless Service Definition File

Here, the clusterIP: none is what tells k8s to make the service headless.

apiVersion: v1
name: Service
metadata:
  name: db-h
spec:
  ports:
    - port: 27017
  selector:
    app: mongodb
  # THIS makes the service headless!
  clusterIP: none

Pod Definitions Need Updates

For pods to work with stateful sets and headless services, 2 fields must be added to the pod definition file. The pods will get dns records instead of the service, so a few details are required:

  • spec.hostname
    • doesn't need to match the service
  • spec.subdomain
    • this must match the name of the headless service in the service def metadata.name - see a pod def file example below

Pod Def File To Work With a StatefulSet And A Headless Service

With this, DNS records get created per pod, with the hostname field and the subdomain field.

apiVersion: v1
kind: Pod
metadata:
  name: db-pod
spec:
  # THIS! must match the headless service metadata.name
  subdomain: db-h
  # THIS!
  hostname: db-pod
  containers:
  - name: mongodb
    image: mongodb:5

Deploying a pod via Deployment

Similar to the pod def file, a deployment would require new details.
The Deployment needs

apiVersion: apps/v1
kind: Deployment
metadata:
  name: db-deployment
  labels:
    app: db
spec:
  replicas: 3
  matchLabels:
    app: db
  template:
    metadata:
      name: db-pod
      labels:
        app: db
    spec:
      containers:
      - name: mongodb
        image: mongodb:5

Comparing to a stateful set

Deploying a stateful set, instead of a deployment, that connects to a headless service - a serviceName needs to be specified for the statefulset.
K8s uses the servicename to apply subdomains to its pods, instaed of the subdomain+hostname field requirements listed above.

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: db-deployment
  labels:
    app: db
spec:
  # THIS! must match the headless-service metadata.name
  # this matches the pods in this statefulSet to the headless service
  serviceName: db-h
  replicas: 3
  matchLabels:
    app: db
  template:
    metadata:
      name: db-pod
      labels:
        app: db
    spec:
      containers:
      - name: mongodb
        image: mongodb:5
Tags: