How Does Service Discovery Work in Kubernetes?
Learn how Kubernetes service discovery uses CoreDNS, ClusterIP, and EndpointSlices to route traffic to healthy Pods automatically.
Expected Interview Answer
Kubernetes service discovery works primarily through DNS: every Service gets a stable DNS name of the form `service-name.namespace.svc.cluster.local` resolved by the in-cluster CoreDNS server, so Pods can reach each other by name instead of tracking ever-changing Pod IPs.
When a Service is created, kube-proxy (or an eBPF equivalent like Cilium) programs iptables or IPVS rules on every node so that traffic to the Service’s stable ClusterIP gets load-balanced across the current set of healthy Pod endpoints matching its selector, and an EndpointSlice object tracks that set of Pod IPs in real time as Pods come and go. CoreDNS watches the Kubernetes API and answers `A`/`AAAA` queries for `myservice.myns.svc.cluster.local` with the Service’s stable ClusterIP, and Pods in the same namespace can use the short name `myservice` because of the default search domain suffixes in `/etc/resolv.conf`. A secondary, older mechanism — environment variables like `MYSERVICE_SERVICE_HOST` injected into every Pod at creation time for Services that already existed — still exists for legacy compatibility but only reflects Services present when the Pod started, which is why DNS is the recommended approach for anything dynamic. For headless Services (`clusterIP: None`), DNS instead returns the individual Pod IPs directly rather than a single virtual IP, which is what StatefulSets use to give each Pod a stable, individually addressable DNS name.
- Decouples clients from ever-changing Pod IPs via a stable DNS name
- Load-balances automatically across healthy Pod endpoints
- Works transparently for any Pod in the cluster with no extra client library
- Headless Services enable direct per-Pod addressing for stateful workloads
AI Mentor Explanation
Service discovery is like calling a team by its franchise name — "Mumbai Indians" — rather than by which eleven specific players happen to be on the field this match. A league directory (DNS) always resolves that franchise name to whichever players are actually turning out today, so a broadcaster booking an interview just calls the franchise, never memorizing the current squad list. If a player is injured and substituted mid-tournament, the franchise name still routes correctly to whoever is playing now. The old approach of hardcoding a specific player’s contact card, which goes stale the moment squads rotate, is exactly the environment-variable fallback that DNS replaced.
Step-by-Step Explanation
Step 1
Create the Service
A Service object gets a stable ClusterIP and a selector matching a set of Pod labels.
Step 2
Endpoints tracked
An EndpointSlice is kept updated in real time with the IPs of currently healthy matching Pods.
Step 3
CoreDNS answers queries
CoreDNS resolves service-name.namespace.svc.cluster.local to the Service’s stable ClusterIP.
Step 4
kube-proxy load-balances
iptables/IPVS/eBPF rules route traffic hitting the ClusterIP across the current healthy Pod endpoints.
What Interviewer Expects
- Knowledge that DNS is the primary, recommended service discovery mechanism
- Understanding of the ClusterIP -> EndpointSlice -> Pod IP chain
- Awareness of the legacy environment-variable mechanism and its staleness limitation
- Knowledge of headless Services and their use with StatefulSets
Common Mistakes
- Believing Pods discover each other by hardcoded IP addresses
- Not knowing environment-variable discovery only reflects Services that existed at Pod start
- Confusing a Service’s ClusterIP with an individual Pod’s IP
- Forgetting that headless Services return individual Pod IPs, not a single virtual IP
Best Answer (HR Friendly)
“Inside a cluster, services find each other by name, not by IP address, because Pod IPs change constantly as things restart or scale. Kubernetes runs an internal DNS server that resolves a stable service name to whichever healthy Pods are currently backing it, and it automatically load-balances traffic across them, so our application code just calls “payments-service” and never has to track actual machine addresses.”
Code Example
apiVersion: v1
kind: Service
metadata:
name: payments
namespace: default
spec:
selector:
app: payments
ports:
- port: 80
targetPort: 8080
---
# From another Pod:
# curl http://payments.default.svc.cluster.local
# curl http://payments (same namespace, short name)Follow-up Questions
- What is the difference between a ClusterIP Service and a headless Service for DNS resolution?
- How does an EndpointSlice differ from the older Endpoints object?
- Why is DNS preferred over the legacy Service environment variables?
- How does cross-namespace service discovery change the DNS name used?
MCQ Practice
1. What is the primary mechanism for service discovery inside a Kubernetes cluster?
CoreDNS resolves stable Service DNS names to the Service’s ClusterIP, which kube-proxy load-balances across healthy Pods.
2. What is a key limitation of the legacy environment-variable service discovery mechanism?
Environment variables for Services are injected only at Pod creation time, so Services created afterward are missed, unlike DNS which is always live.
3. What does DNS return for a headless Service (clusterIP: None)?
Headless Services skip the virtual ClusterIP and let DNS return each backing Pod’s IP directly, used by StatefulSets for stable per-Pod addressing.
Flash Cards
What is the primary service discovery mechanism in Kubernetes? — DNS, via CoreDNS resolving a stable Service name to its ClusterIP.
What DNS name format does a Service get? — service-name.namespace.svc.cluster.local
What tracks which Pod IPs currently back a Service? — An EndpointSlice, updated in real time.
What does a headless Service’s DNS return? — Individual Pod IPs directly, instead of one virtual ClusterIP.