用 LD_PRELOAD 解决容器环境中的 Chrome ERR_NETWORK_CHANGED
运行 Playwright 自动化测试时,我们遇到过一种很难稳定复现的失败:页面正在正常加载,Chrome 却突然报错: net::ERR_NETWORK_CHANGED 它看起来像目标服务断网,但实际检查后发现: 被访问的服务没有重启 Pod 本身的网络仍然可用 同一时刻,Pod 内的容器引擎正在创建或销毁其他容器 重试通常又能成功 真正变化的不是 Chrome 正在使用的网络,而是同一网络命名空间中的虚拟网卡。 为什么启动容器会影响 Chrome 在服务器运行 Docker 时,每次创建或销毁容器,都可能伴随这些操作: 创建或删除 veth 设备 给虚拟网卡增加或移除 IP 地址 更新链路状态和路由信息 这些变化会通过 Linux Netlink 机制通知用户空间。Chrome 恰好也是这些通知的订阅者。 Chromium 在 Linux 上使用 AddressTrackerLinux 跟踪网络状态。初始化时,它会创建一个路由 Netlink 套接字: netlink_fd_.reset(socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)); 随后订阅多组网络事件: addr.nl_groups = RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR | RTMGRP_NOTIFY | RTMGRP_LINK; 因此,同一网络命名空间里任何网卡的地址或链路发生变化,都可能被 Chrome 观察到。事件再经由 NetworkChangeNotifierLinux 向网络栈传播,最终让正在进行的请求以 ERR_NETWORK_CHANGED 结束。 整个链路可以简化成: 创建或销毁容器 ↓ 虚拟网卡、IP 或链路状态变化 ↓ 内核发送 NETLINK_ROUTE 消息 ↓ Chrome 的 AddressTrackerLinux 收到变化 ↓ NetworkChangeNotifier 通知网络栈 ↓ 正在进行的请求被中断 Chrome 的行为对桌面用户是合理的。例如从 Wi-Fi 切换到有线网络后,旧连接确实可能已经失效。但在 CI 中,其他容器产生的虚拟网卡变化通常与浏览器访问的目标毫无关系。 ...