Kubernetes exposes DNS for service discovery, but the DNS server itself must be configured after you install Kubernetes. In the future it will be integrated into kubernetes as part of the platform (see PR11599) but for now you have to setup and run the SkyDNS container yourself.

I have seen some tutorials on how to get skydns working, but almost all of them are rather involved. However, if you just want a simple setup on a single node for testing then it is actually rather easy to get skydns set up.

Setting it up

NOTE: This tutorial assumes that you already have a machine with docker and kubernetes set up and working. This has been tested on Fedora 22 and CentOS 7. It should work on other platforms but YMMV.

So the way kubernetes/skydns work together is by having two parts:

  • kube2sky - listens on the kubernetes api for new services and adds information into etcd.
  • skydns - listens for dns requests and responds based on information in etcd.

The easiest way to get kube2sky and skydns up and running is to just kick off a few docker containers. We’ll start with kube2sky like so:

[root@f22 ~]$ docker run -d --net=host --restart=always          \
                gcr.io/google_containers/kube2sky:1.11           \
                -v=10 -logtostderr=true -domain=kubernetes.local \
                -etcd-server="http://127.0.0.1:2379"

NOTE: We are re-using the same etcd that kubernetes is using.

The next step is to start skydns to respond to dns queries:

[root@f22 ~]$ docker run -d --net=host --restart=always         \
                -e ETCD_MACHINES="http://127.0.0.1:2379"        \
                -e SKYDNS_DOMAIN="kubernetes.local"             \
                -e SKYDNS_ADDR="0.0.0.0:53"                     \
                -e SKYDNS_NAMESERVERS="8.8.8.8:53,8.8.4.4:53"   \
                gcr.io/google_containers/skydns:2015-03-11-001

The final step is to modify your kubelet configuration to let it know where the dns for the cluster is. You can do this by adding --cluster_dns and --cluster_domain to KUBELET_ARGS in /etc/kubernetes/kubelet:

[root@f22 ~]$ grep KUBELET_ARGS /etc/kubernetes/kubelet
KUBELET_ARGS="--cluster_dns=192.168.121.174 --cluster_domain=kubernetes.local"
[root@f22 ~]$ systemctl restart kubelet.service

NOTE: I used the ip address of the machine that we are using for this single node cluster.

And finally we can see our two containers running:

[root@f22 ~]$ docker ps --format "table {{.ID}}\t{{.Status}}\t{{.Image}}"
CONTAINER ID        STATUS              IMAGE
d229442f533c        Up About a minute   gcr.io/google_containers/skydns:2015-03-11-001
76d51770b240        Up About a minute   gcr.io/google_containers/kube2sky:1.11

Testing it out

Now lets see if it works! Taking a page out of the kubernetes github we’ll start a busybox container and then do an nslookup on the kubernetes service:

[root@f22 ~]$ cat > /tmp/busybox.yaml <<EOF
apiVersion: v1
kind: Pod
metadata:
  name: busybox
  namespace: default
spec:
  containers:
  - image: busybox
    command:
      - sleep
      - "3600"
    imagePullPolicy: IfNotPresent
    name: busybox
  restartPolicy: Always
EOF
[root@f22 ~]$ kubectl create -f /tmp/busybox.yaml
pod "busybox" created
[root@f22 ~]$ kubectl get pods
NAME      READY     STATUS    RESTARTS   AGE
busybox   1/1       Running   0          16s
[root@f22 ~]$ kubectl exec busybox -- nslookup kubernetes
Server:    192.168.121.174
Address 1: 192.168.121.174

Name:      kubernetes
Address 1: 10.254.0.1

NOTE: The kubernetes service is the one that is shown from the kubectl get services kubernetes command.

Now you have a single node k8s setup with dns. In the future PR11599 should satisfy this need but this works for now.