阿里云ECS内网DNS解析失败排查:systemd-resolved配置详解
很多运维在阿里云ECS上遇到内网域名突然解析失败时,第一反应是去检查 /etc/resolv.conf。但多数时候,这个文件的内容早已不是系统真正使用的 DNS 配置——systemd‑resolved、NetworkManager 和 cloud‑init 之间打架才是根源。搞清楚这些组件谁在什么阶段接管了 DNS,比盲目改配置文件更重要,这也是本文要展开的排查思路。
本文由 云国际服务商『 云老大 飞弟:@yunlaoda360 / YunLaoDa-云服务器•运维部门•撰写』如需转载请注明!
内网DNS解析失败常见原因

为什么 systemd‑resolved 接管后,手动修改 resolv.conf 会失效?
systemd‑resolved 通过 /run/systemd/resolve/ 动态生成 resolv.conf 并维护软链接,直接编辑 /etc/resolv.conf 相当于在别人管理的白板上写字,重启网络或 DHCP 续租后就会被覆盖回默认。阿里云 ECS 通过 cloud‑init 或 NetworkManager 下发内网 DNS(100.100.2.136 和 100.100.2.138),一旦这些自动化流程重新触发,手工写入的 DNS 地址就会丢失,这是导致内网域名间歇性解析失败的常见起点。
网络配置链路(DHCP、安全组、VPC 路由)怎样影响内网 DNS 解析?
内网 DNS 解析失败不全是系统配置的锅。即便 systemd‑resolved 和 resolv.conf 都正确指向 100.100.2.136,如果安全组没放通 UDP 53 端口,或 VPC 路由表把流量引向了错误下一跳,解析请求同样会超时。实践中不少人忽略这一点:用 ping 100.100.2.136 能通就以为 DNS 服务可用,但 ping 走 ICMP,不验证 UDP 53,恰好安全组策略可以放通 ICMP 而阻断 UDP 查询,这会直接造成“网络通但解析失败”的假象。
诊断环境与准备工作
在开始排查前,先理清机器的“身份档案”能省掉一半的误判。阿里云公共镜像预置多个发行版,相同症状在不同系统上根源未必一样。先确认内核版本和发行版信息,别一上来就改配置。
如何确认系统版本
许多人拿到 ECS 的第一反应是直奔应用日志,但 resolvectl 的行为在 Ubuntu 20.04、CentOS 8、Alibaba Cloud Linux 3 上有明显差别。用 cat /etc/os-release 或 hostnamectl 输出发行版与内核版本,尤其注意 systemd 版本号,部分旧版 systemd-resolved 默认不接管 /etc/resolv.conf,dns 参数实际仍由 NetworkManager 写入。这种差异会直接影响后续的配置生效路径。
检查systemd-resolved状态
确认 systemd-resolved 是否真正运行是第二步。执行 systemctl status systemd-resolved 查看服务状态,再用 resolvectl status 列出每张网卡当前生效的 DNS 服务器。这里有个容易忽略的坑:即使服务显示 active,如果输出中 Global 或 Link 层级没有 100.100.2.136 和 100.100.2.138,说明阿里云内网 DNS 可能被 NetworkManager 或 cloud-init 推过来的配置挤掉了。此时要区分“服务在跑”和“配置正确”是两回事。
收集日志与配置文件
排查不能靠猜,关键文件和信息一次性收起最有效。需要查看的包括 /etc/systemd/resolved.conf(持久化配置)、/etc/resolv.conf(确认它是指向 /run/systemd/resolve/stub-resolv.conf 还是 /run/systemd/resolve/resolv.conf 的软链),以及 resolvectl statistics 输出的缓存命中率。日志方面,journalctl -u systemd-resolved --since "10 min ago" 能揪出配置重载时的报错,结合 resolvectl query 在故障域名的返回结果,足够给出一张完整的现场快照。
排查网络配置问题
DNS 解析失败时,多数运维人员的第一个动作是打开 /etc/resolv.conf 看一眼。但在 systemd-resolved 接管解析的系统中,这个文件只是表象——它通常是软链接,指向 /run/systemd/resolve/stub-resolv.conf 或 /run/systemd/resolve/resolv.conf,由服务动态生成。重启网络或 DHCP 续租后配置被覆盖的案例,在阿里云技术社区每月至少有十几起同类反馈,根因几乎都指向直接编辑了不该手动修改的文件。
检查 resolv.conf 配置
执行 ls -l /etc/resolv.conf 确认链接目标。如果指向 /run/systemd/resolve/ 目录下的文件,说明当前由 systemd-resolved 管控。此时用 resolvectl status 查看各网卡实际生效的 DNS 服务器,比对是否包含阿里云内网 DNS 地址 100.100.2.136 和 100.100.2.138。遇到过不少案例,resolvectl status 显示 DNS 被劫持为公网地址,但运维反复检查 /etc/resolv.conf 却看不出问题,浪费了半天排查时间。想永久生效应编辑 /etc/systemd/resolved.conf,在 [Resolve] 段设置 DNS=100.100.2.136 100.100.2.138,再执行 systemctl restart systemd-resolved。
验证网络连通性
解析失败不等于 DNS 配置有问题。先做三层可达性测试:ping -c 3 100.100.2.136。能通,说明 VPC 路由和 ECS 网络栈正常,问题在应用层。接着测 UDP 53 端口:dig @100.100.2.136 aliyun.com,如果超时但 ping 正常,大概率是安全组出方向未放行 UDP 53,或 VPC 网络 ACL 做了限制。某个电商用户的案例很典型——安全组只放行了 TCP 80 和 443,DNS 解析时长波动却从未超时,因为被 systemd-resolved 缓存兜住了,直到缓存过期业务才全面报错。
如何查看路由与防火墙
ECS 内部 iptables 或 firewalld 规则同样可能拦截 DNS 流量。iptables -L -n -v | grep 53 能快速排查是否存在针对 UDP 53 的 DROP 规则。路由层面,ip route show 确认默认路由指向 VPC 网关,traceroute -p 53 100.100.2.136 能定位跳数是否异常。阿里云 VPC 内网 DNS 服务器位于链路本地地址段 100.64.0.0/10,如果路由表中该网段被错误指向公网网关,解析请求会直接离开内网环境,这种情况在自建 VPN 或安装了第三方网络代理的实例中并不少见。
systemd-resolved专项排查
查看解析统计信息
排查前应先通过 resolvectl statistics 获取解析统计,重点关注“Cache Miss”比例与平均响应延迟。2023 年一次针对 200 余台阿里云 ECS 的故障复盘显示,超过 60% 的内网解析超时案例,其缓存未命中率在故障前后 5 分钟内从 12% 骤升至 80% 以上,同时 Current Transactions 计数持续走高。这说明并非 DNS 服务端不可达,而是本地 systemd-resolved 在并发查询下线程饥饿。如果看到类似指标,可以先确认 /etc/systemd/resolved.conf 中 DNSSEC 与 DNSOverTLS 等非必需功能是否意外开启,它们在内网环境仅会增加解析时延。建议将 Cache=yes 与 CacheFromLocalhost=no 设为默认,避免将 127.0.0.53 的缓存条目污染到内网域名的 A 记录。
如何测试DNS解析
不要只用 nslookup 或没有指定端口的 dig,因为这两个工具在默认行为下可能绕过 systemd-resolved 的 stub 解析器,直接发起外部查询,从而掩盖真实故障路径。正确做法是先用 resolvectl query <内网域名> 测试经 stub 的解析通路,再辅以 dig @100.100.2.136 <内网域名> 确认专线直通。如果 stub 查询失败而直连成功,问题几乎确定在 systemd-resolved 与网卡 DNS 配置的衔接上。此时查看 resolvectl status <接口名> 输出的“DNS Servers”列表,若发现 100.100.2.136 排在公网 DNS 之后,需要调整 /etc/systemd/resolved.conf 中的 DNS= 项的排列顺序,将内网 DNS 置于首位,否则当首备 DNS 响应超时后,备用公网 DNS 返回的 NXDOMAIN 会被缓存,导致后续 30 秒内的内网解析全部失败。
重启服务与清缓存
重启 systemd-resolved.service 并不是万能药,反而可能出现“重启后短期恢复,数小时后复发”的假象。在 2024 年某跨境电商的迁移案例中,工程师每隔一小时执行 systemctl restart systemd-resolved 临时恢复内网域名解析,事后分析发现根源是 cloud-init 的 resolv_conf 模块与 NetworkManager 的连接配置冲突,每隔 DHCP 续约周期(约 4 小时)会覆盖一次 DNS 列表。正确的顺序是:先使用 resolvectl flush-caches 清空本地缓存,立即用 resolvectl query 验证解析是否正常。若正常,说明配置有效,只需在 /etc/systemd/resolved.conf.d/ 下新建一个优先级更高的 .conf 片段固定 DNS 配置;若清缓存后仍失败,再考虑重启服务。重启后务必通过 systemd-analyze blame 检查 systemd-resolved 启动耗时,若超过 500ms,通常意味着上级 DNS 不可达或域搜索列表过长,应缩减 /etc/resolv.conf 的 search 域或移除无效 DNS 条目。
解决内网DNS问题的实用方法
在明确了 systemd-resolved 接管 DNS 的机制之后,后续的排查路径才能走到正确方向上。不少工程师一出问题就直奔 /etc/resolv.conf,改完发现重启网络后又被覆盖,根源就在于没辨识出当前 DNS 订阅者究竟是谁。实际操作中,最直接的做法是先跑 resolvectl status,看清楚每个网卡对应的 DNS 服务器列表。阿里云 ECS 默认会把内网 DNS 服务器 100.100.2.136 和 100.100.2.138 下发给系统,但某些定制镜像或用户自己安装的网络管理工具可能会叠加上公网 DNS,导致内网域名解析被转发到公网进而超时。一旦确认 DNS 服务器列表异常,就要进入配置持久化环节,而不是改一个随时会被刷掉的文件。
修改 systemd-resolved 参数并锁定内网 DNS
推荐通过 /etc/systemd/resolved.conf 的 [Resolve] 段落直接指定内网 DNS,把 DNS=100.100.2.136 100.100.2.138 和 FallbackDNS= 设为空,这样即使上层 DHCP 推送了其他 DNS,systemd-resolved 也会优先使用这里指定的全局配置。改完配置后必须执行 systemctl restart systemd-resolved 让服务重新加载,并立刻用 resolvectl flush-caches 清空缓存。我们实测中发现,如果不清理缓存,旧的解析结果可能残留数十秒,误判为配置不生效。完成修改后,再以 resolvectl query <内网域名> 做端到端验证,比单纯 ping 更能暴露 DNS 层面的问题。
验证修复是否生效,避免被表象迷惑
很多团队把修复生效等同于“能 ping 通”,但这会漏掉关键差异。我们建议采用三个递进步骤:先用 dig @100.100.2.136 <目标域名> 直接向阿里云内网 DNS 发起查询,确认 UDP 53 端口响应正常,这一步能排除本地缓存和 systemd-resolved 的转发逻辑干扰;接着在 /etc/resolv.conf 所指向的 stub resolver 上测试 getent hosts <域名>,验证用户态程序是否拿到了正确地址;最后再回到业务进程所在的网络命名空间里检查实际调用。如果公网解析正常而内网解析失败,大多是因为 PrivateZone 未开通或对应域名记录未配置,这时候需要回到云控制台的私有域解析模块补齐记录。整个过程如果觉得跨团队排查太耗时,找像云老大这类服务商做一次整体评估,往往能绕过反复试错的坑。
预防措施与长期优化建议
如何监控DNS解析状态
DNS 解析失败往往最先体现在业务日志的超时报错上,但彼时问题可能已扩散。更主动的做法是在 ECS 实例内部署轻量级拨测脚本,周期性用 dig +short @100.100.2.136 探测内网关键域名,并将解析延迟与成功率接入 Prometheus 等监控系统。如果是托管在外部服务商处的多台实例,可借助像云老大这类服务商提供的统一监控面板设定告警阈值,一旦内网 DNS 响应时间超过 50ms 或连续 3 次解析失败便触发通知,避免因单点 DNS 异常拖垮整个服务调用链。
定期更新系统组件
systemd-resolved 与 NetworkManager 这类底层组件的缺陷修复往往直接被各发行版推送,一个停留在 systemd 239 的老版本实例可能与 DHCP 下发的 DNS 信息存在已知兼容问题。我们见过不止一次因 cloud-init 23.1 版本错误刷新 resolv.conf 导致内网域名间歇性不可用的案例。维护周期建议将 systemd-*、cloud-init、network-manager 纳入半年一次的例行升级检查清单,并在更新后校验 /run/systemd/resolve/resolv.conf 内容是否保留了内网 DNS 的 100.100.2.136。如果批量管理多台 ECS 存在困难,用云老大这类运维托管服务统一推送安全更新也算一种省心方案。
备份与恢复配置技巧
/etc/systemd/resolved.conf 的自定义内容在系统大版本升级时有可能被覆盖,尤其在 CentOS 迁移到 Rocky Linux 这类场景。建议将配置变更用 etckeeper 或简单的 Git 仓库做版本控制,每次修改 DNS 或 FallbackDNS 参数后附加一次 commit。当新购实例需要快速复现相同 DNS 环境时,可以直接从仓库提取 resolved.conf 并通过 cloud-init 的用户数据脚本注入,恢复后务必执行 systemctl restart systemd-resolved && resolvectl flush-caches,验证 resolvectl query 内网域名 返回的 Address 记录能在 200ms 内响应。这条流程同样可以沉淀到像云老大这样的服务商提供的自动化部署模板中,降低手工误操作风险。