Back to blog
Reliability Engineering September 10, 2026

CoreDNS Latency & DNS Resolution Failures in Kubernetes: SERVFAIL Errors, Upstream Timeouts, and Cache Tuning

Automate WhatsApp Alerts
Start Free ➔

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 kubernetes plugin, querying in-memory caches populated by watching Kubernetes Service and EndpointSlice API objects.
  • Recursive External Resolution: Handled by the forward plugin, routing queries through /etc/resolv.conf to cloud-provider recursive resolvers (e.g. AWS Route 53 Resolver 169.254.169.253 or 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

  1. 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).
  2. Linux Conntrack Table Exhaustion: High-volume UDP traffic causes nf_conntrack: table full, dropping packet errors in the Linux kernel.
  3. DNSSEC Validation Failure: Upstream domain has broken DNSSEC delegation or expired RRSIG records.
  4. 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: Caches NXDOMAIN negative responses for 5 seconds to throttle ndots:5 search-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 SignalHealthy BaselineWarning StateCritical 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 cluster1 replica0 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:

  1. Verify Internal vs. External Failure: Execute dig against kubernetes.default.svc.cluster.local (internal) and google.com (external) from a test pod.
  2. Inspect CoreDNS Pod Health: Run kubectl -n kube-system get pods -l k8s-app=kube-dns -o wide to check for crash loops or OOMKills.
  3. Query CoreDNS Metrics: Check coredns_forward_request_duration_seconds to see if the delay is caused by upstream VPC resolvers.
  4. Inspect Node Conntrack: Check worker node kernel logs for nf_conntrack: table full or insert_failed UDP drops.
  5. Mitigate immediately:
    • If CoreDNS is CPU throttled, remove CPU limits or increase CPU requests in the deployment spec.
    • If ndots:5 is amplifying traffic, tune application pod specs with dnsConfig:
      dnsConfig:
        options:
          - name: ndots
            value: "2"
      
    • Autoscale CoreDNS replicas horizontally across all worker nodes:
      kubectl -n kube-system scale deployment coredns --replicas=8
      
  6. Verify that SERVFAIL rate drops below (0.01%) and p99 DNS latency returns under 5 ms.
  7. 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-autoscaler active, 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: prefetch and serve_stale enabled 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:2 or 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

Zero-Code Uptime Alerts

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.

WhatsApp & Discord 60-Second Checks Free Forever Plan
Try Pingzo Free

Know before your users do

Connect official WhatsApp notification channels, Discord webhooks, Telegram bots, and public status pages. Start in 30 seconds.

Create Free Monitor