排查 pulumi preview 在本地卡住的问题
在使用 Pulumi 管理 Azure 上的资源时,我遇到一个长期困扰的问题:在本地执行 pulumi preview 命令时,整个过程非常慢,甚至经常会卡住不动。我常以为是网络问题,但最终发现是一个出乎意料的外部因素导致的……
问题描述 🔗
当我在本地电脑执行 pulumi preview、pulumi import 等命令排查问题或执行特定操作时,这些命令长时间没有任何输出。另外,当使用 SD-WAN 软件连接专有网络后,却不会出现这个问题。我怀疑这是网络问题,但似乎又不完全是,因为我在本地可以使用 az 命令正常访问 Azure 资源。
排查过程 🔗
经过一般搜索,发现可以使用 strace 命令获取一些诊断信息,比如:
strace -f -e trace=network,connect,recvmsg pulumi preview 2>&1 | tee trace.txt
执行该命令会产生大量输出。最终,它会暂停,然后不断地输出如下内容:
[pid 251511] socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, IPPROTO_IP) = 6
[pid 251511] connect(6, {sa_family=AF_INET, sin_port=htons(80), sin_addr=inet_addr("169.254.169.254")}, 16) = -1 EINPROGRESS (Operation now in progress)
[pid 251511] --- SIGURG {si_signo=SIGURG, si_code=SI_TKILL, si_pid=251506, si_uid=1000} ---
[pid 251511] getsockopt(6, SOL_SOCKET, SO_ERROR, [0], [4]) = 0
[pid 251511] getpeername(6, {sa_family=AF_INET, sin_port=htons(80), sin_addr=inet_addr("169.254.169.254")}, [112 => 16]) = 0
[pid 251511] getsockname(6, {sa_family=AF_INET, sin_port=htons(46948), sin_addr=inet_addr("192.168.40.115")}, [112 => 16]) = 0
[pid 251511] setsockopt(6, SOL_TCP, TCP_NODELAY, [1], 4) = 0
[pid 251511] setsockopt(6, SOL_SOCKET, SO_KEEPALIVE, [1], 4) = 0
[pid 251511] setsockopt(6, SOL_TCP, TCP_KEEPIDLE, [30], 4) = 0
[pid 251511] setsockopt(6, SOL_TCP, TCP_KEEPINTVL, [15], 4) = 0
[pid 251511] setsockopt(6, SOL_TCP, TCP_KEEPCNT, [9], 4) = 0
从这里可以看到,Pulumi 在尝试连接一个 IP 地址为 169.254.169.254 的地址。显然,这是一个私有地址,通常被称为“链路本地地址”(Link-Local Address),通常是无法访问的。当我尝试在使用 curl http://169.254.169.254 时,居然发现这个地址返回了 HTML 页面。
当我用 Android 手机,访问这个地址时,居然打开了家里的光猫管理界面!光猫居然把这个地址路由到了它自己!
这几乎可以确定:Pulumi 在执行 preview 时会尝试访问 Azure 的 IMDS(Instance Metadata Service),其地址为 169.254.169.254。Pulumi 很可能在判断是否在 Azure 环境中运行时,访问该地址以获取环境信息。由于该地址在我的网络环境中被路由到了光猫,光猫返回了一个无关的响应(可能是登录页面),Pulumi 因而重试,导致整个 preview 过程卡住。
我又在 Windows 上的 Chrome 浏览器里打开 http://169.254.169.254,结果显示:
This site can’t be reached
http://169.254.169.254/ is unreachable.
Try running Windows Network Diagnostics.
ERR_ADDRESS_UNREACHABLE
最终结论:
- 在我的家庭网络中,当使用 Linux、WSL2 或 Android 时,访问 169.254.169.254 会被路由到光猫,导致 Pulumi 的
preview卡住。 - 我在使用 WSL2 并启用 SD-WAN 软件时,发往 169.254.169.254 的请求很可能被 SD-WAN 拦截,因此避免了卡住的问题。
- 在 Windows 系统上访问 169.254.169.254 时,Windows 网络栈可能会将其识别为不可达地址,直接返回 UNREACHABLE 错误,而不是路由到默认网关,因此很可能不会卡住。
解决方法 🔗
在 WSL2 中,可以通过添加一个黑洞路由来阻止访问:
sudo ip route add blackhole 169.254.169.254
如果想删除这条路由,可以使用:
sudo ip route del blackhole 169.254.169.254
备注 🔗
169.254.169.254 是 Azure、AWS、GCP 等云服务商的 IMDS(Instance Metadata Service)的默认地址。这地址通常在云环境中可访问,用于获取实例的元数据和环境信息。