恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
K8s 服务 DNS 解析偶发 5 秒超时:conntrack 与 ndots 的 3 个坑
首页
资讯中心
/
K8s 服务 DNS 解析偶发 5 秒超时:conntrack 与 ndots 的 3 个坑
K8s 服务 DNS 解析偶发 5 秒超时:conntrack 与 ndots 的 3 个坑
发布时间:2026/10/15 13:01:08
我不会起名字322· 后端 / 算法 / 数据库 技术栈 力扣 Hot100 Go 项目 Redis MySQL文章目录K8s 服务 DNS 解析偶发 5 秒超时conntrack 与 ndots 的 3 个坑一、先搞清 5 秒从哪来二、第 1 个坑ndots:5 把一次解析放大成 5 次三、第 2 个坑search 域列表过长四、第 3 个坑conntrack 表被打满五、把三个坑串成排查链六、总结K8s 服务 DNS 解析偶发 5 秒超时conntrack 与 ndots 的 3 个坑“为什么偏偏是 5 秒”这是我第一次看到这个故障时的疑问。业务方反馈偶发请求要 5 秒才返回日志里是lookup user-svc.default.svc.cluster.local: i/o timeout。不是 1 秒不是 30 秒雷打不动的 5 秒。这个 5 秒数字本身就是线索。这篇拆 3 个坑ndots:5的放大效应、search域列表过长、conntrack表打满。一、先搞清 5 秒从哪来DNS 解析超时的5 秒不是随便来的它是内核 DNS 重试机制的结果glibc/musl 的 resolver 默认timeout:5每次查询等 5 秒、attempts:2一次查询发 UDP 包没响应 → 等 5 秒 → 重试如果ndots导致串行查询多个域名每个都可能等满 5 秒。所以看到恰好 5 秒几乎可以锁定是DNS 查询超时而不是应用自己慢。# 进容器实测解析耗时kubectlexec-itpod--cat/etc/resolv.conf kubectlexec-itpod--nslookupuser-svc.default.svc.cluster.local kubectlexec-itpod--sh-ctime getent hosts user-svc二、第 1 个坑ndots:5 把一次解析放大成 5 次先看你容器里的/etc/resolv.conf长这样nameserver 10.96.0.10 search default.svc.cluster.local svc.cluster.local cluster.local options ndots:5ndots:5的规则是如果查询的域名里点的数量 5就先把它当相对域名依次拼接search列表里的每个后缀去查全都失败才查原名。我们来算一下user-svc的解析过程点数为 0 5次序实际查询的域名是否命中1user-svc.default.svc.cluster.local✅ 命中这就是它的真实全名—以下都不会发生第 1 次就中了—但如果查询的是user-svc.default.svc.cluster.local点数 4 5就会先拼 search 后缀次序实际查询结果1user-svc.default.svc.cluster.local.default.svc.cluster.local❌ NXDOMAIN2user-svc.default.svc.cluster.local.svc.cluster.local❌ NXDOMAIN3user-svc.default.svc.cluster.local.cluster.local❌ NXDOMAIN4user-svc.default.svc.cluster.local✅ 命中一次解析变成 4 次查询。每次 NXDOMAIN 虽然快但一旦某次丢包要等 5 秒超时整体就变成 5 秒。修法把ndots调小通常设 2或直接用 FQDN以.结尾。spec:dnsConfig:options:-name:ndotsvalue:2# 点数 2 就直接查原名-name:single-request-reopen# 规避 A/AAAA 并发导致的 5 秒single-request-reopen也值得记住glibc 默认把 A 和 AAAA 查询发到同一个 socket某些内核/网络栈下会导致其中一条丢包等 5 秒。这个选项让两条查询用不同 socket。三、第 2 个坑search 域列表过长search列表里每多一个域最坏情况下就多一轮查询。默认的default.svc.cluster.local svc.cluster.local cluster.local已经是 3 个如果应用或平台又追加了自定义域查询次数会线性放大。# 看 search 列表kubectlexec-itpod--cat/etc/resolv.conf|grepsearch判据search列表长度 × 每次超时 5 秒 最坏耗时。3 个域 丢包 15 秒。修法精简search列表dnsConfig.searches或改用 FQDN。四、第 3 个坑conntrack 表被打满这是最隐蔽的一个。即使 DNS 配置完全正确DNS 查询也会失败——因为 UDP DNS 包要经过conntrack连接跟踪记录而 conntrack 表有大小上限。# 看 conntrack 表使用情况在节点上执行cat/proc/sys/net/netfilter/nf_conntrack_count# 当前条目数cat/proc/sys/net/netfilter/nf_conntrack_max# 上限# 看是否有丢包nstat-az|grep-iconntrack# 或cat/proc/net/stat/nf_conntrack|head-1为什么短连接会打满 conntrack每个 DNS 查询、每个短 TCP 连接都产生一条 conntrack 记录默认nf_conntrack_udp_timeout是 30 秒。QPS 高 大量短连接 → 表被占满 →新包直接被丢表现为 DNS 超时、连接超时。判据nf_conntrack_count接近nf_conntrack_max比如超过 80%且insert_failed在涨。# 确认真的是 conntrack 丢弃nstat-az|grep-ETcpAttemptFails|IpExt|conntrackdmesg|grep-inf_conntrack: table full修法# ① 调大表注意也要调大 hashsize否则只是拖慢哈希sysctl-wnet.netfilter.nf_conntrack_max1048576sysctl-wnet.netfilter.nf_conntrack_buckets262144# ② 缩短空闲超时sysctl-wnet.netfilter.nf_conntrack_udp_timeout10# ③ 应用侧用长连接替代短连接减少 conntrack 压力第 ③ 条才是治本——减少连接数永远比调大表更有效。五、把三个坑串成排查链顺序排查点命令命中则1resolv.conf 的 ndotscat /etc/resolv.conf默认 5→调小或改 FQDN2search 域数量同上3 个→精简3解析实测耗时time getent hosts svc恰 5 秒→DNS 超时确认4conntrack 使用率nf_conntrack_count / max接近满→调表减连接5内核丢弃计数nstat -az | grep conntrack有增长→实锤一个可带走物dnsConfig调优片段ndots:2 single-request-reopen可以直接复制进 Deployment。六、总结恰好 5 秒是内核 DNS 重试超时的标志能直接锁定 DNS 问题ndots:5会把一次解析放大成最多 5 次查询每次丢包等 5 秒 → 调小 ndots 或直接用 FQDN末尾带点search域列表越长最坏耗时越长域数 × 5 秒conntrack 表打满会静默丢包表现为 DNS/连接超时但配置全对 —— 判据是nf_conntrack_count接近max治本是减少短连接不是无脑调大 conntrack 表。留个问题给你你们集群里ndots改过没还是默认 5有没有遇到过配了 ndots 之后超时变少但没根治的情况——那大概率是 conntrack 在丢包。