容器集群内DNS解析延迟的优化,核心路径只有三条:压缩Pod到CoreDNS的链路跳数、扩大本地缓存命中率、调整解析配置减少无效查询,其中部署NodeLocal DNSCache和调优CoreDNS缓存,是见效最快的两个动作。
Kubernetes DNS解析延迟优化的核心路径
Pod发起DNS请求后,报文要先穿过容器网络到达CoreDNS Service,再经kube-proxy转发到CoreDNS Pod,这个链路里任何一跳抖动,都会被放大成应用层超时。
典型链路如下:
- Pod内
/etc/resolv.conf指向ClusterIP - 请求命中Service,由kube-proxy的iptables或IPVS规则转发
- 到达CoreDNS Pod,解析本地记录或向上游转发
- 上游响应原路返回
只要这条链路多一跳,延迟就多一层风险。
容器集群DNS解析慢怎么排查:先定位是哪一段慢
很多团队一上来就改CoreDNS配置,方向没错,但如果不先定位,很容易越调越乱,排查按下面三步走。
用nslookup和dig模拟真实请求
进入Pod内部直接测试:
kubectl run -it --rm debug --image=busybox:1.28 -- sh
nslookup kubernetes.default.svc.cluster.local
再测一个外部域名:
nslookup www.baidu.com
对比两次耗时,只慢外部域名,重点看CoreDNS上游转发;内外都慢,重点看本地链路和CoreDNS本身。
看CoreDNS日志与指标
查看CoreDNS Pod状态:
kubectl get pods -n kube-system -l k8s-app=kube-dns -o wide
查看日志:
kubectl logs -n kube-system -l k8s-app=kube-dns --tail=50
日志里出现SERVFAIL、timeout、i/o timeout,说明上游响应或自身处理出了问题。
抓包确认网络链路
在节点上对CoreDNS Pod抓包:
tcpdump -i any port 53 -nn
从Pod内再次发起解析,观察请求是否到达、响应是否返回、间隔多少,如果请求多次重传,基本就是网络层抖动。
CoreDNS和kube-dns对比:延迟差异来自架构
很多集群从kube-dns迁到CoreDNS后,延迟不降反升,原因在架构差异。
| 对比项 | kube-dns | CoreDNS |
|---|---|---|
| 组件数量 | 3个容器(kubedns、dnsmasq、sidecar) | 单进程多插件 |
| 缓存层 | dnsmasq自带缓存 | 需显式开启cache插件 |
| 链路复杂度 | 请求先进dnsmasq,再转kubedns | 请求直接进CoreDNS |
| 扩展性 | 垂直扩展为主 | 水平副本+HPA |
| 配置方式 | ConfigMap+命令行参数 | Corefile插件链 |
CoreDNS单进程模型本身更轻,但默认缓存策略不如dnsmasq激进,迁移后如果不显式配置cache,相当一部分请求会直接打上游,延迟反而升高。
行业共识认为,CoreDNS在副本充足且缓存配置合理的前提下,整体延迟表现优于kube-dns。
容器内DNS解析超时原因:ndots与search域在作怪
Pod的/etc/resolv.conf里有两个参数经常被忽略,却是延迟大户。
默认配置类似:
nameserver 10.96.0.10
search default.svc.cluster.local svc.cluster.local cluster.local
options ndots:5
ndots:5的意思是:域名里点号少于5个时,先拿search域逐个拼接查询,比如应用访问mysql,会先生成:
- mysql.default.svc.cluster.local
- mysql.svc.cluster.local
- mysql.cluster.local
- mysql
最多4次查询,其中前3次基本都会返回NXDOMAIN,这等于凭空多出3次无效请求。
解决办法是降低ndots或让应用使用完整域名。
在Pod模板里可以显式覆盖:
dnsConfig:
options:
- name: ndots
value: "2"
或者直接写完整域名mysql.default.svc.cluster.local,跳过search域拼接。
优化方向一:扩大CoreDNS容量与副本
CoreDNS默认部署2个副本,中型集群一旦请求量上来,队列等待会明显拉高延迟。
先看当前副本数:
kubectl get deployment coredns -n kube-system
再根据节点规模和请求量调整:
kubectl scale deployment coredns -n kube-system --replicas=4
同时给CoreDNS设置资源保障,避免CPU限流:
resources:
requests:
cpu: 200m
memory: 256Mi
limits:
cpu: 1000m
memory: 512Mi
还可以配置HPA,按CPU或内存自动扩缩:
kubectl autoscale deployment coredns -n kube-system --cpu-percent=70 --min=2 --max=8
优化方向二:打开CoreDNS缓存与负缓存
据CoreDNS官方文档,cache插件能缓存正向和反向记录,直接减少对上游DNS的请求,很多集群的Corefile里没有cache段,或者缓存时间设得太短。
推荐配置:
.:53 {
errors
health
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
fallthrough in-addr.arpa ip6.arpa
}
prometheus :9153
forward . /etc/resolv.conf
cache {
success 1000 60
denial 1000 10
}
loop
reload
loadbalance
}
denial负缓存尤其重要,前面说的ndots拼接出来的大量NXDOMAIN,如果每次都穿透到上游,延迟很难看,打开负缓存后,无效查询的响应时间可以从几十毫秒降到几毫秒。
优化方向三:部署NodeLocal DNSCache
这是目前社区公认最有效的优化手段之一,基本原理:在每个节点上跑一个本地DNS缓存代理,Pod的请求不再经过ClusterIP和kube-proxy,而是直接打到节点本地的254.20.10。
链路对比:
- 优化前:Pod → Service ClusterIP → iptables/IPVS → CoreDNS Pod → 上游
- 优化后:Pod → 节点本地NodeLocal DNSCache → CoreDNS → 上游
少了两跳网络转发,也绕过了conntrack。
部署步骤:
- 获取官方yaml,修改
__PILLAR__DNS__SERVER__为集群CoreDNS Service IP - 修改
__PILLAR__LOCAL__DNS__为254.20.10 - apply到集群
- 检查DaemonSet是否每个节点都Running
- 新Pod的
/etc/resolv.conf会自动指向254.20.10
验证方式:
kubectl get pods -n kube-system -l k8s-app=node-local-dns
从新Pod里测试:
nslookup kubernetes.default.svc.cluster.local 169.254.20.10
优化方向四:调整Pod的DNS策略与超时参数
除了ndots,timeout和attempts也会影响感知延迟,默认timeout:5秒太长,如果CoreDNS没响应,应用要等5秒才报错。
建议在Pod模板里显式设置:
dnsConfig:
options:
- name: ndots
value: "2"
- name: timeout
value: "1"
- name: attempts
value: "2"
同时将dnsPolicy设为ClusterFirst或Default,根据业务是否需要访问集群内服务来决定,只访问外部API的服务可以设
Default,直接走节点DNS,完全绕过CoreDNS。
简米云容器服务DNS优化:托管集群的注意事项
在简米云ACK等托管环境里,CoreDNS默认由云平台托管,部分配置可以通过控制台调整,但无法像自建集群那样随意改Corefile。
常用优化手段:
- 在ACK控制台找到“组件管理”,调整CoreDNS副本数
- 开启“NodeLocal DNSCache”插件,ACK已提供一键部署
- 若自建节点,检查节点
/etc/resolv.conf是否指向云内网DNS,避免跨地域解析 - 跨地域访问云服务时,优先使用内网域名,减少公网递归延迟
托管集群的DNS延迟有相当一部分来自上游转发策略,如果上游指向公网DNS,解析外部域名会多走一段公网往返,切换成云厂商内网DNS通常能更快。
业内专家指出,云环境下的DNS优化要优先关注平台侧默认值,很多延迟问题并非CoreDNS本身,而是默认上游和网络策略约束。
写在最后
容器集群DNS解析延迟不是一个单点问题,它分布在Pod配置、CoreDNS容量、缓存策略、节点网络四条线上,单独调整任何一处都可能有效,但组合起来效果最稳。
先把NodeLocal DNSCache部署起来,再调CoreDNS缓存和ndots,最后按Pod特性细分dnsPolicy,这套组合拳能覆盖绝大多数延迟场景。
Q&A:容器集群DNS解析延迟优化常见问题
容器集群DNS解析慢怎么排查第一步该做什么?
先在Pod里用nslookup分别测试内部域名和外部域名,记录耗时差异,内部慢说明CoreDNS或本地链路有问题,外部慢重点查上游DNS转发配置,不要一上来就改CoreDNS副本数,先拿到对比数据再动手。
Kubernetes DNS解析延迟优化需要重启Pod吗?
修改CoreDNS配置、副本数、NodeLocal DNSCache部署都不需要重启业务Pod,但要让Pod拿到新的/etc/resolv.conf,通常需要滚动更新Pod,如果只改了CoreDNS缓存或副本,不影响Pod侧配置,无需重启。
CoreDNS和kube-dns对比哪个更适合高并发集群?
CoreDNS单进程多插件架构在高并发下水平扩展更灵活,配合HPA和NodeLocal DNSCache,整体吞吐和延迟控制优于kube-dns,kube-dns的三组件模型在多副本场景下资源占用偏高,维护复杂度也更大,高并发集群优先选CoreDNS,但必须显式打开cache和负缓存。
首发原创文章,作者:王坚,如若转载,请注明出处:https://idctop.com/article/642049.html




