news 2026/10/23 6:24:53

Kubernetes Pod 服务别名解析失败排查:从 no such host 到 CoreDNS 根因定位

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Kubernetes Pod 服务别名解析失败排查:从 no such host 到 CoreDNS 根因定位

1. 从一个诡异的通信故障说起

集群里跑着一套微服务,订单服务要调库存服务,库存服务要调商品服务,彼此之间全靠 Service 别名互相访问。某天做灰度发布,新拉起来的一批 Pod 突然报错,日志里清一色是no such host或者连接超时。诡异的地方在于:老 Pod 一切正常,新 Pod 就是找不到隔壁服务。重启、重建、换节点,全试了一遍,问题依旧。这种"同一个集群里,有的 Pod 能通、有的 Pod 不能通"的现象,是 Kubernetes 网络排查里最让人头疼的一类。

这篇记录就是围绕这个场景展开的。核心关键词是Kubernetes、Pod 内服务别名通信、DNS 解析、CoreDNS、Service 发现。我会把当时从现象到根因、从临时绕过到彻底修复的完整过程拆开讲,包括 DNS 解析链路是怎么走的、ndots和search域为什么会让别名解析失败、CoreDNS 的配置怎么查、NetworkPolicy 和 Endpoint 怎么排除。适合正在被集群内服务互调问题折磨的运维和开发同学,也适合刚接触 K8s 网络、想搞明白"为什么我的 Pod 解析不了服务名"的入门者。看完你至少能做到:拿到一个no such host的报错,知道按什么顺序去查,而不是盲目重启。

2. 先搞清楚 Pod 里"服务别名"到底是怎么解析的

2.1 服务别名不是魔法,本质是一次 DNS 查询

很多人以为 Pod 里写inventory-svc就能通,是 Kubernetes 内置了什么"服务发现魔法"。其实不是。当你在 Pod 里执行curl http://inventory-svc:8080时,第一步是 glibc 或 musl 的解析器去查 DNS,把inventory-svc这个名字翻译成一个 ClusterIP,然后才发起 TCP 连接。真正干活的,是集群里那个叫CoreDNS的组件。

CoreDNS 以 Deployment 形式跑在kube-system命名空间下,前面挂一个名为kube-dns的 Service,ClusterIP 通常是10.96.0.10这个网段里的某个地址。每个 Pod 被创建时,kubelet 会把/etc/resolv.conf写进去,内容大致长这样:

nameserver 10.96.0.10 search default.svc.cluster.local svc.cluster.local cluster.local options ndots:5

这三行就是整个服务发现的入口。nameserver指向 CoreDNS 的 ClusterIP;search定义了域名后缀的补全顺序;ndots:5决定了什么样的名字会先被当成"绝对域名"去查。理解这三行,基本就理解了 80% 的别名解析问题。

2.2 一次inventory-svc查询的完整链路

假设 Pod 在default命名空间,执行getent hosts inventory-svc,解析器会按search列表依次尝试:

  1. inventory-svc.default.svc.cluster.local
  2. inventory-svc.svc.cluster.local
  3. inventory-svc.cluster.local
  4. 最后才尝试inventory-svc.(作为绝对域名)

只要其中任意一个返回了 A 记录,解析就成功。CoreDNS 收到查询后,会根据配置的kubernetes插件去 API Server 里查对应的 Service 或 Endpoint,把 ClusterIP 返回去。整个过程在毫秒级完成,正常情况下你根本感知不到。

问题就出在"正常情况下"这四个字。一旦search域不对、ndots被改、CoreDNS 挂了、或者查询被 NetworkPolicy 拦了,这条链路就会断在某一环,表现就是no such host。

2.3 为什么"有的 Pod 能通、有的不能"

这是当时最迷惑我的点。同一个 Deployment,滚动更新出来的新 Pod 解析不了,老 Pod 却好好的。后来发现,问题往往出在Pod 的 DNS 配置差异上。Kubernetes 允许通过dnsPolicy和dnsConfig对单个 Pod 的解析行为做定制:

  • dnsPolicy: ClusterFirst是默认值,走集群 DNS。
  • dnsPolicy: Default会继承节点上的 resolv.conf,不走 CoreDNS,自然解析不了服务别名。
  • dnsPolicy: None配合dnsConfig手动指定,配错了就直接废掉。
  • dnsConfig里的searches和options会覆盖默认值,改错ndots或search顺序,别名就查不到。

当时那批新 Pod 的 YAML 里,有人为了"优化外部域名解析"加了dnsConfig,把ndots从 5 改成了 1,还把searches清空了。结果就是:外部域名确实快了,但集群内的短别名inventory-svc因为ndots:1被当成绝对域名直接查,search域又没了,CoreDNS 自然返回 NXDOMAIN。老 Pod 没这个配置,所以正常。这就是"同集群不同命"的典型根因。

3. 排查这类问题的标准动作与工具

3.1 第一步永远是看 Pod 里的 resolv.conf

别急着上 tcpdump,先kubectl exec进 Pod,把/etc/resolv.conf打出来:

kubectl exec -it <pod-name> -n <namespace> -- cat /etc/resolv.conf

重点核对三件事:nameserver是不是 CoreDNS 的 ClusterIP、search域里有没有svc.cluster.local、ndots是不是被改过。我踩过的坑里,有一半以上在这一步就能定位。如果nameserver指向的是8.8.8.8这种外部地址,那基本可以确定dnsPolicy配错了,Pod 压根没走集群 DNS。

3.2 用 nslookup 和 dig 分层验证

确认 resolv.conf 没问题后,进 Pod 手动查:

# 查短别名 nslookup inventory-svc # 查完整 FQDN nslookup inventory-svc.default.svc.cluster.local # 直接指定 CoreDNS 查,排除 search 域干扰 nslookup inventory-svc.default.svc.cluster.local 10.96.0.10

如果短别名失败、FQDN 成功,问题就在search域或ndots;如果 FQDN 也失败,但直接指定 CoreDNS 又成功,那可能是 Pod 的 resolv.conf 里 nameserver 写错了;如果连指定 CoreDNS 都失败,问题就上升到 CoreDNS 本身或网络策略层面了。这个分层验证法能快速缩小范围,比一上来就抓包高效得多。

提示:很多精简镜像里没有nslookup和dig。可以临时起一个带工具的调试 Pod,用kubectl run tmp --image=busybox --rm -it -- sh,然后nslookup目标服务。busybox 自带 nslookup,够用。

3.3 检查 CoreDNS 自身状态

如果怀疑是 CoreDNS 的问题,先看 Pod 和日志:

kubectl get pods -n kube-system -l k8s-app=kube-dns kubectl logs -n kube-system -l k8s-app=kube-dns --tail=100

重点看日志里有没有大量SERVFAIL、NXDOMAIN、i/o timeout。如果 CoreDNS Pod 频繁重启,可能是资源不够或者配置有语法错误。再看 ConfigMap:

kubectl get configmap coredns -n kube-system -o yaml

里面的Corefile定义了kubernetes插件、forward上游、cache等。如果kubernetes插件的pods或endpoints配置被改坏,服务解析就会出问题。我遇到过有人为了"减少 API Server 压力"把pods insecure去掉,结果某些依赖 Pod 域名解析的场景直接挂了。

3.4 别忘了 Endpoint 和 NetworkPolicy

DNS 解析成功只是第一步,解析出来的 ClusterIP 后面还得有真实的 Endpoint 才能通。如果 Service 的 selector 写错、或者后端 Pod 没 Ready,Endpoint 列表就是空的,连接会超时而不是no such host。这两个现象要区分开:

现象可能原因排查方向
no such hostDNS 解析失败resolv.conf、CoreDNS、ndots
connection refused端口不对或进程没起Service targetPort、容器端口
connection timeoutEndpoint 为空或网络策略拦截Endpoint 列表、NetworkPolicy
间歇性失败CoreDNS 负载高或缓存问题CoreDNS 资源、cache 配置

NetworkPolicy 是另一个隐形杀手。如果命名空间里配了默认拒绝入站的策略,又没放行 CoreDNS 的 53 端口,Pod 的 DNS 查询会被直接丢弃,表现也是解析超时。查一下:

kubectl get networkpolicy -n <namespace>

确认有没有策略把 UDP/TCP 53 给挡了。

4. 根因定位与修复实操

4.1 还原当时的故障现场

回到开头那个案例。新 Pod 报no such host,老 Pod 正常。按上面的顺序查:

第一步,进新 Pod 看 resolv.conf,发现ndots:1,search域是空的。老 Pod 是ndots:5加完整 search 域。差异找到了。

第二步,在新 Pod 里nslookup inventory-svc,失败;nslookup inventory-svc.default.svc.cluster.local,成功。这印证了:短别名因为ndots:1被当成绝对域名,又没有 search 域补全,所以查不到;FQDN 是完整的,所以能查到。

第三步,翻 Deployment 的 YAML,找到那段"优化"配置:

dnsConfig: options: - name: ndots value: "1" searches: []

问题根源确认:有人手动清空了searches并把ndots降到 1,破坏了集群内短别名的解析。

4.2 修复方案与验证

修复很简单,把dnsConfig里破坏性的部分去掉,恢复默认行为:

# 删除 searches: [] 和 ndots 覆盖,或者显式写回正确值 dnsConfig: options: - name: ndots value: "5" searches: - default.svc.cluster.local - svc.cluster.local - cluster.local

改完滚动更新,新 Pod 起来后再验证:

kubectl exec -it <new-pod> -- cat /etc/resolv.conf kubectl exec -it <new-pod> -- nslookup inventory-svc

短别名解析成功,故障解除。这里有个经验:如果确实需要优化外部域名解析速度,不要动ndots和searches,而是用 FQDN 访问外部域名,或者在 CoreDNS 层面做 forward 优化。动 Pod 级别的 DNS 配置,影响面太大,很容易误伤集群内通信。

4.3 参数背后的取舍逻辑

为什么默认ndots是 5?因为 Kubernetes 希望集群内的短别名优先被解析。ndots的含义是:如果域名里的点数量少于这个值,就先按 search 域补全去查。inventory-svc有 0 个点,小于 5,所以会走 search 列表。如果设成 1,inventory-svc的 0 个点仍然小于 1,理论上还是会走 search——但前提是 search 列表非空。当时的问题是 search 被清空了,所以补全无从谈起,直接查绝对域名失败。

那为什么有人会把ndots调小?因为访问外部域名如api.example.com有 2 个点,默认ndots:5下会先尝试api.example.com.default.svc.cluster.local等一系列无效查询,浪费几次 DNS 往返才查到真实地址。调小ndots能减少这种无效查询。但代价就是集群内短别名可能受影响。这是一个典型的"优化外部、牺牲内部"的取舍,做之前必须评估集群内服务互调的规模。

注意:如果非要调ndots,建议保留完整的searches列表,并且把值设在 2 到 3 之间,而不是 1。这样既能减少外部域名的无效查询,又能保证集群内短别名(0 个点)仍然走 search 补全。

5. 常见问题速查与避坑心得

5.1 高频问题速查表

问题现象根因解决动作
短别名no such host,FQDN 正常ndots或searches被改恢复默认 DNS 配置
所有域名都解析失败dnsPolicy: Default或 nameserver 错改回ClusterFirst
间歇性解析超时CoreDNS 负载高或副本不足扩容 CoreDNS、调 resources
解析成功但连接超时Endpoint 为空或 NetworkPolicy查 Endpoint、放行 53 端口
跨命名空间别名失败用了短名但不在同命名空间用svc.namespace或 FQDN
CoreDNS 日志大量 SERVFAIL上游 forward 不可达检查 Corefile 的 forward 配置

5.2 跨命名空间访问的坑

短别名inventory-svc只在同命名空间内有效。如果订单服务在order命名空间,库存服务在inventory命名空间,那订单服务里必须写inventory-svc.inventory或者完整 FQDNinventory-svc.inventory.svc.cluster.local。我见过有人图省事,在两个命名空间里各建了一个同名 Service,结果解析到了错误的那个,排查了半天。命名空间隔离是好事,但别名解析不会跨命名空间自动补全,这一点必须记牢。

5.3 独家避坑心得

第一条,永远不要在生产环境随意改 Pod 的dnsConfig。如果确实有外部域名解析性能问题,优先在 CoreDNS 的 Corefile 里做forward和cache优化,而不是动每个 Pod 的解析器配置。Pod 级别的改动影响面不可控,滚动更新时新老 Pod 行为不一致,排查成本极高。

第二条,给 CoreDNS 配好资源限制和副本数。默认 CoreDNS 可能只有 2 个副本,集群规模一大,QPS 上来就容易超时。建议至少 3 个副本,并且配上podAntiAffinity打散到不同节点。资源方面,requests给足 CPU,DNS 是延迟敏感型服务,CPU 被限流会直接导致解析超时。

第三条,用kubectl run起临时调试 Pod 时,记得指定命名空间。默认会落在default,如果你要排查的是order命名空间的服务,调试 Pod 也得在order里,否则短别名解析行为不一样,容易误判。

第四条,CoreDNS 的 cache 有时会"骗"你。改了 Service 的 Endpoint 后,短时间内解析结果可能还是旧的。排查时如果怀疑缓存,可以在 Corefile 里临时调小cache的 TTL,或者直接重启 CoreDNS Pod 清缓存。不过生产环境慎重重启,最好通过配置调整。

5.4 一个容易被忽略的细节:IPv6 与双栈

如果集群开了双栈,Pod 的 resolv.conf 里可能同时有 IPv4 和 IPv6 的 nameserver。某些应用的解析器对 IPv6 处理不好,会先尝试 IPv6 查询、超时后再回退 IPv4,表现为"解析特别慢但最终能通"。这种情况可以在dnsConfig里显式指定nameservers只保留 IPv4 的 CoreDNS 地址,或者检查 CoreDNS 的 Service 是不是双栈暴露的。双栈环境下的 DNS 问题比较隐蔽,日志里往往只看到延迟,看不到报错,需要结合抓包才能确认。

6. 把排查思路固化成习惯

这套排查流程我后来整理成了一个固定动作:一看 resolv.conf,二查短名与 FQDN 对比,三验 CoreDNS 状态,四排 Endpoint 与 NetworkPolicy。四步走下来,绝大多数 Pod 内服务别名通信问题都能定位。真正难的不是技术本身,而是面对"有的通有的不通"这种非确定性现象时,能不能保持分层验证的耐心,而不是一上来就重启大法。

我个人在实际操作中的体会是,Kubernetes 的网络问题,90% 的根因都藏在配置差异里,而不是组件本身坏了。同一个集群里行为不一致,第一反应应该是"这两个 Pod 的配置哪里不一样",而不是"集群是不是出问题了"。把kubectl exec进 Pod 看 resolv.conf 变成肌肉记忆,能省下大量抓包和重启的时间。最后再分享一个小技巧:给关键命名空间配一个常驻的调试 Pod,镜像里预装dig、nslookup、tcpdump、curl,出问题时直接 exec 进去,比临时拉镜像快得多,也不会因为镜像拉取失败耽误排查。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/23 6:21:28

agents-generator - platform

{{PLATFORM_NAME}} 规则 — 模板 仅在项目中检测到相应平台时生成。各平台的检测信号如下。 此文件被封装在受管理的块中。代理在更新时会在标记之间重新生成内容&#xff1b;标记外的人为编辑将被保留。 <!-- AGENTS-GENERATED-START --> # {{PLATFORM_RULES_HEADER}}{{…

作者头像 李华
网站建设 2026/10/23 6:04:39

Path of Building PoE2 新手指南:一晚跑通第一次配装验证

Path of Building PoE2 新手指南&#xff1a;一晚跑通第一次配装验证 【免费下载链接】PathOfBuilding-PoE2 项目地址: https://gitcode.com/GitHub_Trending/pa/PathOfBuilding-PoE2 纠结两件装备留哪件、怀疑某颗辅助和主技能的伤害差异比想象中大&#xff1f;Path o…

作者头像 李华