什么是高可用?
高可用性 HA(High Availability)指的是通过尽量缩短因日常维护操作(计划)和突发的系统崩溃(非计划)所导致的停机时间,以提高系统和应用的可用性。HA 系统是目前企业防止核心计算机系统因故障停机的最有效手段。
实现 HA 的方式,一般采用两台或者多台机器同时完成一项功能,比如数据库服务器,平常只有一台机器对外提供服务,另一台机器作为热备,当这台机器出现故障时,自动动态切换到另一台热备的机器。
什么是Keepalived
Keepalived软件起初是专为LVS(Linux Virtual Server)负载均衡软件设计的,用来管理并监控LVS集群系统中各个服务节点的状态,后来又加入了可以实现高可用的VRRP (Virtual Router Redundancy Protocol ,虚拟路由器冗余协议)功能。因此,Keepalived除了能够管理LVS软件外,还可以作为其他服务(例如:Nginx、Haproxy、MySQL等)的高可用解决方案软件
Keepalived如何实现故障转移
Keepalived对高可用服务之间的故障切换转移,是通过 VRRP 来实现的。在 Keepalived服务正常工作时,主 Master节点会不断地向备节点发送(多播的方式)心跳消息,用以告诉备Backup节点自己还活着,当主 Master节点发生故障时,就无法发送心跳消息,备节点也就因此无法继续检测到来自主 Master节点的心跳了,于是调用自身的接管程序,接管主Master节点的 IP资源及服务。而当主 Master节点恢复时,备Backup节点又会释放主节点故障时自身接管的IP资源及服务,恢复到原来的备用角色。
Keepalived的作用是检测服务器的状态,当服务器宕机或工作出现故障,Keepalived将检测到并将服务器集群中剔除,选择其他服务器代替该服务器的工作;当服务器恢复工作正常,Keepalived检测到自动将服务器加入服务器集群。
总结来说:Keepalived软件是一个监控+自愈的软件。
运行协议是VRRP,主分发器的keepalived会向网络广播。
Keepalived安装
Keepalived安装
##两种方式: ##方法一: yum -y install keepalived(如果你本地安装了mysql,可能会有冲突) ##方法二: cd /usr/local wget http://www.keepalived.org/software/keepalived-2.0.19.tar.gz ##解压文件 tar -zxvf keepalived-2.0.19.tar.gz ##编译 cd keepalived-2.0.19/ ##--prefix 指定安装地址 ##/usr/local/keepalived/ 安装的目录,不要和解压文件一个目录,不然可能报错 ./configure --prefix=/usr/local/keepalived/ ##编译并安装 make && make install
运行前配置
cp /usr/local/keepalived-2.0.19/keepalived/etc/init.d/keepalived /etc/init.d/ mkdir /etc/keepalived cp /usr/local/keepalived/etc/keepalived/keepalived.conf /etc/keepalived/ cp /usr/local/keepalived-2.0.19/keepalived/etc/sysconfig/keepalived /etc/sysconfig/ cp /usr/local/keepalived/sbin/keepalived /usr/sbin/
启动服务
service keepalived start # 配置开机自启动 systemctl enable keepalived #查看服务启动情况 ps -aux |grep keepalived
Keepalive+Nginx高可用集群
双机高可用方法目前分为两种:
1)Nginx+keepalived 双机主从模式:即前端使用两台服务器,一台主服务器和一台热备服务器,正常情况下,主服务器绑定一个公网虚拟IP,提供负载均衡服务,热备服务器处于空闲状态;当主服务器发生故障时,热备服务器接管主服务器的公网虚拟IP,提供负载均衡服务;但是热备服务器在主机器不出现故障的时候,永远处于浪费状态,对于服务器不多的网站,该方案不经济实惠,但是对于主从服务器配置差异很大的机器可以作为一种选择(从服务器就临时用一下嘛)
2)Nginx+keepalived 双机主主模式:即前端使用两台负载均衡服务器,互为主备,且都处于活动状态,同时各自绑定一个公网虚拟IP,提供负载均衡服务;当其中一台发生故障时,另一台接管发生故障服务器的公网虚拟IP(这时由非故障机器一台负担所有的请求)。这种方案,经济实惠,非常适合于当前架构环境。一般来说,两个机器的性能都要相差无几,能够提供正常的业务访问量
双机主从模式
实验环境配置如下:
192.168.223.128: nginx + keepalived master 主
192.168.223.129: nginx + keepalived backup 从
主从节点服务器配置
192.168.223.128(主)—>>
vim /etc/keepalived/keepalived.conf ------------------------------------------------------- ! Configuration File for keepalived global_defs { #不与其他节点重名即可 router_id nginx_router } # 检测nginx是否运行 vrrp_script chk_nginx { script "/etc/keepalived/nginx_check.sh" #心跳执行的脚本 interval 2 #(检测脚本执行的间隔,单位是秒) weight -20 #脚本结果导致的优先级变更,检测失败(脚本返回非0)则优先级 -20 fall 2 #检测连续2次失败才算确定是真失败。会用weight减少优先级(1-255之间) rise 1 #检测1次成功就算成功。但不修改优先级 } vrrp_instance nginx { state BACKUP #此处不设置为MASTER,通过priority来竞争master interface eth0 #网卡名称 virtual_router_id 51 #同一个keepalived集群的virtual_router_id相同 priority 100 # 权重,master要大于slave advert_int 1 # 主备通讯时间间隔 authentication { #设置验证类型和密码,MASTER和BACKUP必须使用相同的密码才能正常通信 auth_type PASS auth_pass 1111 } #与上方nginx运行状况检测呼应 track_script { chk_nginx } # 虚拟ip地址(VIP,一个尚未占用的内网ip即可,可以多个) virtual_ipaddress { 192.168.223.130 192.168.223.131 } }
192.168.223.129(从),就改个priority
vim /etc/keepalived/keepalived.conf global_defs { #不与其他节点重名即可 router_id nginx_router } # 检测nginx是否运行 vrrp_script chk_nginx { script "/etc/keepalived/nginx_check.sh" #心跳执行的脚本 interval 2 #(检测脚本执行的间隔,单位是秒) weight -20 #脚本结果导致的优先级变更,检测失败(脚本返回非0)则优先级 -20 fall 2 #检测连续2次失败才算确定是真失败。会用weight减少优先级(1-255之间) rise 1 #检测1次成功就算成功。但不修改优先级 } vrrp_instance nginx { state BACKUP #此处不设置为MASTER,通过priority来竞争master interface eth0 #网卡名称 virtual_router_id 51 #同一个keepalived集群的virtual_router_id相同 priority 90 # 权重,master要大于slave advert_int 1 # 主备通讯时间间隔 authentication { #设置验证类型和密码,MASTER和BACKUP必须使用相同的密码才能正常通信 auth_type PASS auth_pass 1111 } #与上方nginx运行状况检测呼应 track_script { chk_nginx } # 虚拟ip地址(VIP,一个尚未占用的内网ip即可,可以多个) virtual_ipaddress { 192.168.223.130 192.168.223.131 } }
nginx监听脚本
#与上面配置的脚本路径、名称要保持一致 cd /etc/keepalived #创建nginx检测脚本 vim nginx_check.sh # 添加如下内容 #!/bin/bash nginxpid=`ps -C nginx --no-header | wc -l` if [ $nginxpid -eq 0 ];then systemctl restart nginx sleep 2 nginxpid=`ps -C nginx --no-header | wc -l` if [ $nginxpid -eq 0 ];then killall keepalived fi fi ------------------------------ #给脚本增加可执行权限 chmod +x nginx_check.sh
PS:让keepalived监控NginX的状态:
由于keepalived只检测本机和他机keepalived是否正常并实现VIP的漂移,而如果本机nginx出现故障则不会漂移VIP,所以编写脚本来判断本机nginx是否正常,如果发现NginX不正常,重启之。等待3秒再次校验,仍然失败则不再尝试,关闭keepalived,其他主机此时会接管VIP;
1)经过前面的配置,如果master主服务器的keepalived停止服务,slave从服务器会自动接管VIP对外服务; 一旦主服务器的keepalived恢复,会重新接管VIP。 但这并不是我们需要的,我们需要的是当NginX停止服务的时候能够自动切换。 2)keepalived支持配置监控脚本,我们可以通过脚本监控NginX的状态,如果状态不正常则进行一系列的操作,最终仍不能恢复NginX则杀掉keepalived,使得从服务器能够接管服务。
防止出现脑裂现象
脑裂(split-brain):指在一个高可用(HA)系统中,当联系着的两个节点断开联系时,本来为一个整体的系统,分裂为两个独立节点,这时两个节点开始争抢共享资源,结果会导致资源瓜分甚至“各自为政”,系统混乱,数据损坏。
对于无状态服务的HA,无所谓脑裂不脑裂;但对有状态服务(比如MySQL)的HA,必须要严格防止脑裂:
1)或者共享资源被瓜分、两边”服务”都起不来了;
2)或者两边”服务”都起来了,但同时读写”共享存储”,导致数据损坏(常见如数据库轮询着的联机日志出错)。
防火墙模拟脑裂:
#在192.168.223.129上drop掉组播数据包,让备节点接收不到master上的报文,备节点就会启动接管程序接管主节点的资源, 对外提供服务, 表现形式就是备节点上出现了虚拟IP, 此时主节点也是持有虚拟IP的 iptables -A INPUT -m pkttype --pkt-type multicast -j DROP #或者禁掉128的访问: iptables -I INPUT -s 192.168.223.128 -j DROP iptables -I OUTPUT -s 192.168.223.128 -j DROP #解封: iptables -L INPUT #查看状态 iptables -L OUTPUT #查看状态 iptables -L --line-numbers #带序号查看状态 #然后 iptables -D INPUT 序号 iptables -D OUTPUT 序号 #---------------------------------封禁---------------------------------------- [root@ydt2 ~]# iptables -A INPUT -m pkttype --pkt-type multicast -j DROP #---------------------------------解封---------------------------------------- [root@ydt2 ~]# iptables -L --line-numbers Chain INPUT (policy ACCEPT) num target prot opt source destination 1 ACCEPT udp -- anywhere anywhere udp dpt:domain 2 ACCEPT tcp -- anywhere anywhere tcp dpt:domain 3 ACCEPT udp -- anywhere anywhere udp dpt:bootps 4 ACCEPT tcp -- anywhere anywhere tcp dpt:bootps 5 DROP all -- anywhere anywhere PKTTYPE = multicast [root@ydt2 ~]# iptables -D INPUT 1 [root@ydt2 ~]# iptables -L INPUT Chain INPUT (policy ACCEPT) target prot opt source destination ACCEPT udp -- anywhere anywhere udp dpt:domain ACCEPT tcp -- anywhere anywhere tcp dpt:domain ACCEPT udp -- anywhere anywhere udp dpt:bootps ACCEPT tcp -- anywhere anywhere tcp dpt:bootps
#禁掉组播后会发现128,129两台机器都有一个相同的虚拟IP
解决办法:
1)、使用VRRP广播地址:
# 指定keepalived配置的网卡:eth0,固定的VRRP广播地址:224.0.0.18 由IANA标准指定的多点广播地址224.0.0.18 #将防火墙的vvrp开启,并使用VRRP固定的广播地址 firewall-cmd --direct --permanent --add-rule ipv4 filter INPUT 0 --in-interface eth0 --destination 224.0.0.18 --protocol vrrp -j ACCEPT firewall-cmd --direct --permanent --add-rule ipv4 filter OUTPUT 0 --out-interface eth0 --destination 224.0.0.18 --protocol vrrp -j ACCEPT firewall-cmd --reload #再看从节点VIP不见了 # 查看配置的规则 firewall-cmd --direct --get-rules ipv4 filter INPUT firewall-cmd --direct --get-rules ipv4 filter OUTPUT
2)、使用脚本检测警告
检测思路:正常情况下keepalived的VIP地址是在主节点上的,如果在从节点发现了VIP,就设置报警信息。脚本(在从节点上)
vim check_split_brain.sh ------------------------------------------- #!/bin/bash # 检查脑裂的脚本,在备节点上进行部署 LB01_VIP=192.168.223.130 while true do if [ `ip a show eth0 |grep "$LB01_VIP"|wc -l` -ne 0 ];then if [ `ping -c 1 www.yuandengta.com|grep 100%|wc -l` -ne 0 ]; then echo "ha is brain" else echo "ha is ok" fi fi sleep 1 done ---------------------------------- chmod 777 check_split_brain.sh #执行结果如下: [root@ydt2 keepalived]# ./check_split_brain.sh ha is ok ha is ok ha is ok ha is ok ha is ok ha is ok #当发现异常时候的执行结果: [root@ydt2 keepalived]# ./check_split_brain.sh ha is ok ha is ok ha is ok ha is ok ha is ok ha is ok ha is brain. ha is brain.
启动查看
请执行系统配置设置:
mkdir -p /etc/systemd/system/nginx.service.d printf "[Service]\nExecStartPost=/bin/sleep 0.1\n" >/etc/systemd/system/nginx.service.d/override.conf systemctl daemon-reload systemctl restart nginx.service
接下来启动keepalived:
**启动服务:** service keepalived start # 配置开机自启动 systemctl enable keepalived **查看服务启动情况:** ps -aux |grep keepalived **查看启动日志:** journalctl -xe **查看keepalived日志** tail -f /var/log/messages
配置成功后的效果。eth0是网卡名字;192.168.223.130是虚拟ip,已经成功绑定到网卡上。
Nginx测试
外部访问虚拟IP时,先在各节点执行如下命令,让iptables对虚拟服务ip彻底放行:
# 192.168.223.130虚拟IP #80 nginx端口 iptables -t nat -A PREROUTING -p tcp -d 192.168.223.130 --dport 80 -j REDIRECT
我们人为造些异常出来,反正就一个目标,让VIP漂移到从节点,然后我们再访问192.168.223.130/111.png
双机双主模式
互为主从虚拟实例配置
192.168.223.128–>>
! Configuration File for keepalived global_defs { router_id nginx_router } # 检测nginx是否运行 vrrp_script chk_nginx { script "/etc/keepalived/nginx_check.sh" #心跳执行的脚本 interval 2 #(检测脚本执行的间隔,单位是秒) weight -20 #脚本结果导致的优先级变更,检测失败(脚本返回非0)则优先级 -20 fall 2 #检测连续2次失败才算确定是真失败。会用weight减少优先级(1-255之间) rise 1 #检测1次成功就算成功。但不修改优先级 } vrrp_instance nginx { state BACKUP #此处不设置为MASTER,通过priority来竞争master interface eth0 #网卡名称 virtual_router_id 51 #virtual_router_id相同漂移相同的VIP priority 100 # 权重,master要大于slave advert_int 1 # 主备通讯时间间隔 authentication { #设置验证类型和密码,同一个VIP实例,MASTER和BACKUP必须使用相同的密码才能正常通信 auth_type PASS auth_pass 1111 } #与上方nginx运行状况检测呼应 track_script { chk_nginx } # 虚拟ip地址(VIP,一个尚未占用的内网ip即可,可以多个) virtual_ipaddress { 192.168.223.130 } } #增加的备虚拟节点 vrrp_instance nginx2 { state BACKUP interface eth0 virtual_router_id 52 #注意不要与上方virtual_router_id相同 priority 90 #一定要比上方的优先级低 advert_int 1 authentication { auth_type PASS auth_pass 1111 } #与上方nginx运行状况检测呼应 track_script { chk_nginx } virtual_ipaddress { 192.168.223.131 } }
192.168.223.129–>>
! Configuration File for keepalived global_defs { router_id nginx_router } # 检测nginx是否运行 vrrp_script chk_nginx { script "/etc/keepalived/nginx_check.sh" #心跳执行的脚本 interval 2 #(检测脚本执行的间隔,单位是秒) weight -20 #脚本结果导致的优先级变更,检测失败(脚本返回非0)则优先级 -20 fall 2 #检测连续2次失败才算确定是真失败。会用weight减少优先级(1-255之间) rise 1 #检测1次成功就算成功。但不修改优先级 } vrrp_instance nginx { state BACKUP #此处不设置为MASTER,通过priority来竞争master interface eth0 #网卡名称 virtual_router_id 51 #同一个keepalived集群的virtual_router_id相同 priority 90 # 权重,master要大于slave advert_int 1 # 主备通讯时间间隔 authentication { #设置验证类型和密码,MASTER和BACKUP必须使用相同的密码才能正常通信 auth_type PASS auth_pass 1111 } #与上方nginx运行状况检测呼应 track_script { chk_nginx } # 虚拟ip地址(VIP,一个尚未占用的内网ip即可,可以多个) virtual_ipaddress { 192.168.223.130 } } #增加的主虚拟节点 vrrp_instance nginx2 { state BACKUP interface eth0 virtual_router_id 52 #注意不要与上方virtual_router_id相同 priority 100 #一定要比上方的优先级高 advert_int 1 authentication { auth_type PASS auth_pass 1111 } #与上方nginx运行状况检测呼应 track_script { chk_nginx } virtual_ipaddress { 192.168.223.131 } }
测试
关闭128节点的keepalived的,继续访问130虚拟IP,仍可访问,只不过是129节点支持的而已(nginx配置的代理地址不一样,只是为了显示讲解而已)
特别注意
1、在MASTER节点的 vrrp_instance 中 配置 nopreempt ,当它异常恢复后,即使它 priority 更高也不会抢占,这样可以避免正常情况下做无谓的切换
2、不管提高优先级还是降低优先级,最终优先级的范围是在[1,254],不会出现优先级小于等于0或者优先级大于等于255的情况