Module #21 · intermediate Article
CoreDNS Architecture: In-Cluster DNS Resolution and Service Record Lookup
CoreDNS runs as a Deployment in `kube-system` and automatically creates DNS records for every Service — pods resolve services using short names within the sa...
4 min read+15 XPPublished 2026-05-09
Quick Answer: CoreDNS runs as a Deployment in kube-system and automatically creates DNS records for every Service — pods resolve services using short names within the same namespace or fully qualified names across namespaces.
Detailed Answer:
# Every pod gets /etc/resolv.conf automatically configured:
kubectl exec -it my-pod -- cat /etc/resolv.conf
# nameserver 10.96.0.10 ← CoreDNS ClusterIP
# search production.svc.cluster.local svc.cluster.local cluster.local
# options ndots:5
# The 'search' domains allow short names to resolve:
# curl my-svc → tries my-svc.production.svc.cluster.local
# curl my-svc.staging → tries my-svc.staging.svc.cluster.local
# curl my-svc.staging.svc.cluster.local → fully qualified, always works
DNS Record Types Created by Kubernetes:
# For a Service named 'my-svc' in namespace 'production':
# A record: my-svc.production.svc.cluster.local → ClusterIP (e.g., 10.96.1.5)
# For a Headless Service (StatefulSet):
# A records per pod:
# postgres-0.postgres.production.svc.cluster.local → 10.0.1.5 (pod IP directly)
# postgres-1.postgres.production.svc.cluster.local → 10.0.1.6
# postgres-2.postgres.production.svc.cluster.local → 10.0.1.7
# For a Service with named ports — SRV records:
# _http._tcp.my-svc.production.svc.cluster.local → port 80
# For ExternalName Service:
# my-ext-svc.production.svc.cluster.local → CNAME → mydb.rds.amazonaws.com
Debugging DNS Inside the Cluster:
# Run a debug pod with DNS tools
kubectl run dnsutils --image=nicolaka/netshoot \
--rm -it --restart=Never -- bash
# Inside the pod:
nslookup my-svc.production.svc.cluster.local
# Server: 10.96.0.10
# Address: 10.96.0.10#53
# Name: my-svc.production.svc.cluster.local
# Address: 10.96.1.5
dig my-svc.production.svc.cluster.local
nslookup kubernetes.default.svc.cluster.local # Should always resolve
# Check CoreDNS is healthy
kubectl get pods -n kube-system -l k8s-app=kube-dns
kubectl logs -n kube-system -l k8s-app=kube-dns
# Check CoreDNS ConfigMap for custom DNS rules
kubectl get configmap coredns -n kube-system -o yaml
Custom DNS Configuration:
# CoreDNS ConfigMap — add custom DNS rules
apiVersion: v1
kind: ConfigMap
metadata:
name: coredns
namespace: kube-system
data:
Corefile: |
.:53 {
errors
health
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
fallthrough in-addr.arpa ip6.arpa
}
# Forward internal company DNS to corporate resolver
forward corp.example.com 10.0.0.1
# Forward everything else to public DNS
forward . 8.8.8.8 8.8.4.4
cache 30
loop
reload
loadbalance
}
The ndots:5 Performance Issue:
# ndots:5 means any hostname with fewer than 5 dots triggers search domain lookups
# curl external-api.example.com triggers:
# 1. external-api.example.com.production.svc.cluster.local (fails)
# 2. external-api.example.com.svc.cluster.local (fails)
# 3. external-api.example.com.cluster.local (fails)
# 4. external-api.example.com (finally resolves — 4 DNS lookups wasted!)
# Fix for pods making many external calls:
spec:
dnsConfig:
options:
- name: ndots
value: "2" # Reduce unnecessary search domain lookups
dnsPolicy: ClusterFirst # Default — use CoreDNS
# Other options: None (custom only), Default (use node DNS), ClusterFirstWithHostNet
Key Takeaway: DNS is the glue of Kubernetes networking — when services can't talk to each other, always verify DNS resolution first with nslookup from inside a pod before investigating network policies or service selectors.
Finished reading?
Mark as complete to claim your +15 XP and track progress.
