modern
DNS in Kubernetes and Cloud
CoreDNS, service discovery, the ndots problem, and how cloud providers turn DNS into a managed infrastructure layer
Every container starts with a DNS query
In Kubernetes, DNS is not optional infrastructure — it is the service discovery mechanism. When one microservice calls another, the call resolves through DNS. When a pod needs a database, it queries DNS. CoreDNS sits at the center of every Kubernetes cluster, translating service names into cluster IP addresses thousands of times per second.
CoreDNS: the Kubernetes DNS server
CoreDNS has been the default DNS server in Kubernetes since version 1.13 (December 2018), replacing the older kube-dns. It is a CNCF graduated project written in Go, with a plugin-based architecture that makes it extensible.
CoreDNS runs as a Deployment (typically 2 replicas) in the kube-system namespace, exposed via a Service named kube-dns at a well-known ClusterIP (typically 10.96.0.10). The name kube-dns is retained for backward compatibility.
Key plugins
| Plugin | Function |
|---|---|
kubernetes | Serves DNS records for Kubernetes Services and Pods |
forward | Forwards non-cluster queries to upstream resolvers |
cache | Caches DNS responses (default: 30 seconds) |
loop | Detects and breaks DNS forwarding loops |
reload | Automatically reloads config on ConfigMap changes |
autopath | Optimizes search path resolution to reduce query count |
Configuration lives in a ConfigMap containing a Corefile. The kubernetes plugin watches the Kubernetes API and automatically creates DNS records when Services are created, modified, or deleted.
Service discovery via DNS
Kubernetes creates DNS records for Services and Pods automatically:
ClusterIP Services get an A record mapping the service name to the cluster IP: redis-master.default.svc.cluster.local resolves to 10.96.23.45
Headless Services (ClusterIP: None) return individual Pod IPs directly, enabling client-side load balancing. They also create SRV records for named ports.
ExternalName Services create a CNAME pointing to an external hostname, letting cluster workloads reference external services through the same DNS-based discovery pattern.
SRV records provide port discovery: _http._tcp.api.default.svc.cluster.local returns the port number and target hostname for each ready pod — critical for services running on non-standard ports.
Pod DNS configuration
Every Pod gets a /etc/resolv.conf automatically configured by the kubelet:
nameserver 10.96.0.10
search default.svc.cluster.local svc.cluster.local cluster.local
options ndots:5 The dnsPolicy field controls behavior: ClusterFirst (default) sends queries to CoreDNS with non-cluster queries forwarded upstream. Default inherits the node’s DNS config. None requires explicit configuration.
The ndots:5 problem
The default ndots:5 setting means any domain with fewer than 5 dots is treated as a “relative” name and appended to each search domain before the absolute query is tried.
A pod in the production namespace querying api.example.com generates:
1. api.example.com.production.svc.cluster.local -> NXDOMAIN
2. api.example.com.svc.cluster.local -> NXDOMAIN
3. api.example.com.cluster.local -> NXDOMAIN
4. api.example.com. -> SUCCESS A single external DNS lookup generates 4x the queries. With IPv6 (A + AAAA), that becomes 8x. In clusters with thousands of pods making frequent external API calls, this creates massive DNS query amplification.
Mitigations
| Strategy | Impact |
|---|---|
Trailing dot (api.example.com.) | Forces absolute lookup; zero amplification |
| Reduce ndots (set to 1 or 2 in pod dnsConfig) | Fewer search domain iterations for external domains |
| FQDNs for internal services | Avoids search path entirely |
| NodeLocal DNSCache | Per-node caching agent reduces CoreDNS load |
| CoreDNS autopath plugin | Server-side optimization that short-circuits the search path |
| Cluster-proportional autoscaler | Scales CoreDNS replicas based on cluster size |
NodeLocal DNSCache (available since Kubernetes 1.18) runs a DNS caching agent on every node. Pods query the local cache first, avoiding DNAT rules and connection tracking. This reduces DNS latency from 5-20ms to under 1ms for cached entries and prevents conntrack table exhaustion in large clusters.
From kube-dns to CoreDNS
| Timeline | Event |
|---|---|
| K8s 1.0 - 1.10 | kube-dns was default (SkyDNS + dnsmasq + sidecar) |
| K8s 1.11 (June 2018) | CoreDNS became available as alternative |
| K8s 1.13 (December 2018) | CoreDNS replaced kube-dns as default |
| 2024 | kube-dns deprecated in AKS; CoreDNS sole option |
The transition happened because kube-dns relied on three containers including dnsmasq, which had known security vulnerabilities. CoreDNS is a single binary with a plugin architecture, simplifying deployment and troubleshooting.
Cloud DNS services
All major cloud providers offer managed DNS as a core service, turning authoritative DNS into infrastructure you configure through APIs and IaC rather than managing servers.
AWS Route 53
Named after port 53, Route 53 is the most widely used cloud DNS service. Key features include a 100% availability SLA, DNS-based health checks and failover, and eight routing policies (simple, weighted, latency-based, failover, geolocation, geoproximity, multivalue answer, IP-based).
Alias records are Route 53’s signature feature — they point to AWS resources (ELB, CloudFront, S3, API Gateway) with zero query charges, a significant cost advantage for AWS-heavy architectures.
Route 53 also provides Resolver endpoints for hybrid DNS, allowing on-premises networks to resolve AWS-hosted private zones and vice versa.
Google Cloud DNS
Offers global anycast name servers for low-latency resolution, managed DNSSEC at no extra cost, DNS peering for cross-VPC resolution without VPN, and DNS Armor (powered by Infoblox) for threat detection on outbound queries. Pricing starts at $0.20 per zone/month.
Azure DNS
Provides hosting on Azure’s global anycast network, Azure Private DNS zones with automatic VM registration, and Azure DNS Private Resolver for hybrid connectivity. Azure added DNS Security Policy with Threat Intelligence in 2025 for filtering malicious domains at the VNet level.
Cloud vs. traditional DNS
| Feature | Cloud DNS | Traditional (BIND, PowerDNS) |
|---|---|---|
| Infrastructure | Globally distributed anycast, managed | Self-hosted, manual replication |
| Availability | 100% SLA (Route 53) | 99.9-99.99% typical |
| Scaling | Automatic | Manual capacity planning |
| Health checks | Built-in with routing policies | External monitoring required |
| Cost | Pay-per-query + per-zone | Server costs + operations |
| DNSSEC | Managed signing and key rotation | Manual key management |
Private DNS zones
Cloud providers support private DNS zones — DNS records visible only within a VPC or VNet, never exposed to the public internet.
AWS associates private hosted zones with VPCs. Route 53 Resolver endpoints handle hybrid connectivity between on-premises and cloud.
Google Cloud offers private zones, DNS peering for cross-project resolution, and routing policies with health checks for private workloads.
Azure provides Private DNS zones with auto-registration of VM A records and a Private Resolver for conditional forwarding.
Private zones are foundational for split-horizon DNS, where app.company.com resolves to a private IP inside the network and a public IP outside. This pattern is standard in enterprise DNS architectures.
Service discovery beyond Kubernetes
Consul
HashiCorp Consul provides a built-in DNS interface for service discovery that requires no application modification. It listens on port 8600 (to avoid requiring root privileges) and resolves queries under the .consul domain.
Services register with Consul and are discoverable via DNS: web.service.consul returns healthy service instances. Consul integrates with CoreDNS via the forward plugin, allowing Kubernetes pods to discover external services through service-name.consul lookups.
Unlike pure DNS-based discovery, Consul provides health-aware responses — unhealthy service instances are automatically removed from DNS results.
mDNS and DNS-SD
Multicast DNS (RFC 6762) enables zero-configuration name resolution on local networks. It uses multicast address 224.0.0.251 on port 5353 to resolve .local domain names without a central DNS server. Implementations include Apple Bonjour, Avahi (Linux), and native Windows 10+ support.
DNS-Based Service Discovery (RFC 6763) uses standard DNS record types — PTR, SRV, and TXT — to advertise and discover services. Despite the name, DNS-SD works with both multicast and unicast DNS.
These protocols are the backbone of local device discovery, from AirPrint printers to Matter smart home devices.