Fix CoreDNS When Service Names Stop Resolving
Pods in namespace `dns-check` can reach the `catalog` Service by IP, but `catalog.dns-check.svc.cluster.local` no longer resolves after a CoreDNS configuration change. A BusyBox Pod named `check` is available for testing. The Service and application are healthy.
Live lab access
This scenario is included in Free Practice. Choose from 6 fixed labs with 5 shared sessions per week, automatic grading, hints, solutions, AI Lab Coach and saved progress.
Create an account for this free lab →
Explore the six free labs with AI Lab Coach →
Read the brief on any device. Use a desktop or laptop for the terminal lab. Nothing starts until you choose Start.
The task
Pods in namespace dns-check can reach the catalog Service by IP, but catalog.dns-check.svc.cluster.local no longer resolves after a CoreDNS configuration change. A BusyBox Pod named check is available for testing. The Service and application are healthy.
Requirements
1. Diagnose and correct the cluster-domain configuration in the coredns ConfigMap in kube-system.
2. Make the running CoreDNS deployment use the corrected configuration. Preserve its other plugins and upstream forwarding.
3. From Pod check, verify DNS resolution and HTTP access to catalog.dns-check.svc.cluster.local.
4. Write only the catalog Service's ClusterIP to /root/catalog-ip.txt.
Fix CoreDNS; do not change the Service, application, test Pod, or inject static host records.
Original Prepium guide · Written for Kubernetes v1.35 and checked against the official documentation on 6 October 2026. Use a disposable practice cluster. It edits cluster-wide DNS, so never use a shared cluster.
How CoreDNS decides which names it answers, and how to debug a broken lookup
Pods send DNS queries to the kube-dns Service, which fronts the CoreDNS Pods in kube-system. CoreDNS reads its Corefile from the coredns ConfigMap. In that file the kubernetes plugin answers for the cluster domain and forward sends everything else upstream. When a name stops resolving, work out which path it takes and test each one from inside a Pod.
Pod /etc/resolv.conf ──→ kube-dns Service ──→ CoreDNS Pods (kube-system)
│
Corefile in ConfigMap coredns ├─ kubernetes <cluster domain> ... → Service and Pod records
└─ forward . /etc/resolv.conf → upstream resolvers
1. Read the Corefile before touching anything
kubectl -n kube-system get configmap coredns -o jsonpath='{.data.Corefile}'
kubectl -n kube-system get configmap coredns -o jsonpath='{.data.Corefile}' > Corefile.bak
kubectl -n kube-system get pods -l k8s-app=kube-dns
kubectl -n kube-system get endpointslice -l kubernetes.io/service-name=kube-dns
A typical server block starts with .:53 and lists plugins such as errors, health, kubernetes, forward, cache and reload. The zones after the word kubernetes are the zones that plugin is authoritative for: first the cluster domain (cluster.local by default, matching the kubelet's cluster domain), then in-addr.arpa ip6.arpa for reverse lookups. The backup file is your undo button.
2. Build a known-good baseline
kubectl create namespace prepium-tutorial
kubectl -n prepium-tutorial create deployment ledger --image=nginx:1.27-alpine
kubectl -n prepium-tutorial expose deployment ledger --port=8080 --target-port=80
kubectl apply -f https://k8s.io/examples/admin/dns/dnsutils.yaml
kubectl exec dnsutils -- cat /etc/resolv.conf
kubectl exec dnsutils -- nslookup ledger.prepium-tutorial.svc.cluster.local
kubectl exec dnsutils -- nslookup kubernetes.io
The official dnsutils Pod lives in default, so its search list begins with default.svc.cluster.local and the bare name ledger would miss. Use service.namespace.svc.cluster-domain, or at least ledger.prepium-tutorial. The first lookup should match the CLUSTER-IP of kubectl -n prepium-tutorial get svc ledger; the second proves the upstream path works.
3. Break the upstream path on purpose
Edit the ConfigMap and change only the forward line so it points at an address with no resolver behind it, such as 192.0.2.53 from the range reserved for documentation:
kubectl -n kube-system edit configmap coredns
# forward . /etc/resolv.conf becomes forward . 192.0.2.53
The reload plugin picks up the change by itself (allow up to two minutes), or kubectl -n kube-system rollout restart deployment coredns replaces the Pods at once. Repeat both lookups. ledger still resolves, because the kubernetes plugin answers it locally; kubernetes.io now fails, usually after a pause. That split is the core diagnostic: external names broken points at forward; cluster names broken too points at the kubernetes line, the CoreDNS Pods or the kube-dns endpoints.
4. Restore and confirm
kubectl -n kube-system create configmap coredns --from-file=Corefile=Corefile.bak \
--dry-run=client -o yaml | kubectl apply -f -
kubectl -n kube-system rollout restart deployment coredns
kubectl -n kube-system rollout status deployment coredns
kubectl -n kube-system logs -l k8s-app=kube-dns --tail=20
kubectl exec dnsutils -- nslookup kubernetes.io
Read the logs after every Corefile change: if a new Corefile fails to load, the reload plugin keeps the old configuration running and only prints an error.
Common mistakes
- Testing a short Service name from another namespace. It returns NXDOMAIN although DNS is healthy, because the search list comes from the client Pod's namespace.
- Testing seconds after editing the ConfigMap. The old behaviour persists until the reload interval passes, so a correct fix looks wrong.
- Blaming DNS when the Service has no ready backends. The name still resolves to the ClusterIP but HTTP fails; check EndpointSlices first.
- Assuming silence means success. A Corefile that does not parse leaves the previous one running, with only a log line as evidence.
| Example check | Evidence |
|---|---|
| CoreDNS is serving | Pods with k8s-app=kube-dns are Ready and the kube-dns EndpointSlice lists their addresses |
| Cluster path works | nslookup of the full Service name returns the Service's ClusterIP |
| Upstream path works | An external name resolves from the same debug Pod |
| Config applied cleanly | No plugin or parse errors in the CoreDNS logs after the change |
Cleanup: restore the Corefile from Corefile.bak if you have not already, then run kubectl delete pod dnsutils and kubectl delete namespace prepium-tutorial. References: Debugging DNS Resolution, Customizing DNS Service, DNS for Services and Pods, CoreDNS kubernetes plugin. Next, try Service selector troubleshooting or internal and LoadBalancer Services.
Practice scope
This additional curriculum lab is available in single-task practice with the existing 12-minute limit. Its alternate scenario also appears in one of the two mixed curriculum mocks. The first three 17-task mocks keep their original task sets. Hints, an explained solution and requirement-by-requirement feedback are available in the lab.
Browse CKA practice tasks →