In Kubernetes clusters, CoreDNS operates as the control-plane service discovery backbone. Every inter-pod HTTP call, gRPC stream, database connection pool, and third-party API request begins with a DNS lookup to the kube-dns ClusterIP service. When CoreDNS experiences degradation—whether due to upstream recursive forwarder timeouts, ndots:5 query amplification, or Linux kernel conntrack race conditions—applications throw SERVFAIL errors, latency spikes across all services, and worker threads block waiting on getaddrinfo() system calls.
A brief 50 ms delay in DNS resolution amplifies into multi-second tail latency when application HTTP clients trigger exponential retries. This engineering guide provides an exhaustive breakdown of Kubernetes DNS packet flow, SERVFAIL root cause analysis, CoreDNS cache optimization, NodeLocal DNSCache architecture, Prometheus telemetry, and production incident response runbooks.
1. CoreDNS Failure Model in Kubernetes
Tracing a DNS query from an application container reveals the distributed path across the cluster network overlay:
[Application Container] ──► (glibc / musl getaddrinfo)
│
(Reads /etc/resolv.conf)
├── nameserver 10.96.0.10 (kube-dns Service IP)
├── search default.svc.cluster.local svc.cluster.local cluster.local
└── options ndots:5
│
▼ (UDP Port 53)
[kube-proxy / Cilium eBPF Datapath]
│
▼ (Load Balanced to CoreDNS Pod)
[CoreDNS Ingress Engine]
│
┌───────────────────┴───────────────────┐
▼ ▼
[Internal Cluster Domain] [External Public Domain]
*.svc.cluster.local api.stripe.com / aws.com
│ │
[kubernetes plugin] [cache plugin]
(Watches API Server) │ (Cache Miss)
│ ▼
│ [forward plugin]
│ │
▼ ▼
[Returns Pod/Service IP] [Upstream VPC / ISP DNS]
Recursive vs. Authoritative Resolution
- Authoritative Internal Resolution: Handled directly by CoreDNS via the
kubernetesplugin, querying in-memory caches populated by watching Kubernetes Service and EndpointSlice API objects. - Recursive External Resolution: Handled by the
forwardplugin, routing queries through/etc/resolv.confto cloud-provider recursive resolvers (e.g. AWS Route 53 Resolver169.254.169.253or Google Cloud DNS).
2. Packet-Level DNS Mechanics & ndots:5 Amplification
When an application resolves an external domain (e.g., api.stripe.com), the default Kubernetes resolver configuration (ndots:5) generates severe query amplification.
Query for "api.stripe.com" (contains 2 dots < 5):
1. api.stripe.com.default.svc.cluster.local. ──► NXDOMAIN (CoreDNS)
2. api.stripe.com.svc.cluster.local. ──► NXDOMAIN (CoreDNS)
3. api.stripe.com.cluster.local. ──► NXDOMAIN (CoreDNS)
4. api.stripe.com.ec2.internal. ──► NXDOMAIN (Upstream)
5. api.stripe.com. ──► NOERROR (Upstream - Success!)
Latency Amplification Model
For every external hostname lookup, the client initiates 5 distinct DNS queries. If an upstream resolver experiences a 1-second timeout on query 4:
[ L_{\text{miss}} = \sum_{i=1}^{n} \left(L_{\text{network}, i} + T_{\text{CoreDNS}, i} + T_{\text{upstream}, i}\right) ]
A single external HTTP call stalls for 1,000–3,000 ms purely waiting on DNS search path resolution.
To verify external DNS response codes and measure authoritative answer latency, test domain resolution with the Pingzo DNS Lookup.
3. Understanding SERVFAIL (RCODE=2) in Kubernetes
A SERVFAIL (Server Failure) response indicates that CoreDNS received the query but was unable to obtain an answer from its plugin pipeline or upstream resolvers.
[Application Pod] ──(Query: api.datadoghq.com)──► [CoreDNS] ──(Forward)──► [Upstream VPC DNS]
│
[Upstream Timeout (2.0s)]
│
[Application Pod] ◄── (RCODE=2: SERVFAIL) ──────── [CoreDNS] ◄─────────────────────┘
Primary Causes of CoreDNS SERVFAIL
- Upstream Recursive Timeout: Upstream cloud resolvers throttling queries due to per-ENI packet limits (e.g., AWS Route 53's 1,024 packets/second limit per network interface).
- Linux Conntrack Table Exhaustion: High-volume UDP traffic causes
nf_conntrack: table full, dropping packeterrors in the Linux kernel. - DNSSEC Validation Failure: Upstream domain has broken DNSSEC delegation or expired RRSIG records.
- CoreDNS OOMKilled: Memory limits set too low, causing CoreDNS pods to crash under traffic spikes.
4. Production-Hardened CoreDNS Configuration (Corefile)
Deploy this production-optimized CoreDNS configuration with proactive cache tuning, prefetching, and stale serving:
apiVersion: v1
kind: ConfigMap
metadata:
name: coredns
namespace: kube-system
data:
Corefile: |
.:53 {
errors
health {
lameduck 5s
}
ready
# 1. Authoritative Kubernetes Service Discovery
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
fallthrough in-addr.arpa ip6.arpa
ttl 30
}
# 2. Optimized Dual-Tier In-Memory Cache
cache 30 {
success 10000 30
denial 5000 5
prefetch 2 1m 10%
serve_stale 60s
}
# 3. Upstream Forwarding with Concurrency Limits
forward . /etc/resolv.conf {
max_concurrent 2000
prefer_udp
policy random
expire 10s
}
prometheus :9153
loop
reload
loadbalance round_robin
}
Key Cache Tuning Directives
prefetch 2 1m 10%: Automatically refreshes popular DNS records in the background before their TTL expires if they receive (\ge 2) queries in the last minute. Eliminates cold-cache latency spikes for high-traffic API endpoints.serve_stale 60s: Returns expired cached records for up to 60 seconds if upstream recursive resolvers time out, maintaining application availability during upstream network blips.denial 5000 5: CachesNXDOMAINnegative responses for 5 seconds to throttlendots:5search-domain query storms.
5. NodeLocal DNSCache Architecture
To eliminate conntrack UDP race conditions and reduce cluster-wide CoreDNS load, deploy NodeLocal DNSCache:
[Pod on Node 1] ──(Queries 169.254.20.10:53)──► [NodeLocal DNS DaemonSet (Local Pod)]
│
┌─────────────────┴─────────────────┐
▼ (Cache Hit) ▼ (Cache Miss over TCP)
[Returns 0.1ms Answer] [CoreDNS Cluster Service]
Benefits of NodeLocal DNSCache
- Conntrack Bypass: Replaces UDP connection tracking with a node-local link-local IP (
169.254.20.10), eliminating Linux kernel conntrack table contention. - TCP to CoreDNS: NodeLocal DNSCache forwards cache misses to CoreDNS over persistent TCP connections, preventing UDP packet drops.
- Sub-Millisecond Response: 95% of queries are resolved directly in node-local RAM with (< 0.2\text{ ms}) latency.
6. SRE Operational Threshold Matrix for CoreDNS
Configure Prometheus alerting rules based on actionable threshold boundaries:
| Metric Signal | Healthy Baseline | Warning State | Critical Incident (Page) | Primary Remediation |
|---|---|---|---|---|
| DNS Request Latency (p99) | (< 5\text{ ms}) | (5\text{ ms} - 25\text{ ms}) | (> 50\text{ ms}) | Check upstream timeouts & CPU limits |
| SERVFAIL Error Rate | (< 0.05%) | (0.05% - 0.5%) | (> 0.5%) | Inspect upstream forwarder & DNSSEC |
| Cache Hit Ratio ((H)) | (> 80%) | (60% - 79%) | (< 60%) | Tune cache capacity & prefetch |
| Upstream Forward Latency | (< 15\text{ ms}) | (15\text{ ms} - 50\text{ ms}) | (> 100\text{ ms}) | Cloud VPC DNS resolver saturation |
| CoreDNS Pod CPU Throttling | (0%) | (1% - 10%) | (> 10%) | Remove CPU limits / Scale replicas |
| CoreDNS Replica Count | (\ge 2) per cluster | 1 replica | 0 replicas (Outage) | Enforce PodDisruptionBudget (minAvailable: 2) |
Use the Pingzo SLA Calculator to evaluate how DNS latency and resolution failures impact your customer-facing uptime commitments.
7. Production-Safe Diagnostic Command Toolkit
Copy-pasteable CLI commands for immediate terminal incident triage:
1. Test DNS Resolution Latency & Flag Details via dig
# Test internal Kubernetes service resolution
kubectl exec -it deployment/api-service -- dig +stats +time=2 +tries=2 kubernetes.default.svc.cluster.local
# Test external domain resolution and inspect RCODE
kubectl exec -it deployment/api-service -- dig +stats +time=2 +tries=2 api.stripe.com
2. Inspect Real-Time CoreDNS Pod Logs for Forwarder Timeouts
kubectl -n kube-system logs -l k8s-app=kube-dns --tail=100 | grep -E "SERVFAIL|i/o timeout|plugin/forward"
3. Inspect Linux Kernel Conntrack Table Drops on Node
# Run on Kubernetes worker node
sudo conntrack -S
sudo dmesg | grep -i "conntrack"
8. Prometheus Alerting Rules for CoreDNS
Deploy these production PromQL rules in your Prometheus alertmanager:
groups:
- name: coredns_reliability_alerts
rules:
- alert: CoreDNSSERVFAILErrorSpike
expr: |
(sum(rate(coredns_dns_responses_total{rcode="SERVFAIL"}[5m])) /
sum(rate(coredns_dns_responses_total[5m]))) > 0.01
for: 2m
labels:
severity: critical
tier: networking
annotations:
summary: "CoreDNS SERVFAIL Error Rate > 1%"
description: "CoreDNS is returning SERVFAIL for > 1% of queries. Check upstream recursive resolver reachability."
- alert: CoreDNSHighLatencySpike
expr: |
histogram_quantile(0.99, sum(rate(coredns_dns_request_duration_seconds_bucket[5m])) by (le)) > 0.05
for: 3m
labels:
severity: critical
tier: networking
annotations:
summary: "CoreDNS p99 Latency > 50ms"
description: "CoreDNS query latency exceeded 50ms at p99. Check CoreDNS CPU throttling or upstream network delays."
- alert: CoreDNSLowCacheHitRatio
expr: |
(sum(rate(coredns_cache_hits_total[10m])) /
(sum(rate(coredns_cache_hits_total[10m])) + sum(rate(coredns_cache_misses_total[10m])))) < 0.60
for: 15m
labels:
severity: warning
tier: networking
annotations:
summary: "CoreDNS Cache Hit Ratio Below 60%"
description: "DNS cache efficiency is degraded, causing excessive upstream query load."
9. Step-by-Step Incident Response Runbook: CoreDNS Outage
Follow this ordered diagnostic flow when alerted to DNS latency or resolution failures:
- Verify Internal vs. External Failure: Execute
digagainstkubernetes.default.svc.cluster.local(internal) andgoogle.com(external) from a test pod. - Inspect CoreDNS Pod Health: Run
kubectl -n kube-system get pods -l k8s-app=kube-dns -o wideto check for crash loops or OOMKills. - Query CoreDNS Metrics: Check
coredns_forward_request_duration_secondsto see if the delay is caused by upstream VPC resolvers. - Inspect Node Conntrack: Check worker node kernel logs for
nf_conntrack: table fullorinsert_failedUDP drops. - Mitigate immediately:
- If CoreDNS is CPU throttled, remove CPU limits or increase CPU requests in the deployment spec.
- If
ndots:5is amplifying traffic, tune application pod specs withdnsConfig:dnsConfig: options: - name: ndots value: "2" - Autoscale CoreDNS replicas horizontally across all worker nodes:
kubectl -n kube-system scale deployment coredns --replicas=8
- Verify that
SERVFAILrate drops below (0.01%) and p99 DNS latency returns under 5 ms. - Document root causes in a post-mortem, deploying NodeLocal DNSCache and tuning pod search configurations.
10. Production Hardening Checklist for Kubernetes DNS
- NodeLocal DNSCache Deployed: Link-local daemonset active on all worker nodes to eliminate conntrack races.
- CoreDNS Autoscaler Configured:
cluster-proportional-autoscaleractive, scaling 1 CoreDNS replica per 25 nodes or 1,000 cores. - Pod Anti-Affinity Enforced: CoreDNS replicas distributed across distinct worker nodes and availability zones.
- Dual-Tier Caching Active:
prefetchandserve_staleenabled in the Corefile. - No CPU Limits on CoreDNS: CPU requests configured with guaranteed QoS; CPU limits removed to prevent kernel CFS throttling.
- Application ndots Tuned: High-QPS microservices configured with
ndots:2or fully-qualified domain names (FQDNs ending in.). - Synthetic E2E DNS Probes: Continuous blackbox probes verifying internal and external DNS resolution every 30 seconds.
11. Operational Decision Tree
[Kubernetes DNS Resolution Failure]
│
┌───────────────────────┴───────────────────────┐
▼ ▼
[Internal Resolution Fails] [External Resolution Fails]
(*.svc.cluster.local fails) (api.stripe.com SERVFAIL)
│ │
Check kubernetes Plugin & API Inspect Upstream Forwarder & VPC DNS
│ │
┌───────────┴───────────┐ ┌───────────┴───────────┐
▼ ▼ ▼ ▼
[K8s API Saturation] [CoreDNS Pod Crash] [Upstream Rate Limit] [Conntrack Drops]
Scale K8s Control Pl. Scale CoreDNS Replicas Deploy NodeLocal DNS Tune nf_conntrack_max
Related SRE & Performance Guides
- Kubernetes Ingress & Pod Health Monitoring: Liveness, Readiness, and CrashLoopBackOff Runbooks
- AWS Application Load Balancer (ALB) Monitoring: Target Health, Unhealthy Host Routing, and 504 Errors
- Traefik Reverse Proxy & Ingress Monitoring: Health Probes, Rate Limiting, and TLS Termination
- Infrastructure Observability & Health Checks: Probing Host Saturation and Service Endpoints
Stop Finding Out About Outages from Angry Users
Get instant WhatsApp & Discord alerts the second your API, website, or server goes down. Setup in 30 seconds with 60-second checks.