Kubernetes 集群内 DNS 超时导致服务偶发访问失败的排查
适用场景
本文适用于 Kubernetes 集群中应用访问 Service、数据库、Redis、外部域名时,偶发出现 DNS 解析超时、连接超时或请求延迟突然升高的场景。常见环境包括使用 CoreDNS、kube-proxy、containerd 或 Docker 运行时的生产集群,尤其是业务高峰期、节点扩容后、服务实例频繁发布后更容易暴露问题。
现象描述
业务侧通常不会直接报出 CoreDNS 故障,而是表现为以下几类现象:
- 应用日志间歇出现
lookup xxx on 10.96.0.10:53: read udp ... i/o timeout - Java、Go、Python 服务访问内部 Service 偶发超时,重试后恢复
- 同一个接口 P99 延迟突然升高,但 CPU、内存、数据库指标看起来正常
- 部分 Pod 正常,部分 Pod 异常,异常 Pod 多集中在少数节点
- CoreDNS Pod 没有 CrashLoopBackOff,但 QPS、延迟或错误数异常
这类问题的难点在于它经常是间歇性的。业务看到的是 HTTP 502、504、连接超时,真正的根因可能藏在 DNS 查询链路里。
可能原因
常见原因可以分为五类:
- CoreDNS 资源不足。CPU 被打满后,DNS 查询排队,应用侧看到解析慢或超时。
- CoreDNS 副本数不足。集群规模变大后仍只有两个副本,单个 Pod 承担过多请求。
- 节点本地网络异常。某些节点到 CoreDNS Service IP 或 CoreDNS Pod IP 不通,导致只有这些节点上的业务受影响。
- 上游 DNS 慢。CoreDNS 转发外部域名到上游 DNS 时,上游响应慢或丢包。
- 应用 DNS 查询放大。短 TTL、频繁新建连接、搜索域过多、
ndots配置不合理,导致一次访问触发多次 DNS 查询。
排查思路
排查时不要只看 CoreDNS Pod 是否 Running,Running 只能说明进程还活着,不能说明解析链路健康。建议按下面顺序缩小范围:
- 先确认是内部域名异常还是外部域名异常。
- 再确认异常是否集中在某些业务 Pod 或某些节点。
- 检查 CoreDNS 的 CPU、内存、日志和副本数。
- 从异常 Pod 内部直接测试 DNS 解析延迟。
- 检查 CoreDNS 到上游 DNS 的转发情况。
- 最后再看应用连接池、重试和 DNS 缓存配置。
常用命令
查看 CoreDNS Pod 状态:
kubectl -n kube-system get pod -l k8s-app=kube-dns -o wide
关键字段看 READY、STATUS、RESTARTS 和 NODE。如果 RESTARTS 增长,说明 CoreDNS 进程可能被 OOM、探针失败或异常退出。如果多个 CoreDNS Pod 落在同一节点,节点故障时影响面会变大。
查看 CoreDNS Service:
kubectl -n kube-system get svc kube-dns -o wide
重点看 CLUSTER-IP,这个地址通常会写入 Pod 的 /etc/resolv.conf,例如 10.96.0.10。后续在业务 Pod 中测试时,要确认请求是否真的打到了这个 DNS 地址。
查看 CoreDNS 资源使用:
kubectl -n kube-system top pod -l k8s-app=kube-dns
重点看 CPU 是否长期接近 request 或 limit。如果 CoreDNS CPU 被限制,DNS 查询延迟会明显升高。内存持续上涨则要关注是否有异常插件、日志量或查询压力。
查看 CoreDNS 日志:
kubectl -n kube-system logs -l k8s-app=kube-dns --tail=200
重点搜索 timeout、SERVFAIL、plugin/errors、no such host。如果大量外部域名解析失败,优先检查上游 DNS。如果内部 Service 解析失败,重点检查 Kubernetes API、CoreDNS 配置和服务对象。
进入异常 Pod 测试内部 Service 解析:
kubectl exec -it <pod-name> -n <namespace> -- sh
nslookup kubernetes.default.svc.cluster.local
nslookup <service-name>.<namespace>.svc.cluster.local
关键看返回是否稳定、是否出现超时、解析耗时是否明显偏高。内部域名异常时,问题通常在集群 DNS 链路内。
测试外部域名解析:
kubectl exec -it <pod-name> -n <namespace> -- sh
time nslookup www.baidu.com
time nslookup www.qq.com
如果内部域名正常、外部域名慢,重点看 CoreDNS 的 forward 配置和上游 DNS 连通性。
查看 Pod DNS 配置:
kubectl exec -it <pod-name> -n <namespace> -- cat /etc/resolv.conf
重点看 nameserver、search、options ndots。ndots:5 是 Kubernetes 常见默认值,访问短域名时可能先拼接多个搜索域再查询,放大 DNS 请求量。
查看 CoreDNS 配置:
kubectl -n kube-system get configmap coredns -o yaml
重点看 Corefile 中的 forward、cache、loop、ready、prometheus 配置。cache 可以降低重复查询压力,forward 指向的上游 DNS 决定外部域名解析质量。
定位示例
某业务在高峰期偶发访问 Redis 超时,应用日志出现:
lookup redis.default.svc.cluster.local on 10.96.0.10:53: read udp 10.244.18.32:42531->10.96.0.10:53: i/o timeout
第一步,确认 CoreDNS 状态:
kubectl -n kube-system get pod -l k8s-app=kube-dns -o wide
发现两个 CoreDNS Pod 都 Running,没有重启,但都运行在同一个节点上。
第二步,查看资源:
kubectl -n kube-system top pod -l k8s-app=kube-dns
发现 CoreDNS CPU 在高峰期接近 limit,说明解析请求可能在排队。
第三步,从异常业务 Pod 内测试:
kubectl exec -it order-api-6d7c8f9d9b-abcde -n prod -- sh
time nslookup redis.default.svc.cluster.local
cat /etc/resolv.conf
结果显示多次解析耗时超过 2 秒,并且 /etc/resolv.conf 中有较长的 search 列表和 options ndots:5。应用访问 redis 这种短域名时,会先尝试多个搜索域组合,再查最终域名,造成额外查询。
第四步,检查 CoreDNS 日志:
kubectl -n kube-system logs -l k8s-app=kube-dns --tail=200 | grep -E "timeout|SERVFAIL|plugin/errors"
日志中没有大量内部域名失败,但高峰期延迟明显,最终判断为 CoreDNS 副本不足叠加应用短域名查询放大。
修复方案
可以按风险从低到高逐步处理。
首先扩容 CoreDNS:
kubectl -n kube-system scale deployment coredns --replicas=4
扩容后观察 CoreDNS CPU 和业务超时是否下降。生产环境建议结合集群节点数和 DNS QPS 调整副本数,并使用反亲和性避免副本集中在同一节点。
其次调整 CoreDNS 资源限制:
kubectl -n kube-system edit deployment coredns
适当提高 CPU request 和 limit。CoreDNS 对 CPU 比较敏感,CPU 被 throttling 后,业务侧会直接感知到解析延迟。
再次,优化应用访问地址。内部服务尽量使用完整域名:
redis.default.svc.cluster.local
不要在高频请求路径里频繁解析短域名。对 Java、Go、Node.js 等应用,还要检查连接池复用和 DNS 缓存策略,避免每次请求都新建连接并触发解析。
如果外部域名解析慢,要检查 CoreDNS forward 的上游 DNS:
kubectl -n kube-system get configmap coredns -o yaml
可以将不稳定的上游 DNS 替换为企业内可用的递归 DNS,并保证节点到上游 DNS 的 UDP/TCP 53 端口通畅。
如果异常集中在某些节点,继续检查节点网络:
kubectl get pod -A -o wide | grep <node-name>
kubectl describe node <node-name>
重点看节点是否有网络插件异常、conntrack 表满、丢包、DNS Service IP 访问异常等问题。
预防措施
- 为 CoreDNS 配置合理的 request、limit 和副本数,不要长期使用默认值跑大集群。
- 为 CoreDNS 配置 Pod 反亲和性,避免多个副本落在同一节点。
- 在监控中加入 CoreDNS QPS、错误数、P99 延迟、CPU throttling 指标。
- 业务应用尽量复用连接池,避免短连接放大 DNS 压力。
- 高频访问内部服务时使用完整 Service 域名,减少 search 域查询次数。
- 对上游 DNS 做可用性监控,避免外部域名解析慢拖垮业务请求。
- 发布新服务或扩容节点后,观察 CoreDNS 负载是否同步增长。
总结
Kubernetes DNS 问题经常被误判为应用超时、Nginx 502、数据库慢或网络抖动。实际排查时,要从业务日志中的 lookup、i/o timeout、SERVFAIL 等关键字入手,再结合 CoreDNS 状态、资源、日志、Pod 内解析测试和节点分布逐步定位。
处理这类问题的核心不是只把 CoreDNS 重启一遍,而是确认 DNS 查询链路哪里慢、为什么慢、是否被应用查询模式放大。稳定的 CoreDNS 副本、合理的资源配置、可观测的 DNS 指标和规范的服务访问方式,才是减少线上 DNS 超时的关键。
Discussion
评论