CoreDNS and service discovery
How Services and Pods get DNS names, what a Pod's resolv.conf does with them, how the Corefile is put together, and how to debug a lookup that fails.
After this lesson
- 01You can predict the DNS name and record type for any Service, headless Service or Pod, and resolve it from a client Pod.
- 02You can set dnsPolicy and dnsConfig on a Pod and confirm the result in its /etc/resolv.conf.
- 03You can read and safely change the CoreDNS Corefile, and recognize a cluster whose DNS is down.
Understand and use CoreDNS is its own competency, and DNS also sits underneath every "the app cannot reach the database" troubleshooting task. CoreDNS is just a Deployment in kube-system behind a Service called kube-dns, configured by one ConfigMap. Knowing the naming scheme lets you write a lookup without thinking. Knowing the Corefile lets you change it without breaking the cluster.
The names CoreDNS answers
cluster.local is the cluster domain, set by kubelet's clusterDomain and the kubernetes plugin's zone. It is the default on the exam too, but if a lookup fails everywhere, check it: grep clusterDomain /var/lib/kubelet/config.yaml on a node.
What a Pod's resolver does
kubectl -n nw-dns exec client -- cat /etc/resolv.conf
# search nw-dns.svc.cluster.local svc.cluster.local cluster.local
# nameserver 10.96.0.10
# options ndots:5
kubectl -n kube-system get svc kube-dns # 10.96.0.10: the ClusterIP of CoreDNSkubelet writes this file. nameserver is the kube-dns ClusterIP (kubelet's clusterDNS). The search list is why a bare inventory works inside nw-dns and inventory.nw-dns works from any namespace. ndots:5 means any name with fewer than five dots is tried with each search suffix before being tried as is. So api.example.com costs three failed cluster lookups first. A trailing dot (api.example.com.) skips the search list.
dnsPolicy and dnsConfig
apiVersion: v1
kind: Pod
metadata:
name: resolver
namespace: nw-dnscfg
spec:
dnsPolicy: ClusterFirst
dnsConfig:
searches:
- corp.internal # appended after the cluster search domains
options:
- name: ndots
value: "2" # value is a string
- name: timeout
value: "2"
containers:
- name: busybox
image: busybox:1.36
command: ["sleep", "3600"]dnsConfig and dnsPolicy are immutable on a running Pod. Change them in the manifest and recreate the Pod (kubectl replace --force -f pod.yaml), or change the Deployment template and let it roll.
The Corefile
.:53 {
errors
health {
lameduck 5s
}
ready
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
fallthrough in-addr.arpa ip6.arpa
ttl 30
}
prometheus :9153
forward . /etc/resolv.conf {
max_concurrent 1000
}
cache 30 {
disable success cluster.local
disable denial cluster.local
}
loop
reload
loadbalance
}.:53is a server block for every zone on port 53. You can add more blocks, such ascorp.internal:53 { forward . 10.0.0.53 }, to send one domain to a specific DNS server (a stub domain).kubernetesanswerscluster.localplus reverse lookups from the API (Services, EndpointSlices, Pods).pods insecureenables thea-b-c-d.ns.podrecords.forward . /etc/resolv.confsends everything else to the resolvers of the node CoreDNS runs on. Replace the path with IPs to use specific upstreams.cache 30caches answers for up to 30 seconds. Remember this when a change "does not work" for half a minute.hosts(not present by default) serves static entries; addfallthroughso other names still reach the next plugin.reloadrereads the Corefile when the ConfigMap changes, which takes up to a minute or two.loopstops CoreDNS if it detects it is forwarding to itself.healthandreadyback the Pod's probes.
# Keep a copy first. Every Pod in the cluster depends on this file.
kubectl -n kube-system get cm coredns -o jsonpath='{.data.Corefile}' > /tmp/cka/Corefile.bak
kubectl -n kube-system edit cm coredns # e.g. add, inside .:53 { … }:
# hosts {
# 10.10.10.10 legacy-db.corp.internal
# fallthrough
# }
# Apply now instead of waiting for reload, then make sure both replicas come back
kubectl -n kube-system rollout restart deploy coredns
kubectl -n kube-system rollout status deploy coredns --timeout=120s
kubectl -n kube-system logs -l k8s-app=kube-dns --tail=20 # a syntax error shows up here
# Roll back if it went wrong
kubectl -n kube-system create cm coredns --from-file=Corefile=/tmp/cka/Corefile.bak --dry-run=client -o yaml | kubectl replace -f -
kubectl -n kube-system rollout restart deploy corednsDebugging a lookup
kubectl -n nw-dns run client --image=busybox:1.36 --restart=Never -- sleep 3600
kubectl -n nw-dns wait --for=condition=Ready pod/client --timeout=60s
kubectl -n nw-dns exec client -- nslookup inventory.nw-dns.svc.cluster.local # one Service
kubectl -n nw-dns exec client -- nslookup inventory-pods.nw-dns.svc.cluster.local # headless: one line per Pod
kubectl -n nw-dns exec client -- nslookup kubernetes.default.svc.cluster.local # the API: always exists
kubectl -n nw-dns exec client -- nslookup 10.96.0.1 # reverse lookup
# Is CoreDNS itself healthy?
kubectl -n kube-system get deploy coredns
kubectl -n kube-system get endpointslices -l kubernetes.io/service-name=kube-dns
kubectl -n kube-system logs -l k8s-app=kube-dns --tail=30Learn what broken DNS looks like, because the message names the layer. NXDOMAIN means CoreDNS answered: the name is wrong, the namespace is wrong, or the Service does not exist. ;; connection timed out; no servers could be reached means nothing answered on port 53: CoreDNS is down or has no endpoints, or a NetworkPolicy blocks egress to it. Applications then report bad address or could not resolve host, and every connection that uses a name fails while connections by IP still work.
In the docs · the tab you get on exam day
- DNS for Services and Pods ↗search: “dns for services and pods”
- Debugging DNS Resolution ↗search: “debugging dns resolution”
- Customizing DNS Service ↗search: “customizing dns service corefile”
context · kubectl config use-context kind-cka
Resolve a Service and a headless Service
nw-dns, start a temporary Pod with image busybox:1.36. From it, resolve the fully qualified DNS name of the Service inventory and write the address the lookup returns to /tmp/cka/dns-inventory-ip.txt. Then resolve the fully qualified name of the headless Service inventory-pods and write every address it returns, one per line, to /tmp/cka/dns-inventory-pods.txt. Delete the temporary Pod when you are done.- 01
Set up the scenario
curl -fsSL https://codewithmuh.com/labs/cka/t/nw-dns-1/setup | bash - 02
Solve it in your terminal
Work the way the exam makes you: kubectl, the docs, nothing else. Put any answer files under
/tmp/cka/. - 03
Check your work
curl -fsSL https://codewithmuh.com/labs/cka/t/nw-dns-1/verify | bashCounts toward your readiness score. - 04
Clean up
curl -fsSL https://codewithmuh.com/labs/cka/t/nw-dns-1/cleanup | bash
context · kubectl config use-context kind-cka
Give a Pod an extra search domain
resolver in namespace nw-dnscfg using image busybox:1.36 that runs sleep 3600. It must keep using cluster DNS. Add corp.internal as an additional search domain and set the resolver option ndots to 2. The Pod must be Running.- 01
Set up the scenario
curl -fsSL https://codewithmuh.com/labs/cka/t/nw-dns-2/setup | bash - 02
Solve it in your terminal
Work the way the exam makes you: kubectl, the docs, nothing else. Put any answer files under
/tmp/cka/. - 03
Check your work
curl -fsSL https://codewithmuh.com/labs/cka/t/nw-dns-2/verify | bashCounts toward your readiness score. - 04
Clean up
curl -fsSL https://codewithmuh.com/labs/cka/t/nw-dns-2/cleanup | bash
context · kubectl config use-context kind-cka
Serve a static record from CoreDNS
legacy-db.corp.internal to 10.10.10.10. All existing names, including Services and names outside the cluster, must keep resolving. Confirm from Pod client in namespace nw-dnshosts.Setup breaks part of your lab on purpose. Run the cleanup step when you finish, or reset the lab.
- 01
Set up the scenario
curl -fsSL https://codewithmuh.com/labs/cka/t/nw-dns-3/setup | bash - 02
Solve it in your terminal
Work the way the exam makes you: kubectl, the docs, nothing else. Put any answer files under
/tmp/cka/. - 03
Check your work
curl -fsSL https://codewithmuh.com/labs/cka/t/nw-dns-3/verify | bashCounts toward your readiness score. - 04
Clean up
curl -fsSL https://codewithmuh.com/labs/cka/t/nw-dns-3/cleanup | bash
Finished reading?
0 of 3 tasks passed. Readiness counts tasks, so run them before you move on.