How to set hostname for kubernetes pod in statefulset

11/2/2019

I am using statefulset and I spin up multiple pods but they are not replica of each other. I want to set the hostname of the pods and passing these hostname as a env variable to all the pods so that they can communicate with each other.

I tried to use hostname under pod spec but hostname is never to set to specified hostname. However, it is set to hostname as podname-0.

# Source: testrep/templates/statefulset.yaml
apiVersion: apps/v1
kind: StatefulSet 
metadata:
  name: orbiting-butterfly-testrep
  labels:
    app.kubernetes.io/name: testrep
    helm.sh/chart: testrep-0.1.0
    app.kubernetes.io/instance: orbiting-butterfly
    app.kubernetes.io/managed-by: Tiller
spec:
  replicas: 1
  selector:
    matchLabels:
      app.kubernetes.io/name: testrep
      app.kubernetes.io/instance: orbiting-butterfly
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app.kubernetes.io/name: testrep
        app.kubernetes.io/instance: orbiting-butterfly
    spec:
      nodeSelector:
          testol: ad3
       hostname: test1
       containers:
        - name: testrep
          image: "test/database:v1"
          imagePullPolicy: IfNotPresent
          env:
           - name: DB_HOSTS
             value: test1,test2,test3
-- drifter
kubernetes

2 Answers

11/2/2019

Kuberenetes has service discovery baked in, so you don't have to do that. You can setup a headless service for your StatefulSet to let other applications talk to it.

The pods that are created with StatefulSets are ordered and setup sequentially. Hence the postfix integer value. You can read more on it here.

-- vjdhama
Source: StackOverflow

11/4/2019
  1. As per documentation:

    StatefulSet is the workload API object used to manage stateful applications.

    Manages the deployment and scaling of a set of Pods, and provides guarantees about the ordering and uniqueness of these Pods.

    StatefulSets are valuable for applications that require one or more of the following:

    • Stable, unique network identifiers.
    • Stable, persistent storage.
    • Ordered, graceful deployment and scaling.
    • Ordered, automated rolling updates.
  2. Statefulset Limitations:

    StatefulSets currently require a Headless Service to be responsible for the network identity of the Pods. You are responsible for creating this Service.

  3. Pod Identity

    StatefulSet Pods have a unique identity that is comprised of an ordinal, a stable network identity, and stable storage. The identity sticks to the Pod, regardless of which node it’s (re)scheduled on. For a StatefulSet with N replicas, each Pod in the StatefulSet will be assigned an integer ordinal, from 0 up through N-1, that is unique over the Set.

  4. Stable Network ID

    Each Pod in a StatefulSet derives its hostname from the name of the StatefulSet and the ordinal of the Pod. The pattern for the constructed hostname is $(statefulset name)-$(ordinal). The example above will create three Pods named web-0,web-1,web-2. A StatefulSet can use a Headless Service to control the domain of its Pods. The domain managed by this Service takes the form: $(service name).$(namespace).svc.cluster.local, where “cluster.local” is the cluster domain. As each Pod is created, it gets a matching DNS subdomain, taking the form: $(podname).$(governing service domain), where the governing service is defined by the serviceName field on the StatefulSet.

Note:

You are responsible for creating the Headless Service responsible for the network identity of the pods.

So as described by vjdhama Please create your Statefulset with Headless Service.

You can find this example in the docs:

apiVersion: v1
kind: Service
metadata:
 name: nginx
 labels:
   app: nginx
spec:
  ports:
  - port: 80
    name: web
  clusterIP: None
  selector:
    app: nginx


apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  selector:
    matchLabels:
      app: nginx # has to match .spec.template.metadata.labels
  serviceName: "nginx"
  replicas: 3 # by default is 1
  template:
    metadata:
      labels:
        app: nginx # has to match .spec.selector.matchLabels
    spec:
      terminationGracePeriodSeconds: 10
      containers:
      - name: nginx
        image: k8s.gcr.io/nginx-slim:0.8
        ports:
        - containerPort: 80

In this scenario Pod DNS and Pod Hostnames should be respectively:

    Pod DNS
    web-{0..N-1}.nginx.default.svc.cluster.local

    Pod Hostname
    web-{0..N-1}


    NAME                                   READY   STATUS    RESTARTS   AGE     IP               
    pod/web-0                              1/1     Running   0          5m      192.168.148.78   
    pod/web-1                              1/1     Running   0          4m53s   192.168.148.79   
    pod/web-2                              1/1     Running   0          4m51s   192.168.148.80  

From the Pod perspective:

   root@web-2:# nslookup nginx
   Server:      10.96.0.10
   Address: 10.96.0.10#53

   Name:    nginx.default.svc.cluster.local 
   Address: 192.168.148.80
   Name:    nginx.default.svc.cluster.local
   Address: 192.168.148.78
   Name:    nginx.default.svc.cluster.local
   Address: 192.168.148.79

So you can call each of the respective pods using the Pod DNS, like:

web-0.nginx.default.svc.cluster.local

Update:

Exposing single pod from StatefulSet. You can find here tricky way. Using described above advantages of Statefulset:

The pattern for the constructed hostname is $(statefulset name)-$(ordinal). The example above will create three Pods named web-0,web-1,web-2.

So as an example:

apiVersion: v1
kind: Service
metadata:
  name: app-0
spec:
  type: LoadBalancer
  selector:
    statefulset.kubernetes.io/pod-name: web-0
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80

Will do this for you.

Hope this help.

-- Hanx
Source: StackOverflow