Cluster DNS with CoreDNS

Khimananda Oli 7 min read Virtualization
Cluster DNS with CoreDNS

By Khimananda Oli | Last reviewed: August 2026

Kubernetes service discovery fails silently when misconfigured, causing intermittent timeouts and cascading application errors that are difficult to trace. Implementing Cluster DNS with CoreDNS correctly is the foundation of reliable internal networking, transforming raw IP addresses into stable service names that survive pod restarts and scaling events. This guide covers the practical configuration, plugin architecture, and debugging workflows you need to maintain a resilient DNS layer in production clusters.

Pod (Client)CoreDNS Podcache pluginkubernetes pluginforward pluginUpstream DNS
CoreDNS request flow: queries pass through cache, kubernetes zone handling, and forward plugins before reaching upstream resolvers.

How does Cluster DNS with CoreDNS resolve Kubernetes services?

CoreDNS replaced kube-dns as the default cluster DNS provider in Kubernetes v1.13 because its modular plugin architecture allows operators to customize resolution behavior without recompiling binaries. When a pod queries my-svc.my-namespace.svc.cluster.local, the request hits the CoreDNS Service on port 53, which load-balances across CoreDNS pods. Each pod runs an identical plugin chain defined in the Corefile.

The kubernetes plugin watches the API server for Service and EndpointSlice objects, maintaining an in-memory zone for cluster.local. This eliminates external database lookups for internal traffic. For any query not matching the cluster zone, the forward plugin proxies the request to upstream resolvers like VPC DNS or public recursive servers. Understanding this split-horizon behavior is critical; if your network policies block egress to upstream DNS IPs, external name resolution will fail even if internal services work perfectly.

Essential Corefile directives

A production-ready Corefile balances functionality with safety. Below is a validated configuration for Kubernetes 1.30+ that includes health checks, caching, and safe forwarding:

<Corefile>
.:53 {
    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
}
</Corefile>
  • errors: Logs malformed packets and plugin failures to stderr for container log aggregation.
  • health: Exposes /health on port 8080 for liveness probes. The lameduck period prevents dropped queries during rolling updates.
  • kubernetes: The pods insecure setting allows DNS-based pod identity verification without strict TLS, suitable for most internal clusters. Use pods verified only if you have automated certificate rotation.
  • forward: Uses the node’s /etc/resolv.conf by default. In cloud environments like AWS EKS or Azure AKS, explicitly specify VPC DNS IPs to avoid circular dependencies.
  • cache: A 30-second TTL reduces API server load and latency for repeated lookups.

How do you customize CoreDNS for multi-cluster or hybrid DNS?

Standard Kubernetes DNS assumes a single flat namespace. Real-world infrastructure often requires resolving names across multiple clusters, legacy on-prem systems, or specific SaaS endpoints. You achieve this by adding zone-specific server blocks to the Corefile rather than modifying the global catch-all.

For example, if your organization uses a private hosted zone internal.corp.np managed by Route53 or BIND, add a dedicated block before the generic .:53 block. This ensures private corporate names never leak to public upstream resolvers, a common compliance requirement for fintech and government projects in Nepal.

<Corefile addition>
internal.corp.np:53 {
    errors
    cache 30
    forward . 10.0.0.2 10.0.1.2 {
        policy sequential
        health_check 5s
    }
}
</Corefile addition>

The policy sequential directive tries upstreams in order, failing over only on error. This differs from the default round-robin behavior and is preferable when one resolver is primary and the other is a disaster recovery target. Always pair custom zones with explicit health checks; silent failures in hybrid DNS are among the hardest incidents to diagnose at 2 AM.

Stub domains vs. full zone delegation

Choose stub domains (forwarding specific zones) over full secondary zone transfers unless you require offline resolution capability. Stub domains reduce operational overhead and sync automatically when upstream records change. Full zone transfers via AXFR add complexity around serial numbers and refresh intervals that rarely justify the benefit in dynamic cloud environments.

1. errors2. health/ready3. kubernetes4. forward5. cache/log← Responds if found← Proxies external
CoreDNS plugin chain executes top-to-bottom; the kubernetes plugin short-circuits internal queries while forward handles external resolution.

How do you troubleshoot CoreDNS latency and NXDOMAIN errors?

DNS issues manifest as application timeouts, not clear error messages. Start by verifying the CoreDNS pods themselves are healthy and receiving traffic. Check the kube-system/coredns deployment replicas and ensure the Service endpoints match running pods.

# Verify CoreDNS pods are running and ready
kubectl get pods -n kube-system -l k8s-app=kube-dns -o wide

# Check CoreDNS logs for SERVFAIL or timeout patterns
kubectl logs -n kube-system -l k8s-app=kube-dns --tail=200 | grep -E "SERVFAIL|timeout|NXDOMAIN"

# Test resolution from inside the cluster
kubectl run tmp-shell --rm -i --tty --image nicolaka/netshoot -- nslookup my-service.my-namespace.svc.cluster.local

If nslookup returns NXDOMAIN for a valid service, verify the service exists in the correct namespace and has active endpoints. Headless services (clusterIP: None) return individual pod IPs instead of a virtual IP; applications expecting a single A record may fail unexpectedly. For latency issues, check the cache plugin metrics via Prometheus. A low cache hit ratio indicates either aggressive TTLs or highly unique query patterns that defeat caching.

Common misconfigurations in 2026

  1. ndots:5 default: Kubernetes sets ndots:5 in pod resolv.conf, causing five unnecessary search domain lookups for external FQDNs. Override this per-deployment with dnsConfig.options: [{name: ndots, value: "2"}] for apps making heavy external calls.
  2. Conntrack exhaustion: High DNS QPS can fill the node conntrack table, dropping legitimate packets. Monitor nf_conntrack_count and increase limits via sysctl if DNS queries spike during deployments.
  3. Missing lameduck: Without the lameduck health check parameter, rolling restarts drop in-flight queries. Always include at least 5 seconds to allow graceful drain.
  4. Upstream loops: Forwarding to /etc/resolv.conf that itself points to the CoreDNS Service IP creates infinite recursion. The loop plugin detects this, but prevention is better than detection.

How does CoreDNS compare to kube-dns and NodeLocal DNSCache?

While CoreDNS is the standard, understanding alternatives helps justify architectural decisions during capacity planning or audit reviews.

FeatureCoreDNSkube-dns (Legacy)NodeLocal DNSCache
ArchitectureSingle binary, plugin chainMultiple containers (kubedns, dnsmasq, sidecar)DaemonSet + CoreDNS per node
ConfigurationUnified CorefileSeparate flags/configmapsCorefile + iptables/nftables rules
Custom ZonesNative plugin supportRequires stubDomains configmapInherits upstream CoreDNS config
Latency ProfileNetwork hop to kube-dns ServiceHigher due to dnsmasq overheadSub-millisecond local resolution
Operational ComplexityLowHigh (deprecated)Medium (iptables management)
Best ForGeneral purpose, hybrid DNSLegacy clusters onlyHigh-QPS, latency-sensitive workloads

NodeLocal DNSCache deserves special mention for high-scale environments. By running a caching resolver on every node, it eliminates conntrack pressure and reduces cross-node DNS traffic by 90%+. However, it adds operational complexity around iptables rules and upgrade coordination. For most teams, optimizing CoreDNS cache size and replica count delivers sufficient performance without the additional moving parts. If you're managing Amazon EKS or GKE, both offer managed NodeLocal implementations that reduce this burden significantly.

Standard CoreDNSPod (Node A)Cross-nodeCoreDNS (Node B)NodeLocal DNSCachePod (Node A)LocalhostCache (Node A)Higher LatencyConntrack Pressure<1ms ResolutionNo Cross-node Traffic
NodeLocal DNSCache eliminates cross-node DNS hops, reducing latency and conntrack table pressure compared to standard centralized CoreDNS.

Secure and Optimize Your Cluster DNS with CoreDNS

Reliable Cluster DNS with CoreDNS requires treating DNS configuration as code, not an afterthought. Version-control your Corefile changes through GitOps workflows, validate syntax with coredns -validate before applying, and monitor cache hit ratios alongside application latency metrics. Security-conscious teams should restrict forward targets to known-good resolvers and enable DNSSEC validation where upstream supports it. If your current setup experiences intermittent resolution failures or lacks observability, audit your plugin chain against the patterns described here. For hands-on implementation support or architecture review tailored to your environment, reach out directly to discuss your specific requirements.

Frequently Asked Questions

CoreDNS is the default DNS server for Kubernetes clusters, replacing kube-dns since version 1.13. It provides service discovery by translating service names to cluster IP addresses using a flexible plugin-based architecture defined in the Corefile configuration.

Apply the official manifest using kubectl apply -f https://raw.githubusercontent.com/coredns/deployment/master/kubernetes/coredns.yaml. Ensure your kubelet --cluster-dns flag points to the CoreDNS Service IP and --cluster-domain matches your configured domain, typically cluster.local.

Yes. CoreDNS offers superior performance, lower memory usage, and extensibility through plugins. Kube-dns is deprecated and no longer maintained, making CoreDNS the mandatory standard for all modern Kubernetes deployments and cluster DNS implementations in 2026.

Edit the coredns ConfigMap in kube-system namespace. Add a new zone block before the forward plugin specifying your custom domain and upstream resolvers. Apply changes with kubectl rollout restart deployment coredns to reload the updated Corefile configuration safely.

Common causes include syntax errors in the Corefile, insufficient memory limits, or missing RBAC permissions. Check logs with kubectl logs -n kube-system -l k8s-app=kube-dns and validate configuration using coredns -conf /etc/coredns/Corefile -validate locally.

Allocate 170Mi requests and 300Mi limits per pod for clusters under 500 nodes. Scale horizontally rather than vertically; add replicas based on query volume. Monitor actual usage via Prometheus metrics coredns_cache_size and process_resident_memory_bytes to right-size resources.

Yes. Use the forward plugin with TLS-enabled upstream resolvers like Quad9 or Cloudflare. Configure dnssec plugin for response validation and cache plugin with denial settings to prevent cache poisoning attacks against your cluster DNS infrastructure effectively.

The cache plugin is enabled by default in standard deployments. Tune it by setting cache duration parameters like cache 3600 for positive responses and cache 300 for negative responses within the relevant zone block inside your Corefile configuration.

Slow queries often result from disabled caching, overloaded CoreDNS pods, or ndots:5 causing excessive lookups. Enable cache plugin, scale CoreDNS replicas, and set ndots:2 in pod dnsConfig to reduce unnecessary search domain queries significantly.

Exec into any running pod and run nslookup kubernetes.default.svc.cluster.local. Verify responses return valid cluster IPs. Use dig +trace for detailed query path analysis and confirm CoreDNS is responding correctly without timeouts or SERVFAIL errors.

No. CoreDNS uses standard DNS over UDP/TCP on port 53. While grpc plugin exists for inter-plugin communication, client-facing cluster DNS resolution relies exclusively on traditional DNS protocols compatible with all container runtimes and operating systems.

Enable prometheus plugin binding to :9153. Scrape metrics endpoint via ServiceMonitor for Grafana dashboards tracking query rate, cache hit ratio, response latency percentiles, and error counts. Alert on sustained p99 latency above 100ms or cache miss rates exceeding 40%.

Yes. Deploy at least two replicas across different nodes using pod anti-affinity rules. Kubernetes Service automatically load-balances DNS queries. For large clusters, use node-local DNSCache alongside CoreDNS to reduce cross-node traffic and improve resilience during rollouts.

Essential plugins include kubernetes for service discovery, forward for upstream resolution, cache for performance, log for debugging, errors for error handling, and prometheus for observability. Avoid loading unnecessary plugins as each adds processing overhead to every DNS query processed.

Use rolling updates with maxUnavailable:0 in deployment strategy. Test new versions in staging first. Validate Corefile compatibility using coredns -validate. Monitor error rates during rollout and maintain previous ReplicaSet for instant rollback if resolution failures occur.