AberSheeran
Aber Sheeran

基于抢占式 Keepalived 的健康检查设计

起笔自
所属文集: 程序杂记
共计 1728 个字符
落笔于

Keepalived 有两种模式,抢占式与非抢占式。抢占式遵循优先级高者得 Virtual IP 的理念,当本机健康检查失败、优先级下降后,如果网内存在其他优先级更高的主机,则 Virtual IP 发生转移。非抢占式则是一台服务器始终占据 Virtual IP 直到出现自身关机、断网等情况。

为了让 Virtual IP 在服务异常后切换,非抢占式显然是不满足的。而抢占式又存在一个问题:当设定的备服务器拿到 Virtual IP 后,如果主服务器恢复正常则 Virtual IP 会再度切换回主服务器,而我期望它在备服务器上服务异常之前都不要切换回去。单纯的检查本机服务是否正常是不满足这种需求的。

健康检查脚本设计

先定义好四个变量,以供后续使用。分别是 Virtual IP 地址、主机在网络中的真实 IP 地址、通信网关以及网卡名称。并且设定主服务器的优先级仅比备服务器高 1,而检查失败则扣除 2 优先级。

VIP=virtual_ip
IP=source_ip
GATEWAY=gateway
INTERFACE=interface

检查网络连通性

在健康检查脚本里,我们首先应当检查和网关的线路是不是还能保持通畅。对于一个能被外界连通的双机系统来说,网关是唯一可靠且存在的第三方仲裁者。这里采用 arping 命令判断和网关的连通性,相比于可能被关闭的 ICMP 协议(ping)来说更加可靠一些。

/sbin/arping -I $INTERFACE -q -c 1 -w 1 -s $IP $GATEWAY
if [ $? -ne 0 ]; then
    exit 1;
fi

检查是否处于切换状态

当处于切换到 MASTER 的状态时,始终返回 0,以保证切换时不会出现健康检查失败从而降低优先级导致又切换回去的情况。同理,处于切换到 BACKUP 的状态时始终返回 1,使优先级不会上升。

be_master=$(ps -ef | grep /opt/ha/be_master.sh | grep -v "grep" | wc -l)
if [ $be_master -ne 0 ]; then
    exit 0;
fi

be_backup=$(ps -ef | grep /opt/ha/be_backup.sh | grep -v "grep" | wc -l)
if [ $be_backup -ne 0 ]; then
    exit 1;
fi

检查 Virtual IP 是否存在

当 Virtual IP 在本机上时,正常检查服务状态。如果不在本机上,会有两种情况:

  • 本机是预设好的备服务器——那么此时与设计一致,主服务器优先级本就比备服务器高,返回 0 即可。
  • 本机是预设的主服务器——此时意味着备服务器获得了 Virtual IP,为了避免主服务器恢复正常后直接抢回 Virtual IP,必须返回 1,强制让主服务器优先级降低 2,从而比备服务器低。当备服务器上服务出现问题时,优先级降 2,Virtual IP 就能重新回到主服务器。双方就再次进入初始的优先级状态。
is_master=$(ip addr show $INTERFACE | grep $VIP | wc -l)
if [ $is_master"" -ne "1" ]; then
    if [ $(hostname)"" = "backup-node" ]; then
        exit 0;
    else
        exit 1;
    fi
fi

检查服务状态

这一步就因编写的服务不同而异,在此不具体描述,也没法具体描述。

总结

如上脚本满足了如下几个需求:

  • 双机脑裂——通过引入网关这个第三方来解决。
  • 解决因为切换时的检查问题导致的反复切换
  • 当一台服务器获取 Virtual IP 后即使另一台服务器状态正常也不会抢占,且运行的服务异常时能正常切换。
如果你觉得本文值得,不妨赏杯茶
写函数式的 Python
Type hint 在定义数据模型时的应用