Kubernetes – DNS

Kubernetes – DNS

February 18, 2019 4 By Eric Shanks

DNS is a critical service in any system. Kubernetes is no different, but Kubernetes will implement its own domain naming system that’s implemented within your Kubernetes cluster. This post explores the details that you need to know to operate a k8s cluster properly.

Kubernetes DNS – The theory

I don’t want to dive into DNS too much since it’s a core service most should be familiar with. But at a really high level, DNS translates an IP address that might be changing, with an easily remember-able name such as “theithollow.com”. Every network has a DNS server, but Kubernetes implements their own DNS within the cluster to make connecting to containers a simple task.

There are two implementations of DNS found within Kubernetes clusters. Kube-dns and CoreDNS. The default used with kubeadm after version 1.13 is to use CoreDNS which is managed by the Cloud Native Computing Foundation. Since I used kubeadm to setup our cluster and it’s the default version, this post will focus on CoreDNS.

This topic can be pretty detailed, but lets distill it into the basics. Each time you deploy a new service or pod, the DNS service sees the calls made to the Kube API and adds DNS entries for the new object. Then other containers within a Kubernetes cluster can use these DNS entries to access the services within it by name.

There are two objects that you could access via DNS within your Kubernetes cluster and those are Services and Pods. Now Pods can get a dns entry, but you’d be wondering why, since we’ve learned that accessing pods should be done through a Service. For this reason, pods don’t get a DNS entry by default with CoreDNS.

Services get a DNS entry of the service name appended to the namespace and then appended to “svc.cluster.local”. Similarly pods get entries of PodIPAddress appended to the namespace and then appended to .pod.cluster.local if Pod DNS is enabled in your cluster.

The diagram below shows a pair of services and a pair of pods that are deployed across two different namespaces. Below this are the DNS entries that you can expect to be available for these objects, again assuming Pod DNS is enabled for your cluster.

Any pods looking for a service within the same namespace can just use the common name of the “Service” instead of the FQDN. Kubernetes will add the proper DNS suffix to the request if one is not given. In fact, when you deploy new pods, Kubernetes specifies your DNS server for you unless you override it within a manifest file.

Kubernetes DNS – In Action

Lets take a quick look at how DNS is working in our own Kubernetes cluster. Feel free to deploy any Kubernetes manifest that has a service and pod in the deployment. If you need one, you can use mine below.

apiVersion: apps/v1 
kind: Deployment 
metadata: 
  name: nginx-deployment 
  labels: 
    app: nginx
spec: 
  replicas: 2 
  selector:
    matchLabels:
      app: nginx 
  template: 
    metadata:
      labels: 
        app: nginx
    spec:
      containers:
      - name: nginx-container 
        image: nginx 
        ports:
        - containerPort: 80 
---
apiVersion: v1
kind: Service
metadata:
  name: nginxsvc
spec:
  type: NodePort
  ports:
  - name: http
    port: 80
    targetPort: 80
    nodePort: 30001
    protocol: TCP
  selector:
    app: nginx

You can deploy the file with:

kubectl apply -f [manifest file].ymlCode language: CSS (css)

Now lets look at some information about our service which we’ll check later in this post.

kubectl get svcCode language: JavaScript (javascript)

Once our example pods and services are deployed, let’s deploy another container where we can run some DNS lookups. To do this we’ll deploy the shell-demo container and get an interactive shell by using the commands below. We’ll also install busybox once we’ve got a shell.

Kubectl create -f https://k8s.io/examples/application/shell-demo.yaml

kubectl exec -it shell-demo -- /bin/bash

Apt-get update
Apt-get install busybox -y
Code language: JavaScript (javascript)

Now that busybox is installed and we’re in an interactive shell session, lets check to see what happens when we run a dns lookup on our example service.

busybox nslookup nginxsvc

The results of our nslookup on the nginxsvc that we deployed early on in this post shows the ClusterIP address of the Service. Also, pay close attention to the FQDN. The FQDN is the [service name] +”.” + [namespace name] + “.” + svc.cluster.local.

Summary

DNS is a basic service that we rely on for almost all systems. Kubernetes is no different and it makes accessing other services very simple and straightforward. You can manipulate your DNS configs by update manifest files if you need, but for the basic operations, you should be good to go without even having to configure much. And remember… it’s ALWAYS DNS.

To clean up your cluster run:

kubectl delete -f [manifest file].yml #manifest used during the deploy of the nginxsvc
kubectl delete pod shell-demoCode language: CSS (css)