集群内服务解析慢主因是客户端/etc/resolv.conf的ndots与search域引发7–8次无效查询,应优先优化域名写法(如service-name.)和容器dns配置,而非盲目调大coredns副本数。

为什么集群内服务解析慢,大概率不是CoreDNS本身卡住
多数人遇到 nslookup service-name 延迟高或超时,第一反应是调大 CoreDNS 副本数或改缓存时间,但实际根因常在客户端:容器里 /etc/resolv.conf 的 ndots:5 和 search 域组合导致 7–8 次无效查询。比如访问 redis,它会依次尝试 redis.default.svc.cluster.local、redis.svc.cluster.local、redis.cluster.local,最后才查 redis —— 而真正需要的只是第一个。
解决思路优先级是:客户端域名写法 > 容器 DNS 配置 > CoreDNS 服务端参数。不优化前两者,光加副本只会把压力从 CoreDNS 转移到 NodeLocal DNSCache 或上游 DNS。
怎么写服务名才能让解析只查一次
在 Pod 内访问集群服务时,域名必须带足够多的点(.),绕过 search 域拼接。核心规则就两条:
- 同命名空间下,用
service-name.(注意末尾的点)—— 这会跳过所有search域,直查 A 记录 - 跨命名空间,用
service-name.namespace.svc.cluster.local.(同样以点结尾)
例如访问 default 命名空间下的 mysql,写成 mysql.;访问 kube-system 下的 coredns,写成 coredns.kube-system.svc.cluster.local.。这样无论 ndots 是 1 还是 5,都只发 1 次查询。
应用代码里硬编码域名时,务必加末尾点;用 Helm 或 Kustomize 渲染时,在模板中显式补上 .,别依赖运行时拼接。
CoreDNS 配置里哪些参数真影响集群内解析速度
默认配置中,真正对集群内服务发现有性能影响的只有三个地方,其他如 forward . /etc/resolv.conf 主要管外部域名,和内部解析无关:
-
cache 30:缓存 TTL,30 秒够用;设太高会导致 Service Endpoint 变更后旧 IP 缓存不刷新,建议保持默认或调到 60 -
kubernetes {{ dns_domain }} in-addr.arpa ip6.arpa:这个插件负责监听 Service/Endpoint 变化并生成记录,不能关,但可加pods insecure加速 Pod IP 直查(避免额外 A 记录查询) -
loadbalance:开启后 CoreDNS 会轮询返回多个 A 记录,避免客户端单点连接,建议保留
别碰 ndots 或 search 的全局配置——那是节点或容器镜像层的事,改 CoreDNS 配置文件里的这些值不会生效。
什么时候该开 NodeLocal DNSCache,什么时候纯属浪费
NodeLocal DNSCache 不是“开了就快”,它只在以下情况带来真实收益:
- 集群节点数 ≥ 20,且 DNS QPS 持续 > 5000
- Pod 启停频繁(比如 Serverless 场景),导致大量新 Pod 初始化时集中查
search域 - 使用了
hostNetwork: true的 Pod,它们绕过 ClusterFirst,直连节点/etc/resolv.conf,此时本地缓存能挡掉重复查询
如果集群只有几个节点,或者业务基本不走外部域名、服务名都带结尾点,那部署 NodeLocal DNSCache 反而多一层转发链路,增加延迟。Kubespray 默认开它是为通用场景兜底,不是最优解。
真正省事又有效的组合是:应用侧写对域名 + 容器镜像用 glibc(避开 Alpine 的 musl libc 解析缺陷)+ CoreDNS 保持默认 cache + 节点数超阈值再加 NodeLocal DNSCache。











