Mixing Healthcheck & Failover
对于此示例,我们使用与故障转移部分相同的拓扑。这里的想法是使用 VRRP VIP 作为 LVS VIP。这样,我们将引入一个执行 LVS 真实服务器池监控的高可用 LVS 控制器。
整个配置都在 /etc/keepalived/keepalived.conf 文件中完成。在我们的案例研究中,LVS 控制器 1 上的这个文件如下所示:
# Configuration File for keepalived global_defs { notification_email { admin@domain.com 0633225522@domain.com } notification_email_from keepalived@domain.com smtp_server 192.168.200.20 smtp_connect_timeout 30 lvs_id LVS_MAIN } # VRRP Instances definitions vrrp_sync_group VG1 { group { VI_1 #这种配置一般是内外网配置,VI_1内网,VI_2外网 VI_2 } } vrrp_sync_group VG2 { group { VI_3 VI_4 } } vrrp_instance VI_1 { state MASTER interface eth0 virtual_router_id 51 #主备failover必须相同 priority 150 advert_int 1 authentication { auth_type PASS auth_pass k@l!ve1 } virtual_ipaddress { 192.168.200.10 192.168.200.11 } } vrrp_instance VI_2 { state MASTER interface eth1 virtual_router_id 52 # priority 150 advert_int 1 authentication { auth_type PASS auth_pass k@l!ve2 } virtual_ipaddress { 192.168.100.10 } } vrrp_instance VI_3 { state BACKUP interface eth0 virtual_router_id 53 priority 100 advert_int 1 authentication { auth_type PASS auth_pass k@l!ve3 } virtual_ipaddress { 192.168.200.12 192.168.200.13 } } vrrp_instance VI_4 { state BACKUP interface eth1 virtual_router_id 54 priority 100 advert_int 1 authentication { auth_type PASS auth_pass k@l!ve4 } virtual_ipaddress { 192.168.100.11 } } # Virtual Servers definitions lvs服务 virtual_server 192.168.200.10 80 { delay_loop 30 #指定检查间隔(以秒为单位) lb_algo wrr #负载均衡算法 lb_kind NAT #负载均衡类型 persistence_timeout 50 #指定持久连接的超时值 protocol TCP #协议 sorry_server 192.168.100.100 80 real_server 192.168.100.2 80 { weight 2 HTTP_GET { url { path /testurl/test.jsp digest ec90a42b99ea9a2f5ecbe213ac9eba03 } url { path /testurl2/test.jsp digest 640205b7b0fc66c1ea91c463fac6334c } connect_timeout 3 retry 3 delay_before_retry 2 } } real_server 192.168.100.3 80 { weight 1 HTTP_GET { url { path /testurl/test.jsp digest 640205b7b0fc66c1ea91c463fac6334c } connect_timeout 3 retry 3 delay_before_retry 2 } } } virtual_server 192.168.200.12 443 { delay_loop 20 lb_algo rr lb_kind NAT persistence_timeout 360 protocol TCP real_server 192.168.100.2 443 { weight 1 TCP_CHECK { connect_timeout 3 } } real_server 192.168.100.3 443 { weight 1 TCP_CHECK { connect_timeout 3 } } }
我们在 LVS 控制器 2 上定义对称 VRRP 配置文件。这样,两个控制器同时处于活动状态,控制器 1 处理 HTTP 流,控制器 2 处理 SSL 流。
Keepalived非抢占模式
Keepalived默认为抢占模式:即当master节点挂了之后会自动切换至backup节点,当主节点恢复后会将VIP从备节点抢回。一般在业务中,我们认为第二次切换是多余的,即可将keepalived配置为非抢占模式。
非抢占模式配置的要素为:
1)两个节点的state都必须配置为BACKUP;
2)两个节点都需要在vrrp_instance中添加nopreempt参数;
3)其中一个节点的优先级必须高于另一个节点的优先级。
vrrp_instance VI_1 { #定义实例
state BACKUP #角色类型
...
nopreempt #非抢占模式
配置了非抢占模式后,需要注意keepalived的启动顺序,先启动的节点会变为主节点,VIP会绑定在该节点上,如果需要让A机成为备节点,就不能先启动A机的keepalived服务。
脑裂
在高可用(HA)系统中,当联系2个节点的“心跳线”断开时,本来为一整体、动作协调的HA系统,就分裂成为2个独立的个体。由于相互失去了联系,都以为是对方出了故障。两个节点上的HA软件像“裂脑人”一样,争抢“共享资源”、争起“应用服务”,就会发生严重后果——或者共享资源被瓜分、2边“服务”都起不来了;或者2边“服务”都起来了,但同时读写“共享存储”,导致数据损坏(常见如数据库轮询着的联机日志出错)。
对付HA系统“裂脑”的对策,目前达成共识的的大概有以下几条:
- 添加冗余的心跳线,例如:双线条线(心跳线也HA),尽量减少“裂脑”发生几率;
- 启用磁盘锁。正在服务一方锁住共享磁盘,“裂脑”发生时,让对方完全“抢不走”共享磁盘资源。但使用锁磁盘也会有一个不小的问题,如果占用共享盘的一方不主动“解锁”,另一方就永远得不到共享磁盘。现实中假如服务节点突然死机或崩溃,就不可能执行解锁命令。后备节点也就接管不了共享资源和应用服务。于是有人在HA中设计了“智能”锁。即:正在服务的一方只在发现心跳线全部断开(察觉不到对端)时才启用磁盘锁。平时就不上锁了。
- 设置仲裁机制。例如设置参考IP(如网关IP),当心跳线完全断开时,2个节点都各自ping一下参考IP,不通则表明断点就出在本端。不仅“心跳”、还兼对外“服务”的本端网络链路断了,即使启动(或继续)应用服务也没有用了,那就主动放弃竞争,让能够ping通参考IP的一端去起服务。更保险一些,ping不通参考IP的一方干脆就自我重启,以彻底释放有可能还占用着的那些共享资源。
脑裂产生的原因
一般来说,裂脑的发生,有以下几种原因:
-
高可用服务器对之间心跳线链路发生故障,导致无法正常通信。
- 因心跳线坏了(包括断了,老化)。
- 因网卡及相关驱动坏了,ip配置及冲突问题(网卡直连)。
- 因心跳线间连接的设备故障(网卡及交换机)。
- 因仲裁的机器出问题(采用仲裁的方案)。
-
高可用服务器上开启了 iptables防火墙阻挡了心跳消息传输。
- 高可用服务器上心跳网卡地址等信息配置不正确,导致发送心跳失败。
- 其他服务配置不当等原因,如心跳方式不同,心跳广插冲突、软件Bug等。
提示: Keepalived配置里同一 VRRP实例如果 virtual_router_id两端参数配置不一致也会导致裂脑问题发生。
常见的解决方案
在实际生产环境中,我们可以从以下几个方面来防止裂脑问题的发生:
- 同时使用串行电缆和以太网电缆连接,同时用两条心跳线路,这样一条线路坏了,另一个还是好的,依然能传送心跳消息。
- 当检测到裂脑时强行关闭一个心跳节点(这个功能需特殊设备支持,如Stonith、feyce)。相当于备节点接收不到心跳消患,通过单独的线路发送关机命令关闭主节点的电源。
- 做好对裂脑的监控报警(如邮件及手机短信等或值班).在问题发生时人为第一时间介入仲裁,降低损失。例如,百度的监控报警短倍就有上行和下行的区别。报警消息发送到管理员手机上,管理员可以通过手机回复对应数字或简单的字符串操作返回给服务器.让服务器根据指令自动处理相应故障,这样解决故障的时间更短。
当然,在实施高可用方案时,要根据业务实际需求确定是否能容忍这样的损失。对于一般的网站常规业务.这个损失是可容忍的。
脑裂监控脚本
#当备服务器上出现vip时认为发生脑裂或主备切换 #!/bin/bash while true do if [ `ip a show eth0 |grep 10.0.0.3|wc -l` -ne 0 ] then echo "keepalived is error!" else echo "keepalived is OK !" fi done