DNS in Kubernetes is handled by CoreDNS. It runs as a pod in kube-system and automatically creates DNS records for every Service you create.
Internal DNS in our Voting App
All internal communication uses DNS service names — no hardcoded IPs:
voting-app → redis:6379 (resolves to 10.43.28.68)
voting-app → db:5432 (resolves to 10.43.34.195)
worker → redis:6379 (resolves to 10.43.28.68)
worker → db:5432 (resolves to 10.43.34.195)
result-app → db:5432 (resolves to 10.43.34.195)If a pod restarts and gets a new IP — the Service ClusterIP stays the same, DNS still works, nothing breaks. That’s the whole point of Services and CoreDNS.
The format is always:
<service-name>.<namespace>.svc.cluster.local

Automatic DNS Records
When you apply a Service, CoreDNS automatically registers a DNS name so extra no config needed.
When we ran:
kubectl apply -f redis-service.yamlCoreDNS automatically registered:
redis.voting.svc.cluster.local → 10.43.28.68The format is always:
<service-name>.<namespace>.svc.cluster.localBreaking it down:
redis ← metadata.name in your service YAML
voting ← metadata.namespace in your service YAML
svc ← hardcoded, means it's a Service object
cluster.local ← cluster domain, set at install timeShort Names Also Work
Within the same namespace you can use just the service name — CoreDNS appends the rest automatically via the search domain:
redis ← works inside voting namespace
redis.voting ← works from any namespace
redis.voting.svc.cluster.local ← fully qualified, always worksThis is why voting-app can connect to redis by name and it doesn’t need an IP address. CoreDNS resolves it to the ClusterIP.
Verify DNS from Inside a Pod
Exec into any pod and run nslookup:
k exec -it redis-7c84479b6c-8fzqw -n voting -- /bin/bash
nslookup db
nslookup redisOutput:CoreDNS IP is always 10.43.0.10 — that’s the ClusterIP of the kube-dns service.

resolv.conf Inside a Pod
Every pod gets this automatically injected:
cat /etc/resolv.confsearch voting.svc.cluster.local svc.cluster.local cluster.local
nameserver 10.43.0.10
nameserver 10.43.0.10— CoreDNS ClusterIPsearch voting.svc.cluster.local— allows short names likeredisto resolve
CoreDNS Config
The CoreDNS configuration lives in a ConfigMap:
k get configmap coredns -n kube-system -o yamlKey sections in the Corefile:
.:53 {
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
fallthrough in-addr.arpa ip6.arpa
}
forward . /etc/resolv.conf
}kubernetes cluster.local— handles all.cluster.localDNS lookups, reads from k8s APIforward . /etc/resolv.conf— forwards external DNS queries (google.com etc) to the node’s DNS
Node hostnames are also registered:
NodeHosts: |
172.16.77.10 k3s-cp-01
172.16.77.11 k3s-worker-01
172.16.77.12 k3s-worker-02External DNS
CoreDNS handles internal cluster DNS only. For external DNS we start pointing real domain names at your services we need
- ExternalDNS — watches Services and Ingresses, creates records in Route53/Cloudflare/Azure DNS automatically
- Technitium — manually add
mealie.ash.local → 172.16.77.10 - Ingress + cert-manager — routes external traffic and handles TLS
- Host file – add to our local host file to acesss mealie.ash.local
Quick Reference
# check CoreDNS is running
k get pods -n kube-system | grep coredns
# check CoreDNS config
k get configmap coredns -n kube-system -o yaml
# test DNS from inside a pod
k exec -it <pod> -n <namespace> -- nslookup <service-name>
k exec -it <pod> -n <namespace> -- cat /etc/resolv.conf
# CoreDNS ClusterIP
k get svc kube-dns -n kube-system

