CoreDNS is your cluster’s phone book, but it’s surprisingly complex because it’s designed to be pluggable and extensible.

Let’s see it in action. Imagine you have a service named my-service in the default namespace. From within a pod, you’d typically resolve its cluster IP like this:

# Executed inside a pod
kubectl exec -it <your-pod-name> -- nslookup my-service.default.svc.cluster.local

The output you’d expect to see is something like:

Server:         10.96.0.10
Address:        10.96.0.10#53

Name:   my-service.default.svc.cluster.local
Address: 10.244.1.100

Here, 10.96.0.10 is the ClusterIP of the CoreDNS service itself, and 10.244.1.100 is the ClusterIP of your my-service. CoreDNS intercepts this request, looks up my-service in its internal records (which are populated by Kubernetes), and returns the correct IP.

CoreDNS solves the problem of name resolution within a dynamic Kubernetes environment. Unlike traditional DNS where records are static, Kubernetes is constantly creating and destroying pods and services. CoreDNS needs to be aware of these changes and update its DNS records accordingly, providing a stable and accessible way for workloads to find each other. It achieves this through a series of plugins, each responsible for a specific DNS function.

The core of CoreDNS configuration lies in its Corefile. This is a declarative configuration file that specifies how CoreDNS should handle incoming DNS queries. A typical Corefile for Kubernetes looks like this:

.:53 {
    errors
    health {
       lameduck 5s
    }
    ready
    kubernetes cluster.local in-addr.arpa ip6.arpa {
       pods insecure
       fallthrough in-addr.arpa ip6.arpa
    }
    prometheus :9153
    forward . /etc/resolv.conf
    cache 30
    loop
    reload
    loadbalance
}

Let’s break down the key parts:

  • . :53: This is the default server block, meaning it listens on port 53 for all domain names (.).
  • errors: Logs DNS errors.
  • health { lameduck 5s }: Implements a health check endpoint. The lameduck period allows CoreDNS to finish in-flight requests before shutting down during a graceful termination.
  • ready: Implements a readiness check endpoint.
  • kubernetes cluster.local in-addr.arpa ip6.arpa { pods insecure fallthrough in-addr.arpa ip6.arpa }: This is the most crucial plugin for Kubernetes. It tells CoreDNS to handle DNS queries for cluster.local (your cluster domain), in-addr.arpa (for reverse DNS lookups of IPs), and ip6.arpa (for IPv6 reverse DNS).
    • pods insecure: This setting is often used in Kubernetes to prevent CoreDNS from trying to verify TLS certificates for pod DNS records, which is generally not needed or practical within a cluster.
    • fallthrough in-addr.arpa ip6.arpa: If CoreDNS can’t find a record for an IP address within the cluster domain, it will pass the request to the upstream DNS resolver (usually your node’s /etc/resolv.conf).
  • prometheus :9153: Exposes Prometheus metrics on port 9153, allowing you to monitor CoreDNS’s performance.
  • forward . /etc/resolv.conf: For any queries not handled by the kubernetes plugin, this forwards them to the DNS servers listed in the pod’s /etc/resolv.conf (which usually points to your cluster’s upstream DNS).
  • cache 30: Caches DNS responses for 30 seconds, reducing the load on upstream resolvers and speeding up subsequent lookups.
  • loop: Detects and prevents DNS request loops.
  • reload: Automatically reloads the Corefile when it changes, without needing to restart the CoreDNS pods.
  • loadbalance: Distributes load across multiple CoreDNS instances if you have a highly available setup.

When you deploy Kubernetes, CoreDNS is typically deployed as a Deployment with a corresponding Service. The Corefile is usually mounted into the pods of the Deployment via a ConfigMap.

The one thing most people don’t realize is how granularly you can control DNS resolution behavior using the kubernetes plugin’s options. For instance, pods endpoint instead of pods insecure would attempt to resolve pod IPs directly from the endpoints of services, which can be useful in specific network configurations but is generally more complex and less performant than the default. You can also specify different domains for different plugins, allowing for complex multi-domain setups within a single CoreDNS instance.

The next concept to dive into is how to configure custom DNS entries for your applications using the hosts or rewrite plugins in the Corefile.

Want structured learning?

Take the full Coredns course →