CKA — CoreDNS
CKA Exam Domain
Services & Networking — 20%
CoreDNS is the cluster’s built-in DNS server, and CKA exam questions often ask you to troubleshoot DNS resolution, inspect the Corefile, or fix a misconfigured CoreDNS setup. Understanding its architecture pays off.
What Is CoreDNS?
CoreDNS is the default DNS server in Kubernetes clusters (since v1.13). It provides name resolution for all Services and Pods in the cluster.
When a Pod needs to reach a Service by name (e.g., my-svc.default.svc.cluster.local), CoreDNS resolves that name to the Service’s ClusterIP.
Key facts:
- Runs as a Deployment in the
kube-systemnamespace - Exposed via a Service named
kube-dns(ClusterIP, typically10.96.0.10) - Configuration stored in a ConfigMap named
coredns - Every Pod’s
/etc/resolv.confpoints to thekube-dnsService IP
CoreDNS Architecture
Pod (/etc/resolv.conf → kube-dns IP)
↓ DNS query
kube-dns Service (ClusterIP)
↓
CoreDNS Pods (Deployment, 2 replicas)
↓ reads
coredns ConfigMap (Corefile)
Components:
| Component | Type | Namespace | Purpose |
|---|---|---|---|
coredns |
Deployment | kube-system | Runs CoreDNS Pods (usually 2 replicas) |
kube-dns |
Service (ClusterIP) | kube-system | Stable IP for DNS queries |
coredns |
ConfigMap | kube-system | Contains the Corefile (configuration) |
Check them:
kubectl get deployment coredns -n kube-system
kubectl get svc kube-dns -n kube-system
kubectl get configmap coredns -n kube-system
The Corefile
The Corefile is the heart of CoreDNS configuration. It’s stored in the coredns ConfigMap.
View the Corefile
kubectl get configmap coredns -n kube-system -o yaml
Default Corefile (Annotated)
.:53 { # Listen on port 53 for all zones
errors # Log errors to stdout
health { # Health check endpoint on :8080/health
lameduck 5s
}
ready # Readiness endpoint on :8181/ready
kubernetes cluster.local in-addr.arpa ip6.arpa {
# Handle DNS for the Kubernetes cluster
pods insecure # Enable Pod DNS records (A records)
fallthrough in-addr.arpa ip6.arpa
ttl 30 # Cache TTL of 30 seconds
}
prometheus :9153 # Metrics endpoint for Prometheus
forward . /etc/resolv.conf {
# Forward external DNS queries to upstream
max_concurrent 1000
}
cache 30 # Cache DNS responses for 30 seconds
loop # Detect and stop forwarding loops
reload # Auto-reload Corefile on changes
loadbalance # Round-robin DNS responses
}
Plugin Breakdown
| Plugin | Purpose |
|---|---|
errors |
Logs errors to stdout |
health |
Exposes health check at :8080/health |
ready |
Exposes readiness check at :8181/ready |
kubernetes |
Enables DNS for Kubernetes Services and Pods |
prometheus |
Exposes metrics at :9153/metrics |
forward |
Forwards non-cluster DNS queries to upstream resolvers |
cache |
Caches DNS responses to reduce load |
loop |
Detects and breaks forwarding loops |
reload |
Automatically reloads when ConfigMap changes |
loadbalance |
Randomizes order of A records (round-robin) |
DNS Record Types
CoreDNS creates different DNS records for different Kubernetes resources:
Service DNS Records
| Record Type | Format | Example |
|---|---|---|
| A record | <svc>.<ns>.svc.cluster.local |
nginx-svc.default.svc.cluster.local → 10.96.1.5 |
| SRV record | _<port-name>._<protocol>.<svc>.<ns>.svc.cluster.local |
_http._tcp.nginx-svc.default.svc.cluster.local |
Pod DNS Records
| Record Type | Format | Example |
|---|---|---|
| A record | <pod-ip-dashed>.<ns>.pod.cluster.local |
10-244-1-5.default.pod.cluster.local |
Headless Service DNS
For headless Services (clusterIP: None), CoreDNS returns A records for each Pod’s IP directly:
my-headless.default.svc.cluster.local → 10.244.1.5, 10.244.2.3, 10.244.3.7
ExternalName Service DNS
For ExternalName Services, CoreDNS returns a CNAME record:
apiVersion: v1
kind: Service
metadata:
name: external-db
spec:
type: ExternalName
externalName: db.external-provider.com
external-db.default.svc.cluster.local → CNAME → db.external-provider.com
Custom DNS Entries
You can customize CoreDNS by editing the coredns ConfigMap.
Stub Domains
Forward queries for a specific domain to a custom DNS server:
.:53 {
# ... existing plugins ...
forward . /etc/resolv.conf
}
company.local:53 {
errors
cache 30
forward . 10.0.0.53 # Corporate DNS server
}
Adding Custom Records
Use the hosts plugin to add static DNS entries:
.:53 {
hosts {
10.0.0.100 custom-app.example.com
10.0.0.101 legacy-db.example.com
fallthrough
}
# ... rest of plugins ...
}
Apply Changes
After editing the ConfigMap:
kubectl edit configmap coredns -n kube-system
CoreDNS automatically picks up changes thanks to the reload plugin (usually within 30 seconds). You can also force a reload by restarting the Pods:
kubectl rollout restart deployment coredns -n kube-system
Troubleshooting CoreDNS
These commands are essential for diagnosing DNS issues:
# Check CoreDNS Pods are running
kubectl get pods -n kube-system -l k8s-app=kube-dns
# Check CoreDNS logs for errors
kubectl logs -n kube-system -l k8s-app=kube-dns
# Test DNS resolution from a debug Pod
kubectl run dnsutils --image=registry.k8s.io/e2e-test-images/agnhost:2.39 \
--command -- sleep infinity
kubectl exec -it dnsutils -- nslookup kubernetes.default
# Check resolv.conf inside a Pod
kubectl exec -it dnsutils -- cat /etc/resolv.conf
# Expected resolv.conf content:
# nameserver 10.96.0.10 ← kube-dns ClusterIP
# search default.svc.cluster.local svc.cluster.local cluster.local
# options ndots:5
# Verify the kube-dns Service
kubectl get svc kube-dns -n kube-system
# Check CoreDNS endpoints
kubectl get endpoints kube-dns -n kube-system
Quick DNS Test
# Resolve a Service name
kubectl exec -it dnsutils -- nslookup nginx-svc.default.svc.cluster.local
# Short name (relies on search domains)
kubectl exec -it dnsutils -- nslookup nginx-svc
Common CoreDNS Issues
CrashLoopBackOff
Symptom: CoreDNS Pods are in CrashLoopBackOff.
Common cause: Loop detection. If the node’s /etc/resolv.conf points to 127.0.0.1 (common on systems running systemd-resolved), CoreDNS detects a forwarding loop and crashes.
Fix: Edit the Corefile’s forward plugin to use a specific upstream DNS instead:
forward . 8.8.8.8 8.8.4.4
DNS Resolution Fails
Symptom: Pods can’t resolve Service names.
Troubleshooting checklist:
- Is CoreDNS running?
kubectl get pods -n kube-system -l k8s-app=kube-dns - Does kube-dns Service have endpoints?
kubectl get endpoints kube-dns -n kube-system - Can the Pod reach kube-dns?
kubectl exec <pod> -- nslookup kubernetes.default - Is the Pod’s
/etc/resolv.confcorrect? Checknameserverpoints to kube-dns IP - Are there NetworkPolicies blocking DNS (port 53)?
Slow DNS Resolution
Symptom: DNS queries take several seconds.
Common causes:
ndots:5setting causes unnecessary search domain lookups for external names- Cache size too small for high-traffic clusters
- Insufficient CoreDNS replicas
Practice Questions
Q1. Where is the CoreDNS configuration stored and how do you view it?
Show Answer
The configuration is stored in a ConfigMap named coredns in the kube-system namespace:
kubectl get configmap coredns -n kube-system -o yaml
The actual configuration is in the Corefile key of the ConfigMap.
Q2. What is the DNS name format for a Service named web-svc in namespace production?
Show Answer
web-svc.production.svc.cluster.local
The full format is: <service-name>.<namespace>.svc.cluster.local
From within the same namespace, you can use the short name web-svc. From another namespace, use web-svc.production.
Q3. CoreDNS Pods are in CrashLoopBackOff. The logs show “Loop detected”. How do you fix it?
Show Answer
The loop plugin detected a DNS forwarding loop — typically because the node’s /etc/resolv.conf points to a local resolver (127.0.0.1) that forwards back to CoreDNS.
Fix by editing the Corefile to use explicit upstream DNS servers:
kubectl edit configmap coredns -n kube-system
Change:
forward . /etc/resolv.conf
To:
forward . 8.8.8.8 8.8.4.4
Then restart CoreDNS: kubectl rollout restart deployment coredns -n kube-system
Q4. How do you test DNS resolution from inside the cluster?
Show Answer
# Launch a debug Pod
kubectl run dnsutils --image=registry.k8s.io/e2e-test-images/agnhost:2.39 \
--command -- sleep infinity
# Test resolution
kubectl exec -it dnsutils -- nslookup kubernetes.default.svc.cluster.local
# Check resolv.conf
kubectl exec -it dnsutils -- cat /etc/resolv.conf
Expected output should show the Service resolving to its ClusterIP.
Q5. What happens when a Pod queries a DNS name like my-svc without the full domain?
Show Answer
The Pod’s /etc/resolv.conf has search domains configured:
search default.svc.cluster.local svc.cluster.local cluster.local
With ndots:5, the resolver appends each search domain in order:
my-svc.default.svc.cluster.local— matches if the Service exists in the same namespacemy-svc.svc.cluster.local— tried next if step 1 failsmy-svc.cluster.local— tried nextmy-svc— absolute query as last resort
This is why short names like my-svc work within the same namespace.