目录

1、什么是高可用?

2、什么是Keepalived

3、Keepalived如何实现故障转移

4、Keepalived安装

4.1 下载安装

4.2 运行前配置

4.3 启动服务

5、 Keepalive+Nginx高可用集群

5.1 双机主从模式

5.2 双机双主模式

6、注意


1、什么是高可用?

高可用性 HA(High Availability)指的是通过尽量缩短因日常维护操作(计划)和突发的系统崩溃(非计划)所导致的停机时间,以提高系统和应用的可用性。HA 系统是目前企业防止核心计算机系统因故障停机的最有效手段。

实现 HA 的方式,一般采用两台或者多台机器同时完成一项功能,比如数据库服务器,平常只有一台机器对外提供服务,另一台机器作为热备,当这台机器出现故障时,自动动态切换到另一台热备的机器。

2、什么是Keepalived

Keepalived软件起初是专为LVS(Linux Virtual Server)负载均衡软件设计的,用来管理并监控LVS集群系统中各个服务节点的状态,后来又加入了可以实现高可用的VRRP (Virtual Router Redundancy Protocol ,虚拟路由器冗余协议)功能。因此,Keepalived除了能够管理LVS软件外,还可以作为其他服务(例如:Nginx、Haproxy、MySQL等)的高可用解决方案软件

3、Keepalived如何实现故障转移

Keepalived对高可用服务之间的故障切换转移,是通过 VRRP 来实现的。在 Keepalived服务正常工作时,主 Master节点会不断地向备节点发送(多播的方式)心跳消息,用以告诉备Backup节点自己还活着,当主 Master节点发生故障时,就无法发送心跳消息,备节点也就因此无法继续检测到来自主 Master节点的心跳了,于是调用自身的接管程序,接管主Master节点的 IP资源及服务。而当主 Master节点恢复时,备Backup节点又会释放主节点故障时自身接管的IP资源及服务,恢复到原来的备用角色。

Keepalived的作用是检测服务器的状态,当服务器宕机或工作出现故障,Keepalived将检测到并将服务器集群中剔除,选择其他服务器代替该服务器的工作;当服务器恢复工作正常,Keepalived检测到自动将服务器加入服务器集群。

总结来说:Keepalived软件是一个监控+自愈的软件。

运行协议是VRRP,主分发器的keepalived会向网络广播。

4、Keepalived安装

4.1 下载安装

#两种方式:
​
#方法一:
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

4.2 运行前配置

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/

4.3 启动服务

service keepalived start
​
# 配置开机自启动
systemctl enable keepalived
​
#查看服务启动情况
ps -aux |grep keepalived

5、 Keepalive+Nginx高可用集群

双机高可用方法目前分为两种:

1)Nginx+keepalived 双机主从模式:即前端使用两台服务器,一台主服务器和一台热备服务器,正常情况下,主服务器绑定一个公网虚拟IP,提供负载均衡服务,热备服务器处于空闲状态;当主服务器发生故障时,热备服务器接管主服务器的公网虚拟IP,提供负载均衡服务;但是热备服务器在主机器不出现故障的时候,永远处于浪费状态,对于服务器不多的网站,该方案不经济实惠,但是对于主从服务器配置差异很大的机器可以作为一种选择(从服务器就临时用一下嘛)

2)Nginx+keepalived 双机主主模式:即前端使用两台负载均衡服务器,互为主备,且都处于活动状态,同时各自绑定一个公网虚拟IP,提供负载均衡服务;当其中一台发生故障时,另一台接管发生故障服务器的公网虚拟IP(这时由非故障机器一台负担所有的请求)。这种方案,经济实惠,非常适合于当前架构环境。一般来说,两个机器的性能都要相差无几,能够提供正常的业务访问量

5.1 双机主从模式

实验环境配置如下:

192.168.223.128: nginx + keepalived master 主

192.168.223.129: nginx + keepalived backup 从

5.1.1 主从节点服务器配置

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
    }
}

5.1.2 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,使得从服务器能够接管服务。

5.1.3 防止出现脑裂现象

脑裂(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.

5.1.4 启动查看

启动keepalived之前先将nginx启动,如果nginx报如下错误:

请执行系统配置设置:

 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,已经成功绑定到网卡上。

当前192.128.223.128是主节点,关闭之,查看192.128.223.129的日志信息:

再次启动192.168.223.128,查看192.128.223.129的日志信息:

5.1.5 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

5.2 双机双主模式

5.2.1 互为主从虚拟实例配置

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
    }
}
​

5.2.2 测试

关闭128节点的keepalived的,继续访问130虚拟IP,仍可访问,只不过是129节点支持的而已(nginx配置的代理地址不一样,只是为了显示讲解而已)

关闭前:

关闭后:

6、注意

1)、 在MASTER节点的 vrrp_instance 中 配置 nopreempt ,当它异常恢复后,即使它 priority 更高也不会抢占,这样可以避免正常情况下做无谓的切换

2)、 不管提高优先级还是降低优先级,最终优先级的范围是在[1,254],不会出现优先级小于等于0或者优先级大于等于255的情况

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐