我在ECS被内网DNS卡住两小时

举报
yd_272744321 发表于 2026/11/09 13:04:02 2026/11/09
【摘要】 我在华为云 ECS 升级网关后遇到间歇性 502,排查了 2 小时 17 分钟才确认根因是 cloud-init 回写 DNS,导致 systemd-resolved 轮询到不可达地址。这里记录我当晚的日志、命令、配置改动、恢复数据和实际多花的费用。

故障是从 502 告警开始的

周二 22:14,CES 告警直接打到值班电话,规则是 gateway_5xx_ratio > 3% 且连续两个 5 分钟窗口触发。图上 22:10 到 22:15 从 0.3% 抬到 7.8%,同一时间 RPS 只有 1.9k,没有流量突刺。21:52 我刚把网关从 v2.19.2 升到 v2.19.3,发布单号是 rel-20261015-2152,我当时把排查重心全压在回归问题上。

那一刻我还坚信是发布回归。

2026-10-15T22:16:07.441+08:00 ERROR upstream call failed request_id=7f2e0f
 dial tcp: lookup user-api.svc.prod.internal on 127.0.0.53:53:
 read udp 127.0.0.1:58873->127.0.0.53:53: i/o timeout

2026-10-15T22:16:08.009+08:00 ERROR retry failed request_id=7f2e0f
 Get http://user-api.svc.prod.internal/profile:
 dial tcp: lookup user-api.svc.prod.internal: server misbehaving

2026-10-15T22:16:08.010+08:00 WARN  upstream timeout cost=2001ms route=/profile
2026-10-15T22:16:08.011+08:00 INFO  retry policy exhausted max_retry=1

环境我当晚记得很细,华北乌兰察布 3 台 ECS,c6.large.2,2 vCPU 4 GiB,Ubuntu 22.04.4 LTS,内核 5.15.0-113-generic。网关是 Go 1.22.2 编译,systemd 249.11,Docker 24.0.7。VPC 内网域名在 PrivateZone,后缀 svc.prod.internal。安全组 sg-bp1f2*** 只放了 TCP 443,UDP 53 压根没开。成本也顺手算了,ECS 按量 0.312 元/小时/台,三台 0.936 元/小时,ELB 0.06 元/小时,预发布多挂 9 小时多花 8.91 元。

22:20 到 22:48 我在应用层绕了好几圈。回滚命令是 docker service update --image gateway:v2.19.2 prod_gateway,滚动参数 --update-parallelism 1 --update-delay 10s,三台机器走完用了 6 分 40 秒。5xx 从 7.8% 降到 5.9%,没回到基线。我又翻了线程池和连接池,maxIdleConns=512,maxConnsPerHost=1024,CPU 31%,内存 2.1 GiB,goroutine 峰值 486,GC pause p99 14ms,网卡丢包也接近 0。这些指标看不出资源打满,我才把怀疑点挪到 DNS。

这个判断后来证明确实带偏了我。

dig @100.125.1.250 user-api.svc.prod.internal +time=1 +tries=1
; Query time: 3 msec

for i in $(seq 1 20); do dig @127.0.0.53 user-api.svc.prod.internal +time=1 +tries=1 >/dev/null || echo timeout-$i; done
timeout-3
timeout-6
timeout-11
timeout-14
timeout-18
timeout-20

for i in $(seq 1 20); do getent hosts user-api.svc.prod.internal >/dev/null || echo fail-$i; done
fail-4
fail-9
fail-12
fail-17
fail-19
fail-20

22:34 我做了一个失败尝试,给网关加 GODEBUG=netdns=go+1,想绕开 systemd-resolved。具体改法是 systemctl edit gateway,写入 drop-in:

[Service]
Environment='GODEBUG=netdns=go+1'

然后 systemctl daemon-reload && systemctl restart gateway。日志里确实有 go package net: using the Go DNS resolver,但 22:41 到 22:46 的 5xx 还是 6.1%,几乎没动。我又补了一次 resolvectl flush-caches,再看错误依旧是 read udp ... ->127.0.0.53:53: i/o timeout,这一轮重启只换来了 90 秒抖动窗口。

根因和修复动作

22:49 我跑 resolvectl status 才看到关键线索,ens3 同时挂了 100.125.1.250 和 8.8.8.8。/etc/resolv.conf 里写的是 nameserver 127.0.0.53,应用实际都走本地 stub。问题在于 resolved 会轮询上游 DNS,轮到 8.8.8.8 时 UDP 53 从 NAT 出不去,默认等 5 秒超时;而网关 upstream 超时阈值只有 2 秒,结果就变成随机 502。

Link 2 (ens3)
    Current Scopes: DNS
    DNS Servers: 100.125.1.250 8.8.8.8
    DNS Domain: ~.

# /etc/netplan/50-cloud-init.yaml
network:
  version: 2
  ethernets:
    ens3:
      dhcp4: true
      nameservers:
        addresses:
          - 100.125.1.250
          - 8.8.8.8

8.8.8.8 是基础镜像里遗留的旧配置,cloud-init 每次开机会把 netplan 回写。22:57 我抓了 60 秒包,现象非常直观,发给 8.8.8.8 的 UDP 包每隔几秒一条,没有返回;发给 100.125.1.250 是毫秒级来回。这个证据出来后我才停掉“可能是代码”的猜测。

sudo tcpdump -ni ens3 '(udp port 53) and (host 8.8.8.8 or host 100.125.1.250)'
22:57:11.102310 IP 10.0.3.17.40321 > 8.8.8.8.53: 42111+ A? user-api.svc.prod.internal. (46)
22:57:16.103004 IP 10.0.3.17.40219 > 8.8.8.8.53: 42112+ A? user-api.svc.prod.internal. (46)
22:57:16.106889 IP 10.0.3.17.44773 > 100.125.1.250.53: 19402+ A? user-api.svc.prod.internal. (46)
22:57:16.109771 IP 100.125.1.250.53 > 10.0.3.17.44773: 19402 1/0/0 A 10.0.8.24 (62)

23:06 我按顺序动配置。第一处是固定 resolved 只用 VPC DNS,并把 FallbackDNS 清空。第二处是禁掉 cloud-init 的网络接管,避免重启后 8.8.8.8 回来。我第一次执行时漏了软链,导致容器里读到的仍是旧 resolv.conf,5xx 只从 5.6% 掉到 3.2%,这算当晚第二次返工。补上 ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf 后再重启网关,曲线才真正落回去。

# /etc/systemd/resolved.conf.d/internal-dns.conf
[Resolve]
DNS=100.125.1.250
FallbackDNS=
DNSSEC=no

# /etc/cloud/cloud.cfg.d/99-disable-network-config.cfg
network: {config: disabled}

sudo netplan apply
sudo systemctl restart systemd-resolved
sudo ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf
sudo systemctl restart gateway

23:19 以后告警回到正常区间,5xx 稳在 0.2% 到 0.4%。我用 wrk -t4 -c64 -d60s http://gateway/profile 连跑两轮,修复前抽样 500 次里有 71 次 DNS 失败,修复后是 0/1000。接口延迟 p95 从 2.4s 回到 180ms,p99 从 4.8s 回到 310ms。resolvectl statistics 里 Transaction Timeout 从每分钟 12 到 18 次降到 0,盯了 40 分钟都没再抖。

从 22:14 收到告警到 00:31 关观察窗口,一共 2 小时 17 分钟,真正改配置不到 15 分钟。

现在还没收尾的有两件事,我准备把 100.125.1.250 改成启动时从 metadata 拉取并渲染到 resolved 配置,跨可用区复制环境时少手工改 YAML;另一个是把 DNS 失败从 upstream timeout 里拆成独立指标,上报 error_type=dns_timeout 和 resolver=systemd 两个标签,值班时我可以更快排除“像回归但不是回归”的噪音。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。