一、keepalived简介
keepalived是集群管理中保证集群高可用的一个服务软件,其功能类似于,用来防止单点故障。
二、vrrp协议
2.1 vrrp协议简介
在现实的网络环境中,两台需要通信的主机大多数情况下并没有直接的物理连接,对于这样的情况,他们之间的路由怎么选择的呢?主机如何选定到达目的主机的下一跳路由,这是一个问题,通常解决办法有两种:
在主机上使用动态路由协议
在主机上配置静态路由
很明显,在主机上配置动态路由协议是非常不且实际的,因为管理、维护成本以及是否支持等诸多问题,那么配置静态路由就变得十分的流行,实际上,这种方式我们至今一直在用。但是路由器(或者说默认网关)却经常成为单点。就算配置了多个静态路由,却因为只有重启网络才生效变得不实用。
VRRP的目的就是为了解决静态路由单点故障问题!
VRRP通过一种竞选协议来动态的将路由任务交给LAN中虚拟路由器的某台VRRP路由器,这里看来很绕,因为有两个挂件名词:虚拟路由器和VRRP路由器。
VRRP路由器
VRRP路由器就是一台路由器,只不过上面运行了VRRPD这样的程序,来实现VRRP协议,这是物理的路由器,一台VRRP路由器可以位于多个虚拟路由器。
VRRP虚拟路由器
所谓虚拟,就是说不并不是实际存在的,是一个逻辑而不是物理的路由器,虚拟路由器通常由多台VRRP路由器通过某种方式组成,就好比这些物理的路由器都丢到一个池(pool)里面去,整个pool对外看起来就像是一台路由器,但其实内部有很多台,虚拟路由器的标识称为VRID。
2.2 vrrp工作机制
VRRP通过竞选协议来实现虚拟路由器的功能,所有的协议报文都是通过IP多播包(多播地址224.0.0.18)形式发送的。虚拟路由器由VRID(范围0-255)和一组IP地址组成。所以,在一个虚拟路由器中,不管谁是MASTER,对外都是相同的MAC和IP(称之为VIP)。客户端主机并不需要因为MASTER的改变而修改自己的路由配置,对他们来说这种主从切换是透明的。
在一个虚拟路由器中,只有作为MASTER的VRRP路由器会一直发送VRRP组播包,BACKUP不会抢占MASTER,除非它的优先级(priority)更高。当MASTER不可用时(BAKCUP收不到组播包),多台BACKUP中优先级最高的这台会被抢占为MASTER。这种抢占是非常迅速的(< 1s),以保证服务的连续性。
出于安全性考虑,VRRP包使用了加密协议进行加密。
三、keepalived实战环境准备(配置部分可以参考前面的博文:使用haproxy实现反向代理负载均衡实战)
node1:haproxy+httpd
node2:haproxy+httpd
mini1: httpd
四、keepalived实战
4.1 安装keepalived
分别在两台haproxy的server node1和node2上安装keeepalived,并启动
# yum install -y keepalived
启动apache、haproxy和keepalived
systemcl start haproxy
systemcl enable haproxy
systemcl start haproxy
systemcl enable haproxy
systemctl start keepalived
systemctl enable keepalived
[root@node1 ~]# cd /etc/keepalived/
[root@node1 keepalived]# vim keepalived.conf
! Configuration File for keepalived
global_defs {
notification_email { #keepalived切换时发送email的对象,可以多个,每行一个
[email protected]
}
notification_email_from [email protected] #邮件来自哪里,haproxy-ha代表给haproxy做高可用
smtp_server 127.0.0.1 #本地配置的smtp
smtp_connect_timeout 30 #连接smtp超时时间30s
router_id haproxy-ha #运行haproxy_ha集群的标识,每个集群一个
}
vrrp_script chk_haproxy {
script "/etc/keepalived/scripts/haproxy_chk.sh" # 状态监测脚本,当haproxy进程挂掉时,关闭keepalived,可以有效防止vip的随意漂移
interval 5
weight -2
}
vrrp_instance VI_1 { # vrrp实例的名字,根据业务定义
interface eth0 # 该实例绑定的绑卡设备,centos7要注意默认不是eth0需要改为对应的如:ens33
state MASTER # 指定instance的初始状态,在两台router都启动后,马上发上竞选出Master,这里的state Master并不代表一直是Master
virtual_router_id 51 # VRIP,范围0~255,默认51
priority 50 # 权重值,用来竞选,MASTER要高于BACKUP至少50,node2权重值修改为150
advert_int 5 # 竞选检查间隔,默认1s
authentication { # 设置验证,防止局域网多个keepalived配置混乱
auth_type PASS
auth_pass haproxy_ha
}
virtual_ipaddress { #设置的虚拟ip地址
192.168.3.201
192.168.3.202
}
track_script {
chk_haproxy
}
}
编写haproxy状态检测脚本
# cat /etc/keepalived/scripts/haproxy_chk.sh
#!/bin/bash # auto check haproxy process killall -0 haproxy if [[ $? -ne 0 ]];then /usr/bin/systemctl stop keepalived fi
将配置文件拷贝到node2上,并更改优先级和角色为BACKUP
[root@node1 ~]# scp /etc/keepalived/keepalived.conf 192.168.3.200:/etc/keepalived/ [root@node1 ~]# scp /etc/keepalived/scripts/haproxy_chk.sh 192.168.3.200:/etc/keepalived/scripts/ [root@linux-node2 keepalived]# sed -i 's#priority 100#priority 150#g' keepalived.conf [root@linux-node2 keepalived]# sed -i 's#state MASTER#state BACKUP#g' keepalived.conf
重新启动两台keepalived,此时直接访问虚拟VIP如:192.18.3.202是可以直接访问的(生产环境直接将域名绑定在虚拟IP上即可实现访问)
# systemctl restart keepalived.service
查看两台keepalived的虚拟ip情况
[root@node1 ~]# ip a 1: lo:mtu 65536 qdisc noqueue state UNKNOWN qlen 1 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: eth0: mtu 1500 qdisc pfifo_fast state UP qlen 1000 link/ether 00:50:56:3b:dc:7e brd ff:ff:ff:ff:ff:ff inet 192.168.3.140/24 brd 192.168.3.255 scope global dynamic eth0 valid_lft 64981sec preferred_lft 64981sec inet 192.168.3.201/32 scope global eth0 valid_lft forever preferred_lft forever inet 192.168.3.202/32 scope global eth0 valid_lft forever preferred_lft forever
[root@node2 ~]# ip a 1: lo:mtu 65536 qdisc noqueue state UNKNOWN link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: ens33: mtu 1500 qdisc pfifo_fast state UP qlen 1000 link/ether 00:0c:29:fe:67:7c brd ff:ff:ff:ff:ff:ff inet 192.168.3.200/24 brd 192.168.3.255 scope global ens33 valid_lft forever preferred_lft forever inet6 fe80::20c:29ff:fefe:677c/64 scope link valid_lft forever preferred_lft forever
抓组播包,可以看出检查竞选的频率为4s,MASTER为node1(权重值为150)
[root@node1 ~]# tcpdump -n 'host 224.0.0.18'
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes 09:14:34.916207 IP 192.168.3.12 > 224.0.0.18: VRRPv2, Advertisement, vrid 36, prio 150, authtype simple, intvl 1s, length 20 09:14:35.917550 IP 192.168.3.12 > 224.0.0.18: VRRPv2, Advertisement, vrid 36, prio 150, authtype simple, intvl 1s, length 20 09:14:36.918762 IP 192.168.3.12 > 224.0.0.18: VRRPv2, Advertisement, vrid 36, prio 150, authtype simple, intvl 1s, length 20 09:14:37.237311 IP 192.168.3.140 > 224.0.0.18: VRRPv2, Advertisement, vrid 51, prio 100, authtype simple, intvl 4s, length 68 09:14:37.919298 IP 192.168.3.12 > 224.0.0.18: VRRPv2, Advertisement, vrid 36, prio 150, authtype simple, intvl 1s, length 20 09:14:38.920860 IP 192.168.3.12 > 224.0.0.18: VRRPv2, Advertisement, vrid 36, prio 150, authtype simple, intvl 1s, length 20 09:14:39.921685 IP 192.168.3.12 > 224.0.0.18: VRRPv2, Advertisement, vrid 36, prio 150, authtype simple, intvl 1s, length 20 09:14:40.922149 IP 192.168.3.12 > 224.0.0.18: VRRPv2, Advertisement, vrid 36, prio 150, authtype simple, intvl 1s, length 20 09:14:41.238014 IP 192.168.3.140 > 224.0.0.18: VRRPv2, Advertisement, vrid 51, prio 100, authtype simple, intvl 4s, length 68 09:14:41.923613 IP 192.168.3.12 > 224.0.0.18: VRRPv2, Advertisement, vrid 36, prio 150, authtype simple, intvl 1s, length 20 09:14:42.925114 IP 192.168.3.12 > 224.0.0.18: VRRPv2, Advertisement, vrid 36, prio 150, authtype simple, intvl 1s, length 20 09:14:43.925975 IP 192.168.3.12 > 224.0.0.18: VRRPv2, Advertisement, vrid 36, prio 150, authtype simple, intvl 1s, length 20 09:14:44.927657 IP 192.168.3.12 > 224.0.0.18: VRRPv2, Advertisement, vrid 36, prio 150, authtype simple, intvl 1s, length 20 09:14:45.239277 IP 192.168.3.140 > 224.0.0.18: VRRPv2, Advertisement, vrid 51, prio 100, authtype simple, intvl 4s, length 68
此时停用node1(192.168.3.140)上的haproxy服务或者keepalived服务,vip会发生漂移,当node1的keepalived和haproxy重新启动时,vip会再次发生漂移返回原master节点,即发生了vip的抢夺
五、keepalived设置不抢占资源
当MASTER出现问题后,BACKUP会竞选出新的MASTER,那么当之前的MASTER重新ONLINE后,是继续成为MASTER还是变成BACKUP呢?默认情况下,之前的MASTER起来后悔继续抢占成为MASTER,也就是说,整个过程需要发生两次切换。
1)MASTER -> BACKUP
2) BACKUP -> MASTER
这样对业务频繁的切换是不能容忍的,因此我们希望MASTER起来后成为BACKUP,所以要设置不抢占。keepalived里面提供了nopreempt这个配置,但是这个配置只能用在state为BACKUP的机器上,但是我们明明希望的是MASTER不进行抢占,没办法,MASTER的state也要设置成BACKUP,也就是说两台keepalived的state都要设置成BACKUP。
具体配置为
1)两台的state处都修改为backup
2)最开始最为MASTER的keepalived的在instance配置端加上nopreempt参数,当此keepalived节点挂了,bakcup将抢占为主,原master恢复后不抢占。
六、配置脚本keepalived不争抢资源功能
# cat /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
notification_email {
[email protected]
}
notification_email_from [email protected]
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id haproxy-ha
}
vrrp_script chk_haproxy {
script "/etc/keepalived/scripts/haproxy_chk.sh"
interval 5
weight -2
}
vrrp_instance VI_1 {
interface eth0
state BACKUP # 两个keepalived节点初始状态都配置为BACKUP
virtual_router_id 240
priority 100
advert_int 5
nopreempt # 两个keepalived节点都添加不争抢资源选项
authentication {
auth_type PASS
auth_pass haproxy_ha
}
virtual_ipaddress {
192.168.3.201
192.168.3.202
}
track_script {
chk_haproxy
}
}
七、裂脑
7.1 解释裂脑
在“双机热备”高可用(HA)系统中,当联系2个节点的“心跳线”断开时,本来为一整体、动作协调的HA系统,就分裂成为2个独立的个体。由于相互失去了联系,都以为是对方出了故障,2个节点上的HA软件像“裂脑人”一样,“本能”地争抢“共享资源”、争起“应用服务”,就会发生严重后果:或者共享资源被瓜分、2边“服务”都起不来了;或者2边“服务”都起来了,但同时读写“共享存储”,导致数据损坏(常见如数据库轮询着的联机日志出错)。
运行于备用主机上的Heartbeat可以通过以太网连接检测主服务器的运行状态,一旦其无法检测到主服务器的“心跳”则自动接管主服务器的资源。通常情况下,主、备服务器间的心跳连接是一个独立的物理连接,这个连接可以是串行线缆、一个由“交叉线”实现的以太网连接。Heartbeat甚至可同时通过多个物理连接检测主服务器的工作状态,而其只要能通过其中一个连接收到主服务器处于活动状态的信息,就会认为主服务器处于正常状态。从实践经验的角度来说,建议为Heartbeat配置多条独立的物理连接,以避免Heartbeat通信线路本身存在单点故障。
7.2 产生裂脑的原因
高可用服务器之间心跳线链路故障,导致无法正常通信
1)心跳线坏了(线路老化或者意外断了)
2)网卡及相关驱动坏了,IP配置及冲突问题,网卡直连
3)心跳线间链接的设备故障(网卡及交换机)
4)仲裁的机器或者仲裁方案出问题
高可用服务器对上开启了iptables防火墙阻挡了信条消息传输
高可用服务器对上心跳网卡地址等信息配置不争取额,导致发送心跳失败
启发服务配置不当等原因,如心跳方式不同,心跳广播冲突,软件BUG等
7.3 防止发生裂脑的措施
同时使用穿线电缆和以太网电缆连接,同时用两条线路,这样一条线路坏了,另一个还是好的,依然能传送心跳信息。
当检测到裂脑时强行关闭一个心跳节点,需要特殊设备(Stonith,fence)。相当于程序上备节点发现心跳线故障,发送关机命令到主节点。
做好对脑力额的监控报警(邮件短信值班等),发生问题时人为第一时间介入仲裁,降低损失。当然,在实施高可用方案时,要根据业务需求确定是否能容忍这样的损失,对于一般的网站常规业务,这个损失是可控的。
启用磁盘锁,正在服务一方锁主共享磁盘,裂脑发生时,让对方完全无法抢占。