CKA — CoreDNS

6 minute read

CKA Exam Domain

Services & Networking — 20%

CoreDNS is the cluster’s built-in DNS server, and CKA exam questions often ask you to troubleshoot DNS resolution, inspect the Corefile, or fix a misconfigured CoreDNS setup. Understanding its architecture pays off.

What Is CoreDNS?

CoreDNS is the default DNS server in Kubernetes clusters (since v1.13). It provides name resolution for all Services and Pods in the cluster.

When a Pod needs to reach a Service by name (e.g., my-svc.default.svc.cluster.local), CoreDNS resolves that name to the Service’s ClusterIP.

Key facts:

  • Runs as a Deployment in the kube-system namespace
  • Exposed via a Service named kube-dns (ClusterIP, typically 10.96.0.10)
  • Configuration stored in a ConfigMap named coredns
  • Every Pod’s /etc/resolv.conf points to the kube-dns Service IP

CoreDNS Architecture

Pod (/etc/resolv.conf → kube-dns IP)
  ↓ DNS query
kube-dns Service (ClusterIP)
  ↓
CoreDNS Pods (Deployment, 2 replicas)
  ↓ reads
coredns ConfigMap (Corefile)

Components:

Component Type Namespace Purpose
coredns Deployment kube-system Runs CoreDNS Pods (usually 2 replicas)
kube-dns Service (ClusterIP) kube-system Stable IP for DNS queries
coredns ConfigMap kube-system Contains the Corefile (configuration)

Check them:

kubectl get deployment coredns -n kube-system
kubectl get svc kube-dns -n kube-system
kubectl get configmap coredns -n kube-system

The Corefile

The Corefile is the heart of CoreDNS configuration. It’s stored in the coredns ConfigMap.

View the Corefile

kubectl get configmap coredns -n kube-system -o yaml

Default Corefile (Annotated)

.:53 {                          # Listen on port 53 for all zones
    errors                      # Log errors to stdout
    health {                    # Health check endpoint on :8080/health
        lameduck 5s
    }
    ready                       # Readiness endpoint on :8181/ready
    kubernetes cluster.local in-addr.arpa ip6.arpa {
                                # Handle DNS for the Kubernetes cluster
        pods insecure           # Enable Pod DNS records (A records)
        fallthrough in-addr.arpa ip6.arpa
        ttl 30                  # Cache TTL of 30 seconds
    }
    prometheus :9153            # Metrics endpoint for Prometheus
    forward . /etc/resolv.conf {
                                # Forward external DNS queries to upstream
        max_concurrent 1000
    }
    cache 30                    # Cache DNS responses for 30 seconds
    loop                        # Detect and stop forwarding loops
    reload                      # Auto-reload Corefile on changes
    loadbalance                 # Round-robin DNS responses
}

Plugin Breakdown

Plugin Purpose
errors Logs errors to stdout
health Exposes health check at :8080/health
ready Exposes readiness check at :8181/ready
kubernetes Enables DNS for Kubernetes Services and Pods
prometheus Exposes metrics at :9153/metrics
forward Forwards non-cluster DNS queries to upstream resolvers
cache Caches DNS responses to reduce load
loop Detects and breaks forwarding loops
reload Automatically reloads when ConfigMap changes
loadbalance Randomizes order of A records (round-robin)

DNS Record Types

CoreDNS creates different DNS records for different Kubernetes resources:

Service DNS Records

Record Type Format Example
A record <svc>.<ns>.svc.cluster.local nginx-svc.default.svc.cluster.local → 10.96.1.5
SRV record _<port-name>._<protocol>.<svc>.<ns>.svc.cluster.local _http._tcp.nginx-svc.default.svc.cluster.local

Pod DNS Records

Record Type Format Example
A record <pod-ip-dashed>.<ns>.pod.cluster.local 10-244-1-5.default.pod.cluster.local

Headless Service DNS

For headless Services (clusterIP: None), CoreDNS returns A records for each Pod’s IP directly:

my-headless.default.svc.cluster.local → 10.244.1.5, 10.244.2.3, 10.244.3.7

ExternalName Service DNS

For ExternalName Services, CoreDNS returns a CNAME record:

apiVersion: v1
kind: Service
metadata:
  name: external-db
spec:
  type: ExternalName
  externalName: db.external-provider.com
external-db.default.svc.cluster.local → CNAME → db.external-provider.com

Custom DNS Entries

You can customize CoreDNS by editing the coredns ConfigMap.

Stub Domains

Forward queries for a specific domain to a custom DNS server:

.:53 {
    # ... existing plugins ...
    forward . /etc/resolv.conf
}
company.local:53 {
    errors
    cache 30
    forward . 10.0.0.53           # Corporate DNS server
}

Adding Custom Records

Use the hosts plugin to add static DNS entries:

.:53 {
    hosts {
        10.0.0.100 custom-app.example.com
        10.0.0.101 legacy-db.example.com
        fallthrough
    }
    # ... rest of plugins ...
}

Apply Changes

After editing the ConfigMap:

kubectl edit configmap coredns -n kube-system

CoreDNS automatically picks up changes thanks to the reload plugin (usually within 30 seconds). You can also force a reload by restarting the Pods:

kubectl rollout restart deployment coredns -n kube-system

Troubleshooting CoreDNS

These commands are essential for diagnosing DNS issues:

# Check CoreDNS Pods are running
kubectl get pods -n kube-system -l k8s-app=kube-dns

# Check CoreDNS logs for errors
kubectl logs -n kube-system -l k8s-app=kube-dns

# Test DNS resolution from a debug Pod
kubectl run dnsutils --image=registry.k8s.io/e2e-test-images/agnhost:2.39 \
  --command -- sleep infinity
kubectl exec -it dnsutils -- nslookup kubernetes.default

# Check resolv.conf inside a Pod
kubectl exec -it dnsutils -- cat /etc/resolv.conf

# Expected resolv.conf content:
# nameserver 10.96.0.10           ← kube-dns ClusterIP
# search default.svc.cluster.local svc.cluster.local cluster.local
# options ndots:5

# Verify the kube-dns Service
kubectl get svc kube-dns -n kube-system

# Check CoreDNS endpoints
kubectl get endpoints kube-dns -n kube-system

Quick DNS Test

# Resolve a Service name
kubectl exec -it dnsutils -- nslookup nginx-svc.default.svc.cluster.local

# Short name (relies on search domains)
kubectl exec -it dnsutils -- nslookup nginx-svc

Common CoreDNS Issues

CrashLoopBackOff

Symptom: CoreDNS Pods are in CrashLoopBackOff.

Common cause: Loop detection. If the node’s /etc/resolv.conf points to 127.0.0.1 (common on systems running systemd-resolved), CoreDNS detects a forwarding loop and crashes.

Fix: Edit the Corefile’s forward plugin to use a specific upstream DNS instead:

forward . 8.8.8.8 8.8.4.4

DNS Resolution Fails

Symptom: Pods can’t resolve Service names.

Troubleshooting checklist:

  1. Is CoreDNS running? kubectl get pods -n kube-system -l k8s-app=kube-dns
  2. Does kube-dns Service have endpoints? kubectl get endpoints kube-dns -n kube-system
  3. Can the Pod reach kube-dns? kubectl exec <pod> -- nslookup kubernetes.default
  4. Is the Pod’s /etc/resolv.conf correct? Check nameserver points to kube-dns IP
  5. Are there NetworkPolicies blocking DNS (port 53)?

Slow DNS Resolution

Symptom: DNS queries take several seconds.

Common causes:

  • ndots:5 setting causes unnecessary search domain lookups for external names
  • Cache size too small for high-traffic clusters
  • Insufficient CoreDNS replicas

Practice Questions

Q1. Where is the CoreDNS configuration stored and how do you view it?

Show Answer

The configuration is stored in a ConfigMap named coredns in the kube-system namespace:

kubectl get configmap coredns -n kube-system -o yaml

The actual configuration is in the Corefile key of the ConfigMap.

Q2. What is the DNS name format for a Service named web-svc in namespace production?

Show Answer
web-svc.production.svc.cluster.local

The full format is: <service-name>.<namespace>.svc.cluster.local

From within the same namespace, you can use the short name web-svc. From another namespace, use web-svc.production.

Q3. CoreDNS Pods are in CrashLoopBackOff. The logs show “Loop detected”. How do you fix it?

Show Answer

The loop plugin detected a DNS forwarding loop — typically because the node’s /etc/resolv.conf points to a local resolver (127.0.0.1) that forwards back to CoreDNS.

Fix by editing the Corefile to use explicit upstream DNS servers:

kubectl edit configmap coredns -n kube-system

Change:

forward . /etc/resolv.conf

To:

forward . 8.8.8.8 8.8.4.4

Then restart CoreDNS: kubectl rollout restart deployment coredns -n kube-system

Q4. How do you test DNS resolution from inside the cluster?

Show Answer
# Launch a debug Pod
kubectl run dnsutils --image=registry.k8s.io/e2e-test-images/agnhost:2.39 \
  --command -- sleep infinity

# Test resolution
kubectl exec -it dnsutils -- nslookup kubernetes.default.svc.cluster.local

# Check resolv.conf
kubectl exec -it dnsutils -- cat /etc/resolv.conf

Expected output should show the Service resolving to its ClusterIP.

Q5. What happens when a Pod queries a DNS name like my-svc without the full domain?

Show Answer

The Pod’s /etc/resolv.conf has search domains configured:

search default.svc.cluster.local svc.cluster.local cluster.local

With ndots:5, the resolver appends each search domain in order:

  1. my-svc.default.svc.cluster.local — matches if the Service exists in the same namespace
  2. my-svc.svc.cluster.local — tried next if step 1 fails
  3. my-svc.cluster.local — tried next
  4. my-svc — absolute query as last resort

This is why short names like my-svc work within the same namespace.

Updated: