3. 集群 DNS 解析超时的稳定性加固

集群 DNS 解析超时的稳定性加固 学习卡片

CoreDNS 解析超时的稳定性加固

CoreDNS 解析超时通常不是单一原因,而是缓存命中率、副本数、资源限制、上游 DNS 可达性与网络策略共同作用的结果。加固思路是:先用指标定位瓶颈,再按“缓存 → 副本 → 资源 → 上游/网络策略”的顺序逐层调整,每步调整后验证解析成功率与 P99 延迟。

CoreDNS 解析超时加固:指标定位 → 分层调整 → 验证闭环 请求路径 Pod 应用 /etc/resolv.conf kube-dns Service ClusterIP:53 CoreDNS Pod 副本数 / 资源限制 上游 DNS /etc/resolv.conf 超时 / SERVFAIL 解析失败 关键指标诊断 coredns_dns_requests_total 请求总量 / QPS 判断负载是否突增 coredns_dns_responses_total rcode 分布 SERVFAIL / NXDOMAIN 占比 coredns_cache_hits_total 缓存命中率 低命中 → 上游压力大 coredns_forward_healthcheck 上游健康状态 失败 → 上游不可达 container_cpu_throttled CPU 限流次数 限流 → 处理延迟升高 分层加固措施 ① 缓存调优 cache 30 → 60s,提高命中率,降低上游 QPS prefetch 开启,提前刷新即将过期记录 ② 副本扩容 replicas 2 → 4,分散请求压力 配合 PodAntiAffinity 避免单节点集中 ③ 资源限制调整 CPU limit 100m → 500m,减少 throttling memory limit 170Mi → 256Mi,避免 OOM ④ 上游与网络策略 检查上游 DNS 可达性,调整 forward 超时 NetworkPolicy 放行 CoreDNS → 上游 53/UDP 验证:解析成功率 ↑,P99 延迟 ↓,SERVFAIL 归零 未达标则回到指标诊断重新定位

指标定位与判断依据

在 CoreDNS Pod 中暴露的指标端点为 :9153/metrics。通过以下命令快速抓取关键指标:

# 进入 CoreDNS Pod 或通过 Service 访问指标
kubectl -n kube-system port-forward svc/kube-dns 9153:9153

# 抓取关键指标
curl -s http://127.0.0.1:9153/metrics | grep -E \
  'coredns_dns_requests_total|coredns_dns_responses_total|coredns_cache_hits_total|coredns_cache_misses_total|coredns_forward_healthcheck_failures_total|container_cpu_cfs_throttled'
指标异常表现指向问题对应措施
coredns_cache_hits_total / (hits+misses)命中率 < 60%缓存 TTL 过短或 prefetch 未开① 缓存调优
coredns_dns_requests_totalQPS 突增且单副本承压副本数不足② 副本扩容
container_cpu_cfs_throttled_seconds_total持续增长CPU limit 过低③ 资源限制调整
coredns_forward_healthcheck_failures_total> 0 且增长上游 DNS 不可达或网络策略阻断④ 上游与网络策略
coredns_dns_responses_total{rcode="SERVFAIL"}占比升高上游超时或转发失败④ 上游与网络策略

CoreDNS ConfigMap 加固配置

以下 Corefile 在默认配置基础上调整了缓存 TTL、开启 prefetch,并显式设置 forward 超时与健康检查:

apiVersion: v1
kind: ConfigMap
metadata:
  name: coredns
  namespace: kube-system
data:
  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
            policy random
            health_check 5s
        }
        cache 60 {
            success 9984 60
            denial 9984 30
            prefetch 10 60s 20%
        }
        loop
        reload
        loadbalance
    }
缓存参数说明: cache 60 表示基础 TTL 为 60 秒;prefetch 10 60s 20% 表示当某域名在 60 秒内被请求超过 10 次且剩余 TTL 低于 20% 时,提前异步刷新,避免缓存过期瞬间的同步回源尖峰。

副本与资源限制调整

# 调整 CoreDNS Deployment 副本数与资源
kubectl -n kube-system patch deployment coredns --type='json' -p='[
  {"op":"replace","path":"/spec/replicas","value":4},
  {"op":"replace","path":"/spec/template/spec/containers/0/resources/limits/cpu","value":"500m"},
  {"op":"replace","path":"/spec/template/spec/containers/0/resources/limits/memory","value":"256Mi"},
  {"op":"replace","path":"/spec/template/spec/containers/0/resources/requests/cpu","value":"100m"},
  {"op":"replace","path":"/spec/template/spec/containers/0/resources/requests/memory","value":"128Mi"}
]'

同时建议为 CoreDNS 添加反亲和性,避免所有副本集中在同一节点:

affinity:
  podAntiAffinity:
    preferredDuringSchedulingIgnoredDuringExecution:
    - weight: 100
      podAffinityTerm:
        labelSelector:
          matchLabels:
            k8s-app: kube-dns
        topologyKey: kubernetes.io/hostname

上游 DNS 与网络策略检查

CoreDNS 的上游由节点 /etc/resolv.conf 决定。若上游 DNS 不可达,forward 健康检查会失败并触发 SERVFAIL。检查步骤:

  1. 确认节点 resolv.conf 中的上游地址:cat /etc/resolv.conf,记录 nameserver 列表。
  2. 从 CoreDNS Pod 内测试上游可达性:kubectl -n kube-system exec -it <coredns-pod> -- nslookup kubernetes.default 10.x.x.x。
  3. 若集群启用了 NetworkPolicy,需确保 CoreDNS 可出站到上游 53/UDP 和 53/TCP:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-coredns-egress
  namespace: kube-system
spec:
  podSelector:
    matchLabels:
      k8s-app: kube-dns
  policyTypes:
  - Egress
  egress:
  - to:
    - ipBlock:
        cidr: 10.0.0.0/8
    ports:
    - protocol: UDP
      port: 53
    - protocol: TCP
      port: 53
  - to:
    - namespaceSelector: {}
    ports:
    - protocol: UDP
      port: 53
    - protocol: TCP
      port: 53

验证与结果判读

调整完成后,通过以下方式验证加固效果:

# 1. 观察 CoreDNS Pod 状态与副本数
kubectl -n kube-system get pods -l k8s-app=kube-dns -o wide

# 2. 持续抓取指标,观察 SERVFAIL 与缓存命中率变化
watch -n 5 'curl -s http://127.0.0.1:9153/metrics | grep -E "coredns_dns_responses_total|coredns_cache_hits_total"'

# 3. 从业务 Pod 内做解析压测
kubectl run dns-test --image=busybox:1.36 --rm -it --restart=Never -- \
  sh -c 'for i in $(seq 1 200); do nslookup kubernetes.default >/dev/null 2>&1 || echo "FAIL $i"; done; echo done'
观察项加固前典型表现加固后预期
解析成功率存在间歇性超时200 次压测无 FAIL
SERVFAIL 计数持续增长趋于稳定或归零
缓存命中率< 60%> 80%
CPU throttling持续增长增长显著放缓或停止
P99 解析延迟波动大,偶发 > 5s稳定在 100ms 以内
注意: 调整副本数与资源限制后,需确认节点资源充足,避免 CoreDNS Pod 因资源不足被驱逐。若上游 DNS 本身不稳定,仅调整 CoreDNS 参数无法根治,需同步排查上游 DNS 服务或考虑部署本地缓存 DNS 作为二级缓存。