July 10, 2018·4 min read·engineeringkubernetesdnsconfiguration

CoreDNS makes service discovery behavior configurable in one process

The Kubernetes 1.11 CoreDNS guide explains the migration from kube-dns. Its default configuration preserves familiar discovery behavior while making the DNS server's responsibilities easier to inspect.

A DNS migration can preserve application lookups while changing the implementation behind them. The July 10 CoreDNS guide explains this distinction following general availability in Kubernetes 1.11. CoreDNS consolidates the Kubernetes DNS server's work into one process, with plugins configured through a Corefile. Compatibility with existing discovery behavior remains the default, while additional behavior requires explicit configuration.

I find the consolidation useful because DNS behavior is already difficult to diagnose from an application's connection error. A configuration which identifies the server's responsibilities in one place helps explain where a query should go. It also makes local changes visible as DNS server configuration, which matters when the server supplies both Kubernetes records and forwarding for other names.

The installed Corefile describes several responsibilities

The kubeadm manifests shipped in Kubernetes 1.11.0 show the configuration which supports the new default. A ConfigMap supplies the Corefile to a read-only volume mounted at /etc/coredns. The Deployment starts CoreDNS with that file as its configuration. The pod therefore carries an explicit dependency on a separately represented configuration object.

Within the Corefile, the kubernetes directive receives the cluster DNS domain and reverse-lookup zones. Its block includes pods insecure, upstream and fallthrough for the reverse zones. Outside that block, the configuration enables a health endpoint and Prometheus metrics. It also configures a proxy for upstream resolution, a cache and configuration reload behavior.

This is a concrete expression of DNS responsibilities which had been distributed among kube-dns containers. The Kubernetes integration answers for cluster records, while upstream proxying handles other resolution. A cache can reduce repeated work without becoming the authority for the cluster's resource declarations. These functions belong to the same server process but retain distinct configuration entries.

The default pods insecure setting is particularly relevant to the difference between compatibility and additional validation. An optional verified mode described in the July guide checks for a pod with the requested address in the specified namespace. Kubeadm's shipped manifest does not select that mode. Installing CoreDNS therefore should not be described as automatically enabling every stronger validation option available in its Kubernetes integration. Reading the active Corefile establishes which behavior the installation requests, including changes made after the initial add-on configuration.

The Service name remains kube-dns

The manifests name the CoreDNS Deployment coredns but retain the k8s-app: kube-dns label on its pods. The DNS Service is still named kube-dns and selects that label. Its ports expose both UDP and TCP on port 53. The implementation change preserves a service endpoint while replacing the process which receives the selected traffic.

That naming is relevant when inspecting an upgraded cluster. A Service called kube-dns is compatible with a CoreDNS Deployment behind it. Names alone are insufficient to determine the running implementation. The Deployment's container image and command identify what actually starts, while the Service selector explains how requests reach its pods.

The CoreDNS Deployment requests two replicas and uses a rolling update strategy with one allowed unavailable replica. These are installation choices expressed in the manifest, independent of the DNS protocol behavior. They affect how many server pods the controller maintains and how it can replace them. The manifest also gives the DNS pod dnsPolicy: Default, explicitly avoiding dependence on the cluster DNS policy it supplies to other workloads.

The installed authorization resources grant list and watch access to endpoints, services, pods and namespaces. That permission set explains the API relationship behind the server's Kubernetes integration. DNS records depend on cluster objects which can change during normal operation. Reading the manifests exposes both the DNS-facing endpoint and the resources the server is permitted to observe.

Metrics and runtime permissions need separate interpretation

The July guide warns that CoreDNS metrics differ from kube-dns metrics. The manifest exposes the CoreDNS metrics port at 9153 and enables the Prometheus plugin at that address. Retaining the DNS Service name does not preserve the old metrics contract. A monitoring query based on the prior implementation can therefore need a change even when application lookups remain compatible.

The container security settings also describe the actual installation more precisely than a general claim about implementation safety. The manifest disables privilege escalation, drops capabilities and adds NET_BIND_SERVICE. It sets a read-only root filesystem. These are explicit runtime constraints which can be inspected alongside the command and mounted configuration.

I prefer that level of specificity when assessing infrastructure defaults. A Go implementation and a plugin model explain parts of the server's design, but the deployment still determines its permissions and configuration. The Kubernetes 1.11 manifests make those choices visible through ordinary API objects. The Corefile controls query handling, the authorization objects control API observation, and the Deployment supplies the process which uses both.