Kubernetes Service Discovery and DNS: The Phone Book of Your Cluster 📞
Imagine you just moved to a giant apartment building with thousands of people. How do you find your friend’s apartment? You don’t memorize every room number—you just look them up in the building directory!
In Kubernetes, Service Discovery and DNS is exactly that directory. Your apps (Pods) don’t need to remember where other apps live. They just ask the directory, and it tells them!
The Big Picture: Why Do We Need This?
Think about it:
- Pods come and go like people moving in and out of apartments
- Each Pod gets a new address (IP) when it starts
- How can apps find each other if addresses keep changing?
Answer: We give apps a permanent name instead of a changing address. DNS translates that name into the current address. Simple!
graph TD A["Your App"] -->|"Hey, where is database?"| B["DNS / CoreDNS"] B -->|"It's at 10.96.45.12!"| A A -->|Connects| C["Database Pod"]
1. Service Discovery and DNS: The Basics
What is Service Discovery?
Service Discovery = Finding other apps automatically without hardcoding addresses.
Real-life example:
- You want pizza 🍕
- You don’t memorize the pizza shop’s phone number
- You search “pizza near me” and get the number
- That’s service discovery!
In Kubernetes:
# Your app just uses the name
apiVersion: v1
kind: Pod
spec:
containers:
- name: myapp
env:
- name: DB_HOST
value: "my-database" # Name, not IP!
When your app connects to my-database, Kubernetes DNS automatically finds the right Pod!
How DNS Works in Kubernetes
Every Service gets a DNS name automatically:
<service-name>.<namespace>.svc.cluster.local
Example:
- Service name:
my-database - Namespace:
production - Full DNS name:
my-database.production.svc.cluster.local
Shortcut: If you’re in the same namespace, just use my-database!
2. CoreDNS Configuration: The Brain Behind DNS
What is CoreDNS?
CoreDNS is the phone operator of your cluster. It answers all DNS questions.
graph TD A["Pod asks: Where is my-service?"] --> B["CoreDNS"] B --> C["Looks up Service IP"] C --> D["Returns: 10.96.45.12"] D --> A
The Corefile: CoreDNS Settings
CoreDNS uses a config file called Corefile. Think of it as the operator’s instruction manual.
.:53 {
errors
health
kubernetes cluster.local {
pods insecure
fallthrough in-addr.arpa
}
forward . /etc/resolv.conf
cache 30
loop
reload
loadbalance
}
What each part does:
| Setting | What it Does |
|---|---|
errors |
Log errors |
health |
Health check endpoint |
kubernetes |
Handle cluster DNS |
forward |
Send unknown queries outside |
cache 30 |
Remember answers for 30 seconds |
loadbalance |
Spread requests evenly |
Customizing CoreDNS
Want to add a custom DNS entry? Edit the ConfigMap:
kubectl edit configmap coredns -n kube-system
Example: Add custom host
hosts {
192.168.1.100 mycompany.internal
fallthrough
}
3. DNS Policies: Who Can Ask What?
What are DNS Policies?
DNS Policy controls how a Pod finds DNS servers. It’s like choosing which phone book to use.
The Four DNS Policies
graph TD A["DNS Policies"] --> B["Default"] A --> C["ClusterFirst"] A --> D["ClusterFirstWithHostNet"] A --> E["None"]
1. ClusterFirst (Most Common)
- First ask CoreDNS
- If not found, ask outside DNS
- Best for most apps
apiVersion: v1
kind: Pod
spec:
dnsPolicy: ClusterFirst # Default!
2. Default
- Use the node’s DNS settings
- Skips cluster DNS entirely
3. ClusterFirstWithHostNet
- For Pods using host network
- Still uses cluster DNS first
4. None
- You provide ALL DNS settings
- Maximum control
apiVersion: v1
kind: Pod
spec:
dnsPolicy: None
dnsConfig:
nameservers:
- 8.8.8.8
searches:
- my.dns.search
4. DNS Record Generation: Automatic Name Tags
How Kubernetes Creates DNS Records
Every time you create a Service, Kubernetes automatically creates DNS records. Magic! ✨
Types of DNS Records
A Records (Address Records)
- Maps name → IP address
my-service.default.svc.cluster.local → 10.96.45.12
SRV Records (Service Records)
- Maps name → port + protocol
_http._tcp.my-service.default.svc.cluster.local
# Service with named port
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
ports:
- name: http # This name matters!
port: 80
SRV record created:
_http._tcp.my-service.default.svc.cluster.local
→ 0 0 80 my-service.default.svc.cluster.local
Headless Services: Direct Pod Names
Normal Service → One IP for all Pods Headless Service → Each Pod gets its own DNS name!
apiVersion: v1
kind: Service
metadata:
name: my-headless
spec:
clusterIP: None # Makes it headless!
selector:
app: myapp
DNS records for headless:
pod-name.my-headless.namespace.svc.cluster.local
Perfect for databases where you need specific Pods!
5. Endpoints and EndpointSlices: The Address Book
What are Endpoints?
Endpoints are the actual addresses behind a Service. When you create a Service, Kubernetes creates Endpoints automatically.
graph TD A["Service: my-app"] --> B["Endpoints"] B --> C["Pod 1: 10.1.1.5"] B --> D["Pod 2: 10.1.1.6"] B --> E["Pod 3: 10.1.1.7"]
View Endpoints:
kubectl get endpoints my-service
Output:
NAME ENDPOINTS
my-service 10.1.1.5:80,10.1.1.6:80,10.1.1.7:80
EndpointSlices: The Better Address Book
Problem: With thousands of Pods, one Endpoints object gets HUGE!
Solution: EndpointSlices break it into smaller chunks (max 100 addresses each).
apiVersion: discovery.k8s.io/v1
kind: EndpointSlice
metadata:
name: my-service-abc12
labels:
kubernetes.io/service-name: my-service
endpoints:
- addresses:
- "10.1.1.5"
conditions:
ready: true
Benefits of EndpointSlices:
- Smaller updates (only changed slice)
- Faster propagation
- Less memory usage
- Scales to thousands of Pods
6. Service Topology and Routing: Smart Traffic Direction
What is Service Topology?
Instead of sending traffic anywhere, topology-aware routing sends it to the closest Pod. Like choosing the pizza shop nearest to you!
Topology Keys (Deprecated but Good to Know)
apiVersion: v1
kind: Service
spec:
topologyKeys:
- "kubernetes.io/hostname" # Same node first
- "topology.kubernetes.io/zone" # Same zone next
- "*" # Anywhere as fallback
Topology Aware Hints (The New Way!)
apiVersion: v1
kind: Service
metadata:
annotations:
service.kubernetes.io/topology-mode: Auto
spec:
selector:
app: myapp
How it works:
graph TD A["Request from Zone-A"] --> B{Topology Check} B -->|Has Pod in Zone-A?| C["Route to Zone-A Pod"] B -->|No Pod in Zone-A| D["Route to any Zone"]
Benefits:
- Lower latency (closer = faster)
- Reduced network costs
- Better performance
Internal vs External Traffic Policy
Internal Traffic Policy:
spec:
internalTrafficPolicy: Local # Only same-node Pods
External Traffic Policy:
spec:
externalTrafficPolicy: Local # Preserve client IP
7. Load Balancer Configuration: Sharing the Work
What is a LoadBalancer Service?
It’s a Service that gets a real, external IP from your cloud provider. Anyone on the internet can reach it!
apiVersion: v1
kind: Service
metadata:
name: my-public-app
spec:
type: LoadBalancer
selector:
app: webapp
ports:
- port: 80
targetPort: 8080
Load Balancer Annotations
Each cloud provider has special settings:
AWS:
metadata:
annotations:
service.beta.kubernetes.io/aws-load-balancer-type: nlb
service.beta.kubernetes.io/aws-load-balancer-internal: "true"
GCP:
metadata:
annotations:
cloud.google.com/load-balancer-type: Internal
Azure:
metadata:
annotations:
service.beta.kubernetes.io/azure-load-balancer-internal: "true"
Health Checks
Load balancers need to know if Pods are healthy:
spec:
ports:
- port: 80
targetPort: 8080
healthCheckNodePort: 30000 # For externalTrafficPolicy: Local
Load Balancer IP
Want a specific IP? Request it!
spec:
type: LoadBalancer
loadBalancerIP: 203.0.113.10 # Your static IP
Putting It All Together: A Complete Example
Let’s create a web app with database, using everything we learned:
# Database Service (Headless for StatefulSet)
apiVersion: v1
kind: Service
metadata:
name: postgres
spec:
clusterIP: None
selector:
app: postgres
ports:
- port: 5432
---
# Web App Service (Internal)
apiVersion: v1
kind: Service
metadata:
name: webapp
annotations:
service.kubernetes.io/topology-mode: Auto
spec:
selector:
app: webapp
ports:
- port: 80
targetPort: 8080
---
# Public LoadBalancer
apiVersion: v1
kind: Service
metadata:
name: webapp-public
spec:
type: LoadBalancer
externalTrafficPolicy: Local
selector:
app: webapp
ports:
- port: 443
targetPort: 8080
What happens:
- Web app connects to
postgres(DNS resolves it) - Internal traffic uses topology hints (fast!)
- External users hit the LoadBalancer
- Client IPs are preserved
Quick Reference: DNS Name Formats
| What | DNS Name |
|---|---|
| Service | <svc>.<ns>.svc.cluster.local |
| Pod (headless) | <pod>.<svc>.<ns>.svc.cluster.local |
| SRV record | _<port>._<proto>.<svc>.<ns>.svc.cluster.local |
You Did It! 🎉
You now understand:
- âś… How Pods find each other (Service Discovery)
- ✅ CoreDNS as the cluster’s phone operator
- âś… DNS Policies for different needs
- âś… Automatic DNS record creation
- âś… Endpoints and EndpointSlices
- âś… Smart routing with topology
- âś… LoadBalancer configuration
Remember: In Kubernetes, use names, not IPs. Let DNS do the hard work!
Next: Practice what you learned in the Interactive Lab!
