Kubernetes 中 Alpine(musl) DNS 解析异常排查复盘
Open: Pasted image 20260513104709.png

Kubernetes 中 Alpine(musl) DNS 解析异常排查复盘
问题现象
某个 Kubernetes Pod 中:
curl csghub.example.com
报错:
curl: (6) Could not resolve host: csghub.example.com
DNS server returned general failure
但:
nslookup csghub.example.com 10.43.0.10
能够正常解析:
Name: csghub.example.com
Address: 192.168.50.225
同时:
curl csghub.example.com.
(注意最后带 .)
能够正常访问。
而其他 Pod 没有问题。
一、问题背景
1. Pod
/etc/resolv.conf
异常 Pod:
search spaces.svc.cluster.local svc.cluster.local cluster.local example.com
nameserver 10.43.0.10
options ndots:5
其中:
10.43.0.10
是 Kubernetes CoreDNS Service IPndots:5
是 Kubernetes 默认配置example.com
是额外注入的 search domain
2. Pod 使用 Alpine / musl libc
执行:
ldd --version
输出:
musl libc (x86_64)
Version 1.2.5
说明该 Pod 使用:
- Alpine Linux
- musl libc resolver
而其他正常 Pod 使用:
- Ubuntu/Debian
- glibc resolver
二、根因分析
问题本质:
Kubernetes 默认 DNS 策略 + musl resolver 行为差异 + search domain 污染
共同导致 DNS 查询失败。
三、Kubernetes 默认 DNS 行为
Kubernetes 默认:
options ndots:5
意味着:
域名中 . 数量 < 5 时,
resolver 会优先尝试 search domain。
示例
访问:
csghub.example.com
该域名只有:
2 个 dots
满足:
2 < 5
因此 resolver 不会直接查询公网域名。
而是依次尝试:
csghub.example.com.spaces.svc.cluster.local
csghub.example.com.svc.cluster.local
csghub.example.com.cluster.local
csghub.example.com.example.com
四、真正的问题:search domain 污染
关键问题是:
search ... example.com
导致 resolver 产生错误查询:
csghub.example.com.example.com
这并不是用户真正想解析的域名。
五、CoreDNS 并没有故障
验证:
nslookup csghub.example.com 10.43.0.10
成功。
说明:
- CoreDNS 正常
- 网络正常
- Service DNS 正常
问题不在 Kubernetes DNS Server。
六、为什么 curl 会失败
curl 使用:
libc resolver
即:
- glibc
- musl
而:
nslookup
dig
使用的是:
自带 DNS client
不会完全走 libc resolver 流程。
因此:
nslookup 正常
curl 失败
是典型现象。
七、musl 与 glibc 的关键差异
这是问题核心。
glibc 行为(Ubuntu/Debian)
glibc 更“宽容”。
当 search domain 查询过程中遇到:
SERVFAIL
glibc 通常:
- 会继续尝试下一个 search
- 最后可能 fallback 到原始域名
因此:
最终仍可能解析成功
musl 行为(Alpine)
musl 更“严格”。
当遇到:
SERVFAIL
musl 可能:
直接终止解析链
于是:
curl csghub.example.com
失败:
DNS server returned general failure
八、为什么
curl domain.
可以成功
执行:
curl csghub.example.com.
注意:
最后带 "."
这是:
FQDN(Fully Qualified Domain Name)
完整限定域名。
带
.
的意义
告诉 resolver:
不要 search
不要 ndots
直接查询绝对域名
因此:
直接查询:
csghub.example.com
成功。
九、最终根因总结
问题并非:
- CoreDNS 故障
- 网络故障
- kube-proxy 故障
- Service 故障
真正根因:
Alpine(musl) + Kubernetes ndots:5 + search domain 污染
导致 resolver:
- 进入错误 search 链
- 遇到 SERVFAIL
- musl 提前终止解析
十、为什么其他 Pod 正常
因为其他 Pod:
- 使用 glibc
- 或没有
example.comsearch domain - 或 resolver 行为不同
因此:
即使 search 过程中失败,
glibc 仍可能 fallback 成功
十一、为什么
example.com
是关键问题
标准 Kubernetes search 应该是:
search <ns>.svc.cluster.local svc.cluster.local cluster.local
不应包含公网域名:
example.com
额外注入公网 search domain 会导致:
domain.example.com
这种错误查询。
属于:
DNS search 污染
十二、最终解决方案
方案 1(推荐)
修改 Pod:
dnsConfig:
options:
- name: ndots
value: "1"
效果:
公网域名:
example.com
会直接查询公网。
不会先 search。
方案 2
删除:
example.com
search domain。
恢复标准 K8s search。
方案 3
避免 Alpine。
生产环境建议:
- Debian slim
- Ubuntu
- UBI
- distroless-glibc
方案 4(临时 workaround)
统一使用:
domain.com.
FQDN。
但不推荐长期依赖。
十三、经验总结
1. nslookup 正常 ≠ 应用 DNS 正常
因为:
- nslookup 使用独立 DNS client
- curl/go/java/node 使用 libc resolver
行为不同。
2. Kubernetes 默认 ndots:5 对公网域名不友好
会:
- 增加 DNS 查询
- 放大 search domain 问题
- 增加 DNS latency
3. Alpine(musl) 在 Kubernetes 中 DNS 兼容性较差
尤其:
- ndots
- search domain
- SERVFAIL
- corporate DNS
组合场景。
4. 不要向 search domain 注入公网域名
错误示例:
searches:
- example.com
十四、推荐最佳实践
推荐统一:
dnsConfig:
options:
- name: ndots
value: "1"
并:
- 避免 Alpine 作为生产基础镜像
- 保持 search domain 简洁
- 不混入公网域名
- 避免依赖 search 自动补全公网域名
十五、此次问题的最终定性
这是一个:
Kubernetes DNS search/ndots 与 musl libc resolver 行为差异导致的兼容性问题
属于: