Keepalived-脑裂
什么是脑裂?
在高可用(HA)系统中,当主备节点之间的心跳线断开时,双方无法检测到对方状态,均认为自身是主节点,导致系统分裂为两个独立部分。此时:
- 双方可能同时抢占共享资源(如VIP),造成服务冲突。
- 若涉及有状态服务(如数据库),可能导致数据损坏(如双写冲突)
脑裂产生的原因
网络问题
- 心跳线故障(断线、老化、网卡/交换机故障)。
- 防火墙阻挡VRRP协议(如未放行组播地址
224.0.0.18)。 - 网卡配置错误或IP冲突。
配置错误
- 主备节点
virtual_router_id不一致。 - 心跳间隔(
advert_int)或超时时间设置不合理。
- 主备节点
其他因素
- 仲裁节点故障(若使用第三方仲裁)。
- Keepalived软件Bug或资源竞争。
脑裂的解决方案
冗余心跳线路
- 同时使用以太网和串行电缆,避免单点故障。
配置优化
- 确保主备节点
virtual_router_id、auth_pass一致。 - 启用非抢占模式(
nopreempt),避免主节点恢复后重新抢占VIP。
第三方仲裁
通过脚本定期检测网关或参考IP,若无法连通则自动降级或重启Keepalived:
bash
#!/bin/bash
# 双检测仲裁脚本(业务端口+网关)
VIP="192.168.1.100"
GATEWAY="192.168.1.1"
PORT=80 # 业务服务端口
FAIL_COUNT_THRESHOLD=3
LOG_FILE="/var/log/keepalived_arbiter.log"
check_service() {
# 检测本地业务端口是否活跃
if ! nc -z localhost $PORT &>/dev/null; then
return 1
fi
return 0
}
check_gateway() {
if ! ping -c 2 -W 3 $GATEWAY &>/dev/null; then
return 1
fi
return 0
}
LOG_FILE="/var/log/check_nginx.log"
function log() {
local level="${2:-INFO}" # 默认日志级别
echo "[$(date '+%F %T')] [$level] $1" | tee -a "$LOG_FILE"
}
if ip addr show eth0 | grep -q $VIP; then
FAIL_COUNT=0
while [ $FAIL_COUNT -lt $FAIL_COUNT_THRESHOLD ]; do
if ! check_gateway || ! check_service; then
FAIL_COUNT=$((FAIL_COUNT + 1))
log "检测失败: 网关或端口不可达 (次数: $FAIL_COUNT)" "ERROR"
else
break
fi
sleep 5
done
if [ $FAIL_COUNT -ge $FAIL_COUNT_THRESHOLD ]; then
log "仲裁生效: 停止Keepalived"
systemctl stop keepalived
fi
fi