Keepalived--05--脑裂问题

本文详细介绍了高可用系统中可能出现的'脑裂'现象及其原因,包括网络故障、心跳线断开等。针对此问题,提出了添加冗余心跳线、启用磁盘锁和设置仲裁机制等对策。同时,通过编写vrrp_script和track_script脚本,实现了对服务状态和网络状态的自动检测,当出现问题时自动停止或重启keepalived服务,以避免'脑裂'情况的发生。此外,还提供了一个定时任务脚本check_keepalived.sh,用于在服务恢复后自动重启keepalived。这些自动化手段能有效提高系统的稳定性和容错能力。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、问题

1.1、 场景(高可用)

在高可用(HA)系统中,当联系2个节点的"心跳线"断开时,本来为一整体、动作协调的HA系统,就分裂成为2个独立的个体。由于相互失去了联系,都以为是对方出了故障。两个节点上的HA软件像"裂脑人"一样,争抢"共享资源"、争起"应用服务",就会发生严重后果——或者共享资源被瓜分、2边"服务"都起不来了;或者2边"服务"都起来了,但同时读写"共享存储",导致数据损坏(常见如数据库轮询着的联机日志出错)。

1.2、 场景2(主备模式)

假设节点A和B组成主备关系,A为备用节点,B为主节点,那么当在图标红叉位置发生网络故障时,节点A接收不到节点B的组播通知,将抢占虚拟IP。这时出现的后果就是节点A和节点B均拥有虚拟IP,就可能导致了脑裂

在这里插入图片描述

1.3、脑裂产生的原因

  1. 高可用服务器对之间心跳线链路发生故障,导致无法正常通信。
    1. 因心跳线坏了(包括断了,老化)。
    2. 因网卡及相关驱动坏了,ip配置及冲突问题(网卡直连)
    3. 因心跳线间连接的设备故障(网卡及交换机)
    4. 因仲裁的机器出问题(采用仲裁的方案)。
  2. 高可用服务器上开启了 iptables防火墙阻挡了心跳消息传输。
  3. 高可用服务器上心跳网卡地址等信息配置不正确,导致发送心跳失败。
  4. 其他服务配置不当等原因,如心跳方式不同,心跳广插冲突、软件Bug等。
  5. 提示: Keepalived配置里同一 VRRP实例如果 virtual_router_id两端参数配置不一致也会导致裂脑问题发生。
  6. 服务器网线松动等网络故障

1.4、对付HA系统"裂脑"的对策,目前达成共识的的大概有以下几条

  1. 添加冗余的心跳线,例如:双线条线(心跳线也HA),尽量减少"裂脑"发生几率;

  2. 启用磁盘锁。

    1. 正在服务一方锁住共享磁盘,“裂脑"发生时,让对方完全"抢不走"共享磁盘资源。但使用锁磁盘也会有一个不小的问题,如果占用共享盘的一方不主动"解锁”,另一方就永远得不到共享磁盘。现实中假如服务节点突然死机或崩溃,就不可能执行解锁命令。后备节点也就接管不了共享资源和应用服务。于是有人在HA中设计了"智能"锁。即:正在服务的一方只在发现心跳线全部断开(察觉不到对端)时才启用磁盘锁。平时就不上锁了。
  3. 设置仲裁机制。例如设置参考IP(如网关IP),当心跳线完全断开时,2个节点都各自ping一下参考IP,不通则表明断点就出在本端。不仅"心跳"、还兼对外"服务"的本端网络链路断了,即使启动(或继续)应用服务也没有用了,那就主动放弃竞争,让能够ping通参考IP的一端去起服务。更保险一些,ping不通参考IP的一方干脆就自我重启,以彻底释放有可能还占用着的那些共享资源。

1.5、思考

为了解决上面的问题,每个节点应该定时去判断自身的应用服务状态及自身网络状态。
当自身应用服务异常、或无法ping通网关,则认为自身出现故障,停止keepalived服务。

二、解决问题

2.1、通过vrrp_script及track_script实现

在keepalived的配置文件最前面加入以下代码,定义一个跟踪脚本:

# 定义一个名称为check_local的检查脚本
vrrp_script check_local { 
	#shell脚本的路径
	script "/usr/local/keepalived/bin/check_local.sh"
	
	#运行间隔
	interval 5 
}

再在vrrp_instance配置中加入以下代码使用上面定义的检测脚本

track_script {
  check_local
}
check_local.sh 检测规则是
  1. 自身web服务故障(超时或者http返回状态不是200)
  2. 无法ping通网关
  3. 产生以上任何一个问题,停止keepalived实例
check_local.sh 缺陷
  1. 当停止掉keepalived服务,那么当故障恢复后,keepalived是无法自动恢复的。

所以我们需要一个定时任务脚本,当障恢复后,keepalived重启。这个脚本要加入到cron任务中。

2.2、定时任务脚本,当障恢复后,keepalived重启

在每个节点运行shell脚本(check_service.sh)检测本机的服务是否正常

  1. 如果本地服务连续三次检测失败,停止掉本机的keepalived, 如此虚拟IP自动转移到备用机器之上
  2. 如果本地服务连接三次检测成功,但keepalived没有启动,则启动之,以达到故障恢复之目的。
    1. 这个可以解本机或是网关偶尔出现一次故障,但是被我们关掉的keepalived问题
check_keepalived.sh
#!/bin/bash

MYSQL=mysql
MYSQL_USER=root
MYSQL_PASSWORD=Fwfk~2021
 
 


maxfails=3
fails=0
success=0

while [ 1 ]
do
	# 当mysql 连接不上的时候
  $MYSQL -u $MYSQL_USER -p$MYSQL_PASSWORD -e "show status;" >/dev/null 2>&1
  if [ $? -ne 0 ] ; then
		# 错误次数+1
    let fails=$[$fails+1]
    success=0
  else
		# 当mysql 连接上的时候,成功次数
    fails=0
    let success=$[$success+1]
  fi

	# 如果失败次数大于最大失败次数,关闭keepalived
  if [ $fails -ge $maxfails ] ; then
    fails=0
    success=0

		# 检查 keepalived 是否运行,运行就关闭
    service keepalived status | grep running
    if [ $? -eq 0 ] ; then
      logger -is "当前mysql连接不上,关闭keepalived"
      service keepalived stop 2>&1 | logger
    fi
		
  fi

  if [ $success -gt $maxfails ] ; then
		# 检查 keepalived 是否停止,停止就重启
    service keepalived status | grep stopped
    if [ $? -eq 0 ] ; then
      logger -is "mysql 多次尝试连接,都正常,启动mysql"
      service keepalived start
    fi
    success=0
  fi
  sleep 3
done

关键的执行点,均已经记录到系统日志中(/var/log/messages)

2.3、添加定制任务

sudo crontab -e

内容

*/1 * * * * /etc/keepalived/check_mysql.sh

2.4、测试

  1. 停止掉本机的keepalived, 稍过一会,就会keepalived服务被自动启动了

    1. 因为检测mysql服务,3次都是正常的,就重启keepalived服务
  2. 停止掉本机的mysql, 稍过一会,就会发现keepalived服务也被停止掉了,再启动mysql, 稍过一会,发现keepalived也被正常启动,并绑定了正确的虚拟IP

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值