Linux DNS 解析失败:从 resolv.conf 到容器网络逐层验证
DNS 故障要区分“没有网络”“解析器不可达”“返回错误记录”和“应用缓存旧结果”。
维护者 Kevin · Ovalk
适用范围与前提
适用于具有 dig 与系统解析器的 Linux;systemd、NetworkManager 和容器的配置管理方式不同。
查询公共解析器时仅使用公开域名,不要向外部 DNS 发送内部服务名称。应在故障应用所在的网络命名空间收集结果。
常见症状
- curl 报 Could not resolve host
- 服务名在容器中解析失败、在宿主机正常
- 间歇性 NXDOMAIN 或超时
1. 验证解析链条
先用指定 DNS 服务器和系统默认解析器分别查询,避免只根据 ping 判断。若指定服务器也失败,检查网络/防火墙;若只有默认解析失败,检查 resolv.conf、systemd-resolved 或容器 DNS 配置。
cat /etc/resolv.conf
dig example.com
dig @1.1.1.1 example.com +short2. 检查搜索域与应用使用的解析器
短名称受 search domain、ndots 和库实现影响。Kubernetes 中还要核对 Pod 的 dnsPolicy、CoreDNS 日志及服务命名空间。应用语言运行时可能缓存 DNS,修复记录后仍需等待或刷新。
getent hosts example.com
resolvectl status 2>/dev/null || true3. 保留证据后恢复
记录失败域名、时间、上游 DNS、响应码和源网段,再决定切换 resolver 或修正记录。不要把公共 DNS 固化为生产唯一依赖,内部域名往往需要私有解析器。
journalctl -u systemd-resolved --since "1 hour ago" --no-pager解读证据
| 观察结果 | 下一步检查 |
|---|---|
| NXDOMAIN | 当前解析器视图中不存在该名称。检查拼写、搜索后缀、权威记录及负缓存。 |
| SERVFAIL 或超时 | SERVFAIL 表示解析失败,并不能证明记录不存在;超时则没有有效响应,应检查上游健康与 UDP/TCP DNS 连通性。 |
| dig 正常、应用失败 | 对照 getent 与应用解析器及缓存;单次 DNS 查询不能验证 hosts 文件和 NSS 规则。 |
说明性诊断案例
以下假设案例用于解释推理,并非客户真实事故,也不代表已在你的技术环境中测试。
应用容器无法解析内部数据库,但宿主机可以;两边都能解析公开网站。这将范围缩小到私有名称解析,而非一般网络连通性。对照容器 DNS、搜索后缀与目标私有解析器;全部切换到公共 DNS 反而会使内部数据库持续不可达。
验证恢复
- 在每个受影响运行环境中解析准确的完整域名,并测试应用连接,而不只是查询 IP。
- 等待相关正向或负缓存 TTL 后复测,确保结果符合预期的私有或公共视图。
回滚与停止条件
变更前记录解析器配置及管理它的服务;若私有名称或其他工作负载失败,通过该服务恢复配置。直接修改自动生成的 resolv.conf 不是持久修复。
预防与长期修复
- 监控关键域名的 A/AAAA/CNAME 解析与响应时间。
- 为内部和外部域名设计明确的 split-horizon 规则。
- 测试容器、节点和应用运行时三种解析路径。
参考资料与纠错
请使用与你安装版本匹配的文档。以下资料解释基础行为,命令仍需结合实际环境验证。
向 Kevin 提交更正,请附页面地址、版本与脱敏复现步骤。请查看编辑原则(英文)。