Kubernetes: custom upstream for domain with CoreDNS

If you have a domain that you want CoreDNS to forward to a specific upstream DNS, you can add a block to the CoreDNS configmap.

Adding this domain block to the CoreDNS configmap and restarting the CoreDNS pods is sufficient will make the change take affect.  You may need to restart client pods if DNS caching is happening at the pod level.

Edit CoreDNS ConfigMap

By default, the CoreDNS deployment is configured by the ‘coredns’ ConfigMap.  Open it for editing

kubectl edit cm -n kube-system coredns

Assuming we want to have all DNS queries that end with “my.local” to be forwarded to the upstream DNS server at 192.168.1.1, we need to add the following 4 lines to the ConfigMap.

my.local:53 {
  log 
  forward . 192.168.1.1:53 
}

Which looks like below in the overall context of the ConfigMap.

apiVersion: v1
data:
  Corefile: |
    my.local:53 {
      log
      forward . 192.168.1.1:53
    }
    .:53 {
        log
        errors
        health {
           lameduck 5s
        }
        ready
        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

Restart CoreDNS pods

The CoreDNS pod(s) need to be restarted.

# enable CoreDNS logging if not found
kubectl get cm -n kube-system coredns -o=json | grep -q log || kubectl get cm -n kube-system coredns -o=json | jq 'del(.metadata.resourceVersion,.metadata.uid,.metadata.selfLink,.metadata.creationTimestamp,.metadata.annotations,.metadata.generation,.metadata.ownerReferences,.status)' | sed 's#\.:53 {#\.:53 {\\n    log#' | kubectl replace -f -

# restart all CoreDNS pods
kubectl get pod -n kube-system -l k8s-app=kube-dns --no-headers | awk '{print $1}' | xargs -I{} kubectl delete pod -n kube-system {}

# wait to be available again
kubectl wait deployment -n kube-system coredns --for condition=Available=True --timeout=90s

# tail CoreDNS logs
kubectl logs deployment/coredns -n kube-system -f

Validate DNS upstream

# try alpine based image with musl library which can act differently than libc
kubectl run -ti --rm alpine-musl --image=giantswarm/tiny-tools:3.12 --restart=Never --timeout=5s -- nslookup sub.my.local

# try libc based library
kubectl run -ti --rm busybox-libc --image=busybox:1.35.0-glibc --restart=Never --timeout=5s -- nslookup sub.my.local

The DNS queries will be output in the CoreDNS logs tailed earlier.

 

REFERENCES

CoreDNS.io manual

CoreDNS github

kubernetes.io, CoreDNS for Service Discovery

Digital Ocean, how to customize CoreDNS

coredns.io, corefile configuration explained

kubernetes.io, customizing DNS

kubernetes.io, troubleshooting DNS resolution

pracucci.com, why 5 ndots for kubernetes dns lookup can negatively affect performance

infracloud.io, using CoreDNS effectively