← Start of tutorial

WIUNIX ACADEMY

Kubernetes DNS failure: trace the Pod, CoreDNS and Service endpoints

Page 2 of 3. Review the earlier steps and prerequisites before continuing.

YOUR SYSTEM. YOUR STEPS.

Where are you working?

Choose your OS and version. The prerequisites, commands and troubleshooting follow your environment.

Red Hat Enterprise Linux 10Reviewed against official documentation ·

USE YOUR OWN VALUES

Configure this tutorial

Set the example values for your environment; related explanations and copy panels update together. Never enter passwords, private keys or tokens. Values stay in this tab and are not sent to the server or share links. Check actual DNS, certificates and network policy before running commands.

Different IP addresses, domains or ports? Open the settings below, change the values and select “Apply to tutorial”, then copy the updated commands.

Set values for my environment11 editable values

Interpret the result without guessing

NXDOMAIN: check name, namespace and record semantics, including headless Service and readiness. Timeout: test DNS reachability and NetworkPolicy before the zone contents. SERVFAIL: inspect CoreDNS processing, permissions and upstream resolution. UDP failure with TCP success suggests a transport/size/path issue, not necessarily a missing record.

Search-list expansion can multiply requests. A trailing-dot FQDN is a useful control, not a blanket recommendation to change ndots globally. A and AAAA behavior also depends on the Service families and client IPv6 support.

05

LET’S BUILD

Inspect cluster DNS Pods, Service and EndpointSlices

The traditional k8s-app=kube-dns label and kube-dns Service name are also used by CoreDNS. Confirm them in your distribution before relying on the selector. Empty EndpointSlices or unready endpoints explain a Service with nothing healthy behind it; a DNS ClusterIP existing alone is not enough.

bash

Operator terminal; authorized lab context

kubectl --context='lab' -n kube-system get pods -l k8s-app=kube-dns -o wide
kubectl --context='lab' -n kube-system get service kube-dns -o yaml
kubectl --context='lab' -n kube-system get endpointslice -l kubernetes.io/service-name=kube-dns -o wide
kubectl --context='lab' -n kube-system logs -l k8s-app=kube-dns --all-containers=true --tail=100 --timestamps
How do I know it worked?

DNS Service ports include UDP/TCP53 and ready DNS endpoints exist, or a concrete missing component is identified.

06

LET’S BUILD

Separate Service selection from application health

Compare Service selector and targetPort to Pod labels and actual listening port, then read EndpointSlice readiness. A DNS answer with no ready endpoints can still occur for a normal ClusterIP Service. Inspect network policy at both source egress and destination ingress; a Service DNS failure and a TCP timeout may have different causes.

bash

Operator terminal; authorized lab context

kubectl --context='lab' -n 'academy-lab' describe service 'api'
kubectl --context='lab' -n 'academy-lab' get endpointslice -l kubernetes.io/service-name='api' -o yaml
kubectl --context='lab' -n 'academy-lab' get networkpolicy
kubectl --context='lab' -n 'academy-lab' get networkpolicy
How do I know it worked?

The Service maps to the intended ready Pods and the intended port; both traffic directions have reviewed policy.

07

LET’S BUILD

Compare internal and external DNS

If internal Kubernetes records work but an owned external domain fails, inspect the forward path, egress, authoritative DNS and the node resolver. A systemd-resolved stub used as an upstream can create a forwarding loop in a misconfigured deployment; do not replace kubelet resolver settings without the cluster owner. Keep sensitive names and query logs private.

bash

Operator terminal; authorized lab context

kubectl --context='lab' -n 'academy-lab' exec 'dns-client' -c 'tools' -- dig +time=2 +tries=1 'example.com.' A
kubectl --context='lab' -n kube-system get configmap coredns -o yaml
kubectl --context='lab' describe clusterrole system:coredns
How do I know it worked?

A failure is isolated to cluster records, upstream forwarding or workload-specific networking; no global change is made.

08

LET’S BUILD

Use one direct connectivity control

For the existing HTTP Service, compare DNS-based access with the known Service IP using the same Host header. curl must already exist in this authorized diagnostic container. A 401/403/404 can prove transport while still failing application authorization/routing; define the expected status with the owner. This panel sends a GET to the explicitly selected health path only.

bash

Operator terminal; authorized lab context

kubectl --context='lab' -n 'academy-lab' exec 'dns-client' -c 'tools' -- curl --noproxy '*' --connect-timeout 3 --max-time 8 --output /dev/null --write-out 'HTTP %{http_code}\n' 'http://api.academy-lab.svc.cluster.local:8080/healthz'
kubectl --context='lab' -n 'academy-lab' exec 'dns-client' -c 'tools' -- curl --noproxy '*' --connect-timeout 3 --max-time 8 --output /dev/null --write-out 'HTTP %{http_code}\n' -H 'Host: api.academy-lab.svc.cluster.local' 'http://10.96.20.30:8080/healthz'
How do I know it worked?

Compare actual GET transport and application status for named and direct routes.

Repair through the owner and repeat the same controls

Correct the demonstrated defect in the source of truth: a wrong service name, selector, endpoint readiness, DNS permission or narrowly scoped policy. CoreDNS configuration changes affect the cluster and require its own guarded review/rollback. Reuse the pre-change probes after the correction, include one previously healthy workload and compare both UDP and TCP. Do not call recovery complete because one query succeeds.

Explore all tutorials ↗