
September 11, 2026
12 min read
By Kokil Thapa | Last reviewed: September 2026
Every pod in a Kubernetes cluster needs a reliable way to turn api.default.svc.cluster.local into an IP address. That job belongs to cluster DNS with CoreDNS, the default in-cluster resolver since Kubernetes 1.13. When DNS breaks, microservices cannot talk, health checks fail, and deployments look fine on paper but stall in production. This guide walks through how CoreDNS fits the cluster, how to deploy and tune it, and how to fix the failures I have seen on real client infrastructure. If you are new to name resolution itself, start with our practical guide to how DNS works before diving into cluster internals.
kube-system, reads a Corefile for zone rules, and forwards external queries to upstream resolvers configured on your nodes.What is cluster DNS with CoreDNS in Kubernetes?
CoreDNS is a flexible, plugin-driven DNS server written in Go. In Kubernetes it replaces the older kube-dns stack. The control plane still stores service and endpoint data in etcd. CoreDNS watches the API and builds records on the fly.
A typical query path looks like this. A pod asks its local resolver at 10.96.0.10 (the cluster IP of the kube-dns Service). CoreDNS receives the query, matches a zone in the Corefile, and returns an A record, a CNAME, or an NXDOMAIN.
Two DNS names matter for every workload. Short names like mysql resolve inside the same namespace. Fully qualified names like mysql.database.svc.cluster.local work across namespaces. The cluster domain defaults to cluster.local. You can change it, but most managed platforms keep the default.
CoreDNS also supports pod-level DNS records when the pod plugin is enabled. That gives you addresses like 10-244-1-5.default.pod.cluster.local. Many teams disable this for smaller zone files and faster lookups. For background on record types, see our post on DNS record types explained.
Core components you should know
- Corefile — ConfigMap in
kube-systemthat defines zones and plugins. - coredns Deployment — Usually two or more replicas for HA.
- kube-dns Service — Stable ClusterIP every pod uses via
/etc/resolv.conf. - NodeLocal DNSCache — Optional daemonset that caches on each node (common on large clusters).
The relationship between CoreDNS and etcd is indirect. CoreDNS never reads etcd directly. It uses the Kubernetes API, which is backed by etcd as described in our etcd in Kubernetes guide. That separation keeps DNS logic in one place and cluster state in another.
How do you deploy CoreDNS in a Kubernetes cluster?
Managed clusters on GKE, EKS, and AKS ship CoreDNS by default. Self-managed clusters on Ubuntu need explicit installation. The steps below work on kubeadm-style setups running Kubernetes 1.28 or later.
- Confirm no legacy kube-dns pods remain:
kubectl get pods -n kube-system -l k8s-app=kube-dns. - Apply the upstream manifest or your distro package:
kubectl apply -f https://github.com/coredns/deployment/raw/master/kubernetes/coredns.yaml.sed(adjust for your cluster CIDR). - Verify the Deployment:
kubectl -n kube-system get deploy coredns. - Check the ConfigMap:
kubectl -n kube-system get configmap coredns -o yaml. - Run a test pod and resolve a Service:
kubectl run -it --rm dns-test --image=busybox:1.36 --restart=Never -- nslookup kubernetes.default.
On bare-metal Ubuntu nodes I maintain for clients, I align node resolvers first. Broken upstream DNS on the host breaks CoreDNS forwarding. Our Ubuntu DNS configuration guide covers systemd-resolved and /etc/resolv.conf pitfalls that propagate into pods.
Default Corefile for a standard cluster
Most clusters start with a Corefile like this. Edit the ConfigMap, then roll the Deployment.
.: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
}
Each block is a server block listening on port 53. The kubernetes plugin watches Services and Endpoints. The forward plugin sends external queries to the node's /etc/resolv.conf inside the CoreDNS pod. After editing, restart pods or rely on the reload plugin for a graceful reload.
kubectl -n kube-system rollout restart deployment/coredns
kubectl -n kube-system rollout status deployment/coredns
For multi-cluster GitOps workflows, pin the CoreDNS manifest in Git and sync with Argo CD. Patterns for that appear in our multi-cluster Kubernetes across clouds article. Treat DNS config like any other cluster baseline.
CoreDNS needs RBAC to list and watch Services, Endpoints, and Namespaces. Restricting those permissions breaks resolution silently. Our Kubernetes RBAC guide explains how to audit ServiceAccount bindings without over-tightening system components.
How does CoreDNS resolve service names inside a cluster?
Resolution follows predictable search-path rules. When a pod queries api, the stub resolver tries suffixes from dnsConfig or the default search list. With ndots:5, names with fewer than five dots get search domains appended first.
The default search path looks like this:
nameserver 10.96.0.10
search default.svc.cluster.local svc.cluster.local cluster.local
options ndots:5
CoreDNS receives api.default.svc.cluster.local after search expansion. The kubernetes plugin matches the zone cluster.local. It returns the ClusterIP for a ClusterIP Service. For headless Services it returns pod IPs from Endpoints or EndpointSlices.
Headless vs ClusterIP behaviour
A ClusterIP Service gets one stable virtual IP. DNS returns that IP regardless of which pods are ready. A headless Service (clusterIP: None) returns A records for each ready endpoint. StatefulSets depend on this for stable network identity per pod.
ExternalName Services return CNAME records pointing outside the cluster. That is useful for aliasing managed databases without hard-coding IPs. Cross-cloud setups often combine this with external DNS as covered in our cross-cloud DNS and traffic routing post.
CoreDNS exposes Prometheus metrics on port 9153 when the prometheus plugin is enabled. Watch coredns_dns_requests_total and coredns_forward_healthcheck_broken_total for early warning signs. A spike in NXDOMAIN often means a mis-typed Service name or a namespace mismatch.
CoreDNS vs kube-dns: which should you use in 2026?
kube-dns is deprecated. No new clusters should run it. CoreDNS is the only supported in-cluster DNS for current Kubernetes releases. If you still run kube-dns on an older cluster, plan migration before your control plane upgrade forces it.
| Criteria | CoreDNS | kube-dns (legacy) |
|---|---|---|
| Architecture | Single binary, plugin chain in Corefile | dnsmasq sidecar + kubedns container |
| Config model | Corefile zones, hot reload | ConfigMap with limited knobs |
| Observability | Native Prometheus plugin | Requires sidecar scraping |
| Custom zones | file, rewrite, template plugins | Harder to extend cleanly |
| Kubernetes support | Default since 1.13, required on modern versions | Removed from current docs |
| Performance tuning | cache, loadbalance, NodeLocal DNSCache | dnsmasq cache only |
The verdict is straightforward. Use CoreDNS everywhere. Migrate legacy kube-dns during your next maintenance window. The official Kubernetes documentation at kubernetes.io/docs/concepts/services-networking/dns-pod-service/ describes current behaviour and naming conventions.
For teams comparing in-cluster DNS with a standalone BIND server, the trade-off is scope. BIND excels at authoritative zones for public domains. CoreDNS excels at dynamic Kubernetes service discovery. Many production stacks run both layers. Our BIND DNS server on Linux guide covers the authoritative side when you need it.
How do you configure custom DNS zones with CoreDNS?
Production apps often need stub zones for internal domains, split-horizon forwarding, or ad-block style rewrites. CoreDNS handles this with extra server blocks in the Corefile.
Forward an internal domain to corporate DNS
Suppose your company uses corp.example.com on-premises. Add a block that forwards only that suffix:
corp.example.com:53 {
errors
cache 30
forward . 10.10.0.53 10.10.0.54
}
Keep the default .:53 block for cluster.local and upstream internet resolution. Order matters when zones overlap. More specific zones should appear as separate server blocks.
Override a hostname with the hosts plugin
hosts /etc/coredns/hosts.db {
fallthrough
}
Mount the hosts file via a ConfigMap volume. This is handy for pinning legacy dependencies during migration. Prefer Kubernetes Services once the dependency runs inside the cluster.
Custom dnsConfig on a Pod
Some workloads need different upstreams or search paths. Set dnsPolicy: None and define dnsConfig explicitly:
apiVersion: v1
kind: Pod
metadata:
name: custom-dns-pod
spec:
dnsPolicy: None
dnsConfig:
nameservers:
- 10.96.0.10
searches:
- myapp.svc.cluster.local
- svc.cluster.local
options:
- name: ndots
value: "2"
containers:
- name: app
image: myapp:1.0
Lowering ndots reduces unnecessary search-path queries. That cuts latency for external API calls. Validate with kubectl exec and cat /etc/resolv.conf before rolling to production.
On booking platforms like Adventure Third Pole Trek, microservices call payment and SMS APIs by public hostname. Correct forward rules prevent those calls from looping inside the cluster. Test external resolution from a debug pod after every Corefile change.
How do you troubleshoot CoreDNS when cluster DNS fails?
DNS failures show up as connection timeouts, not always as clear DNS errors. Application logs say "connection refused" or "no such host" while the Service and pods look healthy. Work through the checklist below before restarting random components.
- Check CoreDNS pod health:
kubectl -n kube-system get pods -l k8s-app=kube-dns— labels still say kube-dns even though the workload is CoreDNS. - Review logs:
kubectl -n kube-system logs -l k8s-app=kube-dns --tail=100. Look for loop detection, permission denied, or forward timeouts. - Test from a debug pod:
kubectl run -it --rm debug --image=nicolaka/netshoot --restart=Never -- dig @10.96.0.10 kubernetes.default.svc.cluster.local. - Verify kube-dns Service endpoints match running CoreDNS pods.
- Confirm node upstream DNS works on the host with
dig google.combefore blaming CoreDNS. - Check for CoreDNS loop: the
loopplugin detects when forwarded queries return to CoreDNS. Fix by pointingforwardat real upstreams, not127.0.0.1.
A common mistake on Ubuntu nodes: /etc/resolv.conf points to 127.0.0.53 (systemd-resolved). CoreDNS pods inherit that and create a loop or timeout. Set node-level resolvers to real upstream IPs, or use the forward plugin with explicit IPs instead of /etc/resolv.conf.
Scale-related problems need horizontal fixes. Increase CoreDNS replicas when CPU throttling appears. Add Pod anti-affinity so replicas land on different nodes. For clusters above roughly 200 nodes, deploy NodeLocal DNSCache to cut cross-node traffic to the kube-dns Service.
When you manage many clusters through Rancher or similar tools, DNS baselines drift fast. Standardise the Corefile template across environments. Our Rancher multi-cluster management guide covers fleet-wide config patterns that apply here.
If you need regex testing for rewrite rules before applying them, the regex tester tool on this site helps validate patterns offline. CoreDNS rewrite mistakes are easier to catch before they hit production.
For deeper CoreDNS plugin reference, the project documentation at coredns.io/plugins/ is the authoritative source. The CNCF project page at cncf.io/projects/coredns tracks release cadence and governance.
Key Takeaways
- Cluster DNS with CoreDNS is the default Kubernetes resolver—plan every deployment around a healthy Corefile and at least two replicas.
- Internal names resolve through the
kubernetesplugin; external names depend on correctforwardupstreams on your nodes. - Migrate legacy kube-dns before upgrading Kubernetes; CoreDNS is the only supported path in 2026.
- Fix Ubuntu/systemd-resolved loop issues by pointing forward at real upstream IPs, not
127.0.0.53. - Use Prometheus metrics and dig from a netshoot pod to separate Service misconfig from DNS infrastructure failure.
- Pin CoreDNS manifests in Git for multi-cluster fleets so DNS config does not drift silently.
People Also Ask
What IP address do pods use for DNS in Kubernetes?
Pods send queries to the ClusterIP of the kube-dns Service in kube-system. That IP appears as the nameserver in /etc/resolv.conf. It is typically something like 10.96.0.10, but the exact address depends on your Service CIDR. Run kubectl get svc kube-dns -n kube-system to confirm.
Can you run CoreDNS outside Kubernetes?
Yes. CoreDNS is a general-purpose DNS server. Many teams run it on bare metal or at the edge. Inside Kubernetes it adds the kubernetes plugin for automatic service record generation. Outside the cluster you would use file, etcd, or other plugins instead.
Why do I get NXDOMAIN for a service that exists?
Most often the query uses the wrong namespace or an incomplete search path. A pod in staging asking for api resolves api.staging.svc.cluster.local, not api.production.svc.cluster.local. Use the fully qualified name to test, then fix the Service name or namespace in application config.
Does CoreDNS work with IPv6 clusters?
Yes. Enable the ip6.arpa reverse zone in the Corefile alongside in-addr.arpa for IPv4. Dual-stack clusters need dual-stack Services and EndpointSlices. Verify AAAA records with dig AAAA from a debug pod before declaring IPv6 ready.
Build reliable cluster DNS from day one
Cluster DNS with CoreDNS is easy to ignore until it breaks a release. Treat the Corefile, node resolvers, and RBAC as first-class infrastructure. Test resolution after every platform upgrade and every network change. If you are standing up Kubernetes for a new product—or fixing DNS on an existing fleet—Linux system administration support and our ongoing maintenance services cover deployment, tuning, and incident response. For greenfield application work on top of a solid cluster, see enterprise application development. Ready to talk through your setup? Contact us with your cluster size and distro—we will map a practical DNS baseline you can ship this week.
Frequently Asked Questions
0 Comments
Leave a comment
Your email is not published. Comments appear once they have been read. Sign in to have your details filled in.

