015.keepalived

KeepAlive

在单台负载节点的场景下,如果负载节点宕机,则造成整个业务系统的无法访问,所以此时需要多负载节点作为备用;在多负载节点的场景下,如果主负载节点宕机,如何将业务指向到备用负载节点?修改客户端网关IP可以实现,但在客户端数量较多的情况下工作量巨大,直接将备用负载节点IP修改为主节点的IP也无法实现,这与ARP缓存有关,所以此时需要多节点、自动切换的功能

高可用VRRP原理

高可用通常是指两台相互之间有探测通信的相同的业务系统,一台故障,另一台能自动接管业务。KeepAlive是一款基于VRRP协议实现高可用功能的软件,VRRP通过软件或硬件的形式在主备双节点之外,增加一个虚拟MAC(VMAC)与虚拟IP(VIP),客户端通过请求VIP的形式访问负载节点,无论是主节点或备节点处理客户请求,客户端都只会在ARP缓存表中记录VMAC和VIP的对应关系

高可用需要解决的问题

  • 通过投票选举、设置优先级的方式,确定谁是主节点、谁是备节点
  • 通过抢占式、非抢占式设置,决定主节点故障恢复后是否会抢夺备节点的VIP
  • 解决两个节点都认为自身是主节点的问题(脑裂)

KeepAlive安装

  1. 实践环境
主机名 IP 角色
lb01 10.0.0.5 Master
lb02 10.0.0.6 Backup
VIP 10.0.0.2
  1. 在lb节点上安装keepalived
# lb01
[root@lb01 ~]# yum install -y keepalived
[root@lb01 ~]# rpm -qc keepalived	# 查看配置文件存放路径
[root@lb01 ~]# cp /etc/keepalived/keepalived.conf{,.bak}
[root@lb01 ~]# vim /etc/keepalived/keepalived.conf 
global_defs {	# 全局配置
	router_id lb01	# 表示身份名称
}

vrrp_instance VI_1 {
	state MASTER	# 仅作为角色的标识,真正的角色选择要看优先级
	interface eth1	# 网卡绑定接口
	virtual_router_id 50	# 虚拟路由id,一个网络环境下存在多个keepalived时,通过这个id号来区分keepalive分组
	priority 150	# 优先级
	advert_int 1	# 主备节点检测间隔时间
	authentication {	# 认证
		auth_type PASS	# 明文认证
		auth_pass 1111	# 明文密码
	}
	virtual_ipaddress {	# VIP地址,可以配置多个
		10.0.0.2
	}
}

# lb02

[root@lb02 ~]# vim /etc/keepalived/keepalived.conf
global_defs {
	router_id lb02	# 备节点身份名称
}

vrrp_instance VI_1 {
	state SLAVE	# 备节点角色
	interface eth1
	virtual_router_id 50
	priority 149	# 优先级需要比主节点低
	advert_int 1
	authentication {
		auth_type PASS	# 明文认证
		auth_pass 1111	# 主备节点密码必须一致
	}
	virtual_ipaddress {
		10.0.0.2
	}
}

KeepAlived的日志默认写入/var/log/message,通过/etc/sysconfig/keepalived配置文件能够看到keepalived的默认选项是-D;监视lb02节点的message日志的同时启动keepalived,可以看到keepalived读取了配置文件,并因为没有找到优先级更高的角色而主动获取VIP,此时再启动lb01节点的keepalived,lb02日志因为检测到更高优先级的角色而让出VIP;由此可见KeepAlived默认使用抢占式VIP,抢占式在业务高峰期可能会出现客户端频繁切换网关的情况,影响使用体验

  1. 配置keepalived服务的放行
[root@lb02 ~]# echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf 
[root@lb02 ~]# sysctl -p
[root@lb02 ~]# firewall-cmd --permanent --add-protocol=vrrp
  1. 逐步启动lb02、lb01节点,查看keepalived变化
# 启动lb02备节点,持续查看备节点日志
[root@lb02 ~]# systemctl start keepalived 
[root@lb02 ~]# tail -F /var/log/messages

# 启动lb01主节点后,查看备节点日志,备节点VIP已经移除
Mar 19 13:14:37 lb02 Keepalived_vrrp[2395]: VRRP_Instance(VI_1) Received advert with higher priority 150, ours 149
Mar 19 13:14:37 lb02 Keepalived_vrrp[2395]: VRRP_Instance(VI_1) Entering BACKUP STATE
Mar 19 13:14:37 lb02 Keepalived_vrrp[2395]: VRRP_Instance(VI_1) removing protocol VIPs.

KeepAlived抢占式与非抢占式

默认情况下,Master节点故障后Backup节点会自动接管Master节点的工作并成为Master,但Master节点恢复后它本身会抢占VIP,这在业务繁忙的时间段可能会造成一定的网络波动

# lb01

vrrp_instance VI_1 {
	...
	state BACKUP
	nopreempt	# 添加非抢占参数
	priority 150
	...
}

配置非抢占式KeepAlived建议具备3个条件

  1. 两个节点的state都必须是BACKUP
  2. 两个节点都需要添加nopreempt参数
  3. 其中一个节点的优先级必须要高于另一个节点

这三个建议中,实际只要将主节点的state角色改为BACKUP并添加nopreempt参数即可生效,但仍应尽量保持双节点的配置同步

KeepALived抓包分析

宿主机通过cmd查看本地ARP解析,同时启停一下lb01节点的keepalived服务,观察宿主机的ARP地址解析是否变化,有变化说明keepalived成功向客户端ARP广播过地址发生变化的信息

双节点keepalived服务都正常时,此时VIP在lb01节点上,查看宿主机arp
? (10.0.0.2) at 52:54:00:ba:88:4b [ether] on virbr0

关闭lb01节点的keepalived服务,再次观察宿主机的arp解析
? (10.0.0.2) at 52:54:00:64:23:2a [ether] on virbr0

VRRP包的基本信息,包含虚拟路由ID、优先级、发送频率、认证密码等

VRRP包的基本信息

KeepAlived抢占式立即能够看到源IP的切换

KeepAlived抢占式

双节点配置完全同步测试

在角色和优先级完全一样的情况下,先启动keepalived服务的节点会成为主节点,这样的配置也能够正常使用keepalived服务,但它会影响到要使用VIP的其他服务,例如wordpress站点,keepalived服务没有故障、VIP的ping测试也没有问题的情况下,使用VIP访问wordpress站点访问不到页面

# 同步配置文件
[root@lb01 ~]# scp /etc/keepalived/keepalived.conf lb02:/etc/keepalived/

# lb02节点先启动keepalived服务
[root@lb02 ~]# systemctl start keepalived.service

此时lb02节点就已经被认定为主节点,即便重启lb02节点的keepalived服务,VIP也会在漂移后重新回到lb02节点

KeepAlived与Nginx的关联

keepalived虚拟地址漂移与nginx服务进行关联,基本无需操作,因为nginx默认监听在所有IP地址上,这意味着当VIP落在某一个负载节点上时,nginx已经开始监听该VIP的80端口了,所以在实验环境下只需要修改一下本地的hosts解析,将站点域名解析到VIP上就能够直接访问了

KeepAlived脑裂

由于某些原因,导致两台keepalived节点在指定的时间内无法检测到对方的心跳,各自取得资源及服务的所有权,但此时两台keepalived节点又都还存活

服务器网线松动等网络故障
服务器硬件故障发生损坏现象而崩溃
主备都开启firewalld防火墙
Nginx服务崩溃

通过防火墙模拟脑裂,在keepalived脑裂情况下,VIP仍能通过ping测试和网站访问测试,但通过抓包测试可以看到keepalived两台主备节点不停在争抢VIP,这在某些服务和高并发的情况下是不被允许的

# 配置双节点的防火墙
[root@lb02 nginx]# firewall-cmd --remove-protocol=vrrp --permanent
[root@lb02 nginx]# firewall-reload

keepalived.png

# 备节点脑裂探测脚本
[root@lb02 ~]# vim /opt/script/split_brain.sh
#!/bin/sh
LB_VIP=10.0.0.2
LB01_IP=10.0.0.5
VIRTUAL_IP=$(ip add | grep "^${LB_VIP}$" | wc -l)
while true; do
        ping -c 2 -W 3 $LB01_IP &> /dev/null
        if [ $? -eq 0 -a ${VIRTUAL_IP} -eq 1 ]; then    # 既能ping通主节点、又能在自身匹配到VIP
                echo "ha is split brain.warning." >> /opt/keeperr.log   # 这个文件是为了检测脚本是否执行,也可以将此步骤换成邮箱
                exit
        else
                echo "ha is ok" >> /opt/keepalived.log
                exit
        fi
        sleep 1
done
[root@lb02 ~]# chmod 755 /opt/script/split_brain.sh

在这个脚本中exit非常重要,因为这个脚本使用的是while循环,判断条件是true,这意味着while会一直循环。在keepalived服务中调用的脚本,执行时间不可超过keepalived配置文件中,interval所定义的时间,否则keepalived将无法正常获取到VIP,从日志中可看到keepalived会一直杀死正在执行的脚本。因此每个判断下exit都是为了终止while循环,exit终止循环后,keepalived会主动重复执行脚本,等同于keepalived本身就是一个大的循环语法,脚本中实际上只需要编写测试语句

Mar 19 18:12:44 lb02 Keepalived_vrrp[23263]: /opt/script/split_brain.sh exited due to signal 15
Mar 19 18:12:49 lb02 Keepalived_vrrp[23263]: /opt/script/split_brain.sh exited due to signal 15
Mar 19 18:12:54 lb02 Keepalived_vrrp[23263]: /opt/script/split_brain.sh exited due to signal 15

出现脑裂问题时,必须随机下线某一个keepalived服务(不是下线主机)

KeepAlived保证Nginx服务可用

KeepAlived本身只做VIP地址漂移,它与nginx并没有直接关系,所以在某些情况下,主节点nginx服务崩溃,keepalived服务并不会收到影响,这就导致VIP会一直存在主节点上,用户请求站点失败;由于keepalived不会主动进行切换,所以需要编辑一个脚本检测nginx的存活状态,如果不存活则杀死nginx和keepalived,强制使VIP漂移到备节点

# 检测nginx存活脚本
[root@lb01 ~]# vim /opt/script/check_nginx.sh
#!/bin/sh
NGINXPID=$(ps -C nginx --no-header | wc -l)	# 检测nginx进程

if [ $NGINXPID -eq 0 ]; then
	systemctl start nginx	# 检测不到nginx进程时,启动nginx
	sleep 3
	NGINXPID=$(ps -C nginx --no-header | wc -l)	# 再次检测nginx进程
	if [ $NGINXPID -eq 0 ]; then
		systemctl stop keepalived	# nginx启动失败,关闭keepalived服务
	fi
fi
[root@lb01 ~]# chmod +x /opt/script/check_nginx.sh

主节点keepalived配置文件调用脚本

[root@lb01 ~]# vim /etc/keepalived/keepalived.conf
vrrp_script check_web {	# 定义脚本
	script "脚本绝对路径"		# 要执行的脚本存放路径
	interval 5	# 5秒检查一次
}

vrrp_instance VI_1{
	...

	track_script {	# 调用脚本
		check_web
	}
}

keepalived配置文件中设置每5秒执行一次脚本,其脚本本身的执行时长必须要小于5秒,否则脚本还没执行完,keepalived会主动杀死当前脚本进程并重新执行一遍脚本;以上都是针对抢占式keepalived的场景,如果是非抢占式场景,那么两个节点都需要配置检测脚本

关于KeepAlived

公有云不支持keepalived,因为公有云不支持组播,它提供自带的高可用服务

posted @ 2023-06-19 09:23  hebo  阅读(65)  评论(0)    收藏  举报