Obtain Pod DNS Name Programmatically

4/5/2018

I have a statefulset with 3 members. They are accessible from inside the cluster with something like:

podname-{0..n}.service.default.svc.cluster.local

I'm using the Kubernetes API from a Controller. I just created the Statefulset with:

import (
    "k8s.io/client-go/kubernetes"
    appsv1 "k8s.io/api/apps/v1"
)
...

s := appsv1.StatefulSet{ /* some data */ }
kubernetes.AppsV1().StatefulSets(nameSpace).Create(s)

Let's assume everything worked correctly, and after a few minutes I have 3 running Pods. How can I get the Pod DNS entries for the newly created Pods?

I know I can build the DNS with:

fmt.Sprintf("%s-%d.%s.%s.svc.cluster.local", s.Name, idx, service, S.Namespace)

But I'm finding some issues:

  1. I will have to calculate the index depending on the amount of replicas
  2. I need to know about the service name used for this StatefulSet
  3. I'm assuming the cluster domain is cluster.local which is not necessarily true

What I think it should exists (but I'm not sure if it really exists), is an API, that given a StatefulSet will allow me to know the DNS names of the Replicas that were created. Does an API like this exists?

-- licorna
kubernetes
kubernetes-go-client

2 Answers

4/10/2018

When you create the headless Service with the StatefulSet, it should create DNS SRV entries. You can query that to get a list of all host names of the pods corresponding to the headless Service without knowing the number. For example, if using Python you can do:

>>> import dns
>>> for item in dns.resolver.query('your-app-name-headless', 'SRV'): item
...
<DNS IN SRV rdata: 10 25 0 2555bb89.your-app-name-headless.your-project.svc.cluster.local.>
<DNS IN SRV rdata: 10 25 0 830bdb18.your-app-name-headless.your-project.svc.cluster.local.>
<DNS IN SRV rdata: 10 25 0 aeb532de.your-app-name-headless.your-project.svc.cluster.local.>
<DNS IN SRV rdata: 10 25 0 a432c21f.your-app-name-headless.your-project.svc.cluster.local.>

See:

-- Graham Dumpleton
Source: StackOverflow

4/6/2018

Event sniffing what you need is pretty much exactly how KubeDNS works.

So code here of old and simple way. take a look podWatchFunc method. So here short example of code

func podWatchFunc(c *kubernetes.Clientset, ns string, s labels.Selector) func(options meta.ListOptions) (watch.Interface, error) {
    return func(options meta.ListOptions) (watch.Interface, error) {
        if s != nil {
            options.LabelSelector = s.String()
        }
        w, err := c.CoreV1().Pods(ns).Watch(options)
        if err != nil {
            return nil, err
        }
        return w, nil
    }
}

Another good and recommended way in official doc

 import (
   "fmt"
   "k8s.io/client-go/1.4/kubernetes"
   "k8s.io/client-go/1.4/pkg/api/v1"
   "k8s.io/client-go/1.4/tools/clientcmd"
)
...
   // uses the current context in kubeconfig
   config, _ := clientcmd.BuildConfigFromFlags("", "path to kubeconfig")
   // creates the clientset
   clientset, _:= kubernetes.NewForConfig(config)
   // access the API to list pods
   pods, _:= clientset.CoreV1().Pods("").List(v1.ListOptions{})
   fmt.Printf("There are %d pods in the cluster\n", len(pods.Items))
... 

full code

You also may understand that dns is separate k8s service, not part of cluster services. So find ip/host and call your dns endpoint For details if you use default naming policy and coredsn or dns-masq service. You also can have domain name from pod metadata name or selflink

    metadata:
  creationTimestamp: 2018-04-01T13:45:01Z
  generateName: client-deployment-f8454db47-
  labels:
    app: client
    pod-template-hash: "940108603"
  name: client-deployment-f8454db47-5gk64
  namespace: novaposhta
  ownerReferences:
  - apiVersion: extensions/v1beta1
    blockOwnerDeletion: true
    controller: true
    kind: ReplicaSet
    name: client-deployment-f8454db47
    uid: d833ef0f-35b2-11e8-9278-42010a840112
  resourceVersion: "73550"
  selfLink: /api/v1/namespaces/novaposhta/pods/client-deployment-f8454db47-5gk64
-- Grigoriev Nick
Source: StackOverflow