记一次循环依赖导致的运维小事故¶
背景¶
每次没有 UPS 或 UPS 容量不够用的倒闸对于运维来说都是一次鸡飞狗跳。这次很不幸,鸡飞狗跳终于轮到了我,还好花了一个半小时还是解决了。在这里做个简单的复盘。
现象与排查¶
首先介绍一下现象:停电恢复之后,服务器开起来,但是无法从互联网连接内网的网关(即主网关)。还好,之前考虑到网关的重要性,做了备份,走内网的备用网关顺利进入了内网,然后发现主网关即使 IP 地址是对的,也连不上互联网。虽然通过 keepalived 的配置,主网关和备用网关会通过虚拟 IP 给内网机器提供一个高可用的默认网关,但由于 keepalived 只是检测了机器是否开机,并没有判断能否正常访问互联网,所以 keepalived 总会选择优先级更高的主网关,导致虚拟 IP 指向主网关,因而内网的机器都连不上互联网,还得继续尝试修复主网关。
主网关运行在 ESXi 的虚拟机里,于是进入 ESXi 管理网页,看看它的网络情况。这个虚拟机的网络用的并不是 ESXi 的普通网络,而是通过 vCSA 配置的基于 DS 的 LACP。看了几个不同的 ESXi,发现问题都集中在 LACP 上。而 ESXi 是没法配置 DS 的,所以就先去看了 vCSA。连上 vCSA 以后一看,所有的 ESXi 都掉线了。原来,之前为了方便配置,vCSA 都是通过域名连接 ESXi 的,而域名就需要有 DNS 服务器解析,然而主网关连不上互联网,也就连不上配置好的互联网的 DNS 服务器,于是 vCSA 无法配置 ESXi,然后 ESXi 的部分虚拟机就会断网,正好主网关又在被断网的虚拟机里面。这就形成了一个循环依赖。
既然找到了问题,那就需要打破循环依赖:把主网关在 keepalived 里的优先级调低,让备用网关上位。结果这时候发现一个小的问题:备用网关的 NAT 忽然不工作了。排查了一下,发现是因为 net.ipv4.ip_forward = 1 写在了 /etc/sysctl.conf 文件里,而 Debian 升级 Trixie 以后,这个文件已经不会被应用了,而要把内容写到 /etc/sysctl.d/*.conf 里面去,通过 /usr/lib/systemd/systemd-sysctl --cat-config 来确认是否持久化成功。由于主网关一直工作得很好,备用网关很久都没有做 NAT 了,导致这个问题一直没有被发现。
修好以后,vCSA 就能找回 ESXi 了,然后通过 vCSA 再重新配置一下 ESXi 的 DS LACP 网卡,然后一切就恢复了。
反思¶
虽然事故解决了,但这个过程中暴露了很多问题:
- 首先就是循环依赖:ESXi 的 DS LACP 依赖 vCSA,vCSA 依赖 DNS,DNS 依赖主网关,主网关通过 DS LACP 访问互联网。如果没有准备好备用网关,且备用网关恰好没有用 DS LACP 因此不受影响,那么修复起来就更麻烦了。解决循环依赖的办法也很简单,对于一些重要的虚拟机(如网关),它所依赖的功能越简单越好。
- 备用网关的 NAT 功能在升级 Debian 版本后,因为没有仔细阅读 sysctl 的变化而失效了,升级后缺少对功能的检查。
- keepalived 只判断机器是否在线,但没有判断机器是否可以正常连接互联网、承担起网关的职能。
- ESXi + vCSA 这类闭源软件,修复起来还是比较痛苦的,很多内部的工作原理并不清楚,可调试性也比较差,以后还是会谨慎选择。