Technical Theory

CoreDNS Configuration

Introduction

This tutorial demonstrates how to configure CoreDNS, the default DNS server in Kubernetes, to resolve custom domain names within the cluster. You will learn how to modify the CoreDNS ConfigMap to add custom DNS entries and verify that they resolve correctly from within your pods.

Prerequisites:

  • A running Kubernetes cluster (Minikube, Kind, or a cloud provider’s Kubernetes service).
  • kubectl command-line tool configured to interact with your cluster.

Task 1: Inspecting the Default CoreDNS Configuration

First, let’s examine the default CoreDNS configuration. This will give us a baseline to understand what we’re changing.

  1. Get the CoreDNS ConfigMap:

    NODE_TYPE // bash
    kubectl get configmap coredns -n kube-system -o yaml
  2. Examine the output. Look for the Corefile key in the data section. This contains the CoreDNS configuration. You will see entries like kubernetes, prometheus, and errors plugins.

    NODE_TYPE // yaml
    apiVersion: v1
    data:
      Corefile: |
        .:53 {
            errors
            health {
               lameduck
            }
            kubernetes cluster.local in-addr.arpa ip6.arpa {
               pods insecure
               fallthrough in-addr.arpa ip6.arpa
               ttl 30
            }
            prometheus :9153
            forward . /etc/resolv.conf {
               max_concurrent 1000
            }
            cache 30
            loop
            reload
            loadbalance
        }
    kind: ConfigMap
    metadata:
      name: coredns
      namespace: kube-system
    The Corefile is the primary configuration file for CoreDNS. It defines how CoreDNS handles DNS queries.

Task 2: Creating a Custom DNS Entry

Now, let’s add a custom DNS entry to the CoreDNS configuration. We’ll create an entry for example.local that resolves to the IP address 192.168.1.100.

  1. Edit the CoreDNS ConfigMap:

    NODE_TYPE // bash
    kubectl edit configmap coredns -n kube-system
  2. In the Corefile section, add a new zone for example.local before the existing . zone:

    NODE_TYPE // yaml
    apiVersion: v1
    data:
      Corefile: |
        example.local:53 {
            errors
            forward . 8.8.8.8 8.8.4.4
        }
        .:53 {
            errors
            health {
               lameduck
            }
            kubernetes cluster.local in-addr.arpa ip6.arpa {
               pods insecure
               fallthrough in-addr.arpa ip6.arpa
               ttl 30
            }
            prometheus :9153
            forward . /etc/resolv.conf {
               max_concurrent 1000
            }
            cache 30
            loop
            reload
            loadbalance
        }
    kind: ConfigMap
    metadata:
      name: coredns
      namespace: kube-system
    Be careful when editing the ConfigMap. Incorrect syntax can break DNS resolution in your cluster.
    The forward . 8.8.8.8 8.8.4.4 line tells CoreDNS to forward any requests for domains outside example.local to Google’s public DNS servers.

Task 3: Applying a Static DNS Record

Now let’s configure CoreDNS to return a static IP address for our example.local domain.

  1. Edit the CoreDNS ConfigMap:

    NODE_TYPE // bash
    kubectl edit configmap coredns -n kube-system
  2. Modify the Corefile section to include a hosts block. Replace the forwarding entry with a static IP record:

    NODE_TYPE // yaml
    apiVersion: v1
    data:
      Corefile: |
        example.local:53 {
            errors
            hosts {
              192.168.1.100 example.local
              fallthrough
            }
        }
        .:53 {
            errors
            health {
               lameduck
            }
            kubernetes cluster.local in-addr.arpa ip6.arpa {
               pods insecure
               fallthrough in-addr.arpa ip6.arpa
               ttl 30
            }
            prometheus :9153
            forward . /etc/resolv.conf {
               max_concurrent 1000
            }
            cache 30
            loop
            reload
            loadbalance
        }
    kind: ConfigMap
    metadata:
      name: coredns
      namespace: kube-system
    The hosts plugin allows you to define static DNS records within CoreDNS. The fallthrough keyword ensures that if a record is not found in the hosts file, CoreDNS will continue to the next plugin in the chain.

Task 4: Restarting CoreDNS Deployments

Kubernetes will automatically rollout the changes to the CoreDNS pods.

  1. To expedite the rollout, you can manually restart the CoreDNS deployments.

    NODE_TYPE // bash
    kubectl rollout restart deployment coredns -n kube-system

Task 5: Verifying the DNS Resolution

Now, let’s verify that our custom DNS entry resolves correctly from within a pod in the cluster.

  1. Create a test pod:

    NODE_TYPE // yaml
    apiVersion: v1
    kind: Pod
    metadata:
      name: dns-test
    spec:
      containers:
      - name: busybox
        image: busybox:latest
        command:
          - sleep
          - "3600"
        imagePullPolicy: IfNotPresent
      restartPolicy: Always

    Save this as dns-test.yaml and apply it:

    NODE_TYPE // bash
    kubectl apply -f dns-test.yaml
  2. Get a shell into the test pod:

    NODE_TYPE // bash
    kubectl exec -it dns-test -- sh
  3. Use nslookup or ping to resolve example.local:

    NODE_TYPE // bash
    nslookup example.local

    or

    NODE_TYPE // bash
    ping example.local
  4. Expected output (using nslookup):

    NODE_TYPE // output
    Server:    10.96.0.10
    Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local
    
    Name:      example.local
    Address 1: 192.168.1.100

    If the output shows that example.local resolves to 192.168.1.100, then your configuration is working correctly.

    If nslookup is not available in the busybox image, you can use ping -c 1 example.local and check the IP address in the output.

Conclusion

In this tutorial, you learned how to configure CoreDNS in Kubernetes to resolve custom domain names. You modified the CoreDNS ConfigMap to add a static DNS entry and verified that it resolves correctly from within a pod. This is a fundamental skill for managing internal DNS resolution in Kubernetes clusters.

Next Topic