How does service discovery/DNS work inside a Kubernetes cluster?

6 minintermediatednscorednsservice-discovery

Quick Answer

Kubernetes runs an internal DNS service (CoreDNS, in modern clusters) that automatically creates a DNS record for every Service, following the pattern `<service-name>.<namespace>.svc.cluster.local` — a Pod can reach a Service in its own namespace by its short name alone, or fully-qualified across namespaces. This means applications never need to hardcode IP addresses or discover peers through an external registry — DNS resolution, backed by Kubernetes's own cluster state, is the built-in service discovery mechanism.

Detailed Answer

The DNS naming pattern

Every Service automatically gets a DNS record following a predictable pattern:

<service-name>.<namespace>.svc.cluster.local
# A Service named "backend-api" in namespace "production"
# is resolvable at:
backend-api.production.svc.cluster.local

From within the same namespace, the short name alone resolves correctly (http://backend-api), because a Pod's DNS search domains include its own namespace — this is why application configuration inside a cluster almost never needs a fully-qualified name, just the plain Service name, as long as the caller and the Service are in the same namespace. Calling across namespaces requires at least backend-api.production (namespace included), or the fully-qualified form.

CoreDNS — the component that answers these queries

Modern Kubernetes clusters run CoreDNS (the successor to the older kube-dns) as a cluster add-on, typically itself a Deployment with a few replicas for availability, exposed via its own Service (usually named kube-dns for historical compatibility, even though it's running CoreDNS). Every Pod's /etc/resolv.conf is automatically configured (by the kubelet) to send DNS queries to CoreDNS's ClusterIP, with the appropriate search domains appended.

# Inside a Pod, this is what gets auto-configured:
cat /etc/resolv.conf
# nameserver 10.96.0.10          <- CoreDNS's Service ClusterIP
# search default.svc.cluster.local svc.cluster.local cluster.local

What gets a DNS record, and what doesn't

  • Every Service gets a DNS A/AAAA record resolving to its ClusterIP (or, for a headless Service, resolving directly to its backing Pods' individual IPs — see that question).
  • Pods themselves can optionally get individual DNS records too (if subdomain and a headless Service are configured — mainly relevant for StatefulSets, where individually addressing web-0 vs web-1 matters).
  • Ordinary Pods (not part of a headless-Service-backed StatefulSet) don't get an individually resolvable DNS name by default — you address them collectively, through their Service.

Why this is the "built-in service discovery" story

Rather than requiring applications to register themselves with, and query, a separate external service registry (like Consul, or a hand-rolled database of "which host runs which service"), Kubernetes uses its own control plane's already-authoritative knowledge of every Service and its endpoints to answer DNS queries directly and automatically. An application only needs to know one thing at deploy time — the Service's name — and DNS plus the Service abstraction together handle everything about which actual Pod IPs currently back it, with zero application-level service-registry code required.

A common practical gotcha

DNS resolution inside a Pod has a real (if usually small) latency cost, and some language runtimes' default DNS resolvers cache results in ways that don't always respect TTLs correctly, or don't retry properly against multiple nameserver entries — this occasionally causes subtle connectivity issues after a Service's backing Pods change, and is worth knowing as a troubleshooting angle when "everything looks fine in Kubernetes but the app still can't reach its dependency" comes up.