keepalived高可用
1.keepalived高可用简介
Keepalived 软件起初是专为LVS负载均衡软件设计的,用来管理并监控LVS集群系统中各个服务节点的状态,后来又加入了可以实现高可用的VRRP功能。因此,Keepalived除了能够管理LVS软件外,还可以作为其他服务(例如:Nginx、Haproxy、MySQL等)的高可用解决方案软件。
Keepalived软件主要是通过VRRP协议实现高可用功能的。
VRRP是Virtual Router RedundancyProtocol(虚拟路由器冗余协议)的缩写,
VRRP出现的目的就是为了解决静态路由单点故障问题的,它能够保证当个别节点宕机时,整个网络 可以不间断地运行。
所以,Keepalived 一方面具有配置管理LVS的功能,同时还具有对LVS下面节点进行健康检查的功能,另一方面也可实现系统网络服务的高可用功能。
1.1.keepalived的重要功能
keepalived 有三个重要的功能,分别是:
1.管理LVS负载均衡软件
2.实现LVS集群节点的健康检查
3.作为系统网络服务的高可用性(failover)
1.2. keepalived高可用故障转移的原理
Keepalived 高可用服务之间的故障切换转移,是通过 VRRP 来实现的。
在 Keepalived 服务正常工作时,主 Master 节点会不断地向备节点发送(多播的方式)心跳消息,用以告诉备 Backup 节点自己还活看,当主 Master 节点发生故障时,就无法发送心跳消息,备节点也就因此无法继续检测到来自主 Master 节点的心跳了,于是调用自身的接管程序,接管主 Master 节点的 IP 资源及服务。
而当主 Master 节点恢复时,备 Backup 节点又会释放主节点故障时自身接管的IP资源及服务,恢复到原来的备用角色。
1.3.keepalived工作过程与原理
1.3.1.keepalived工作过程
1.两台服务器利用VRRP来竞选,确定主服务器和备服务器
2.确定主服务器后,主服务器会做3件事
1.会不断的给备服务器发送心跳消息,通知备服务器
2.主服务器就会获得VIP用来接收客户端的请求
3.会与后端服务器通信,来处理用户请求
3.当主服务器服务因为某种原因中断,
备服务器不会接收到心跳消息时,自身就会启动服务,变为主服务器,
直到主服务器服务恢复,
1.3.2.keepalived工作原理描述
Keepalived高可用对之间是通过VRRP通信的,因此先介绍一下VRRP
VRRP
1) VRRP,中文名为虚拟路由冗余协议,VRRP的出现是为了解决静态路由的单点故障。
2) VRRP是通过一种竟选协议机制来将路由任务交给某台 VRRP路由器的。
3) VRRP用 IP多播的方式(默认多播地址(224.0_0.18))实现高可用对之间通信。
4) 工作时主节点发包,备节点接包,当备节点接收不到主节点发的数据包的时候,就启动接管程序接管主节点的开源。备节点可以有多个,通过优先级竞选,但一般 Keepalived系统运维工作中都是一对。
5) VRRP使用了加密协议加密数据,但Keepalived官方目前还是推荐用明文的方式配置认证类型和密码。
keepalived工作原理
Keepalived高可用是通过 VRRP 进行通信的, VRRP是通过竞选机制来确定主备的,主的优先级高于备,因此,工作时主会优先获得所有的资源,备节点处于等待状态,当主挂了的时候,备节点就会接管主节点的资源,然后顶替主节点对外提供服务。
在 Keepalived 服务之间,只有作为主的服务器会一直发送 VRRP 广播包,告诉备它还活着,此时备不会枪占主,当主不可用时,即备监听不到主发送的广播包时,就会启动相关服务接管资源,保证业务的连续性.接管速度最快可以小于1秒。
2.keepalived配置
主机 | IP |
---|---|
master(主) | 192.168.30.244/24 |
VIP地址 | 192.168.30.246/32 |
slave(备) | 192.168.30.245/24 |
两台服务器apache配置完成
[root@master ~]# ss -anlt
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 *:22 *:*
LISTEN 0 100 127.0.0.1:25 *:*
LISTEN 0 128 :::80 :::*
LISTEN 0 128 :::22 :::*
LISTEN 0 100 ::1:25 :::*
[root@slave ~]# ss -anlt
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 *:22 *:*
LISTEN 0 100 127.0.0.1:25 *:*
LISTEN 0 128 :::80 :::*
LISTEN 0 128 :::22 :::*
LISTEN 0 100 ::1:25 :::*
1.主服务器配置keepalived
关闭防火墙selinux
[root@master ~]# systemctl stop firewalld
[root@master ~]# systemctl disable firewalld
[root@master ~]# setenforce 0
[root@master ~]# sed -ri 's/^(SELINUX=).*/\1disabled/g' /etc/selinux/config
配置网络源
[root@master ~]# curl -o /etc/yum.repos.d/CentOS7-Base-163.repo http://mirrors.163.com/.help/CentOS7-Base-163.repo
[root@master ~]# sed -i 's/\$releasever/7/g' /etc/yum.repos.d/CentOS7-Base-163.repo
[root@master ~]# sed -i 's/^enabled=.*/enabled=1/g' /etc/yum.repos.d/CentOS7-Base-163.repo
[root@master ~]# yum -y install epel-release vim wget gcc gcc-c++
安装keepalived
[root@master ~]# yum -y install keepalived
进入配置文件,先备份
[root@master ~]# cd /etc/keepalived/
[root@master keepalived]# cp keepalived.conf{,-bak}
[root@master keepalived]# ls
keepalived.conf keepalived.conf-bak
1.修改配置文件
[root@master keepalived]# vim keepalived.conf
! Configuration File for keepalived
global_defs {
router_id lb01 ##唯一标识,不能重复
}
vrrp_instance VI_1 {
state MASTER
interface ens33
virtual_router_id 20 ##两边要一致
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass zyy ##两边要一致
}
virtual_ipaddress {
192.168.30.246 ##VIP
}
}
virtual_server 192.168.30.246 80 { ##监听的端口(服务)
delay_loop 6
lb_algo rr
lb_kind DR
persistence_timeout 50
protocol TCP
real_server 192.168.30.244 80 { ##真实主机的IP
weight 1
TCP_CHECK {
connect_port 80
connect_timeout 3
nb_get_retry 3
delay_before_retry 3
}
}
real_server 192.168.30.245 80 {
weight 1
TCP_CHECK {
connect_port 80
connect_timeout 3
nb_get_retry 3
delay_before_retry 3
}
}
}
2.重复服务
[root@master ~]# systemctl enable keepalived
[root@master ~]# systemctl start keepalived
2.备服务器配置keepalived
关闭防火墙和selinux
[root@slave ~]# systemctl stop firewalld
[root@slave ~]# systemctl disable firewalld
[root@slave ~]# setenforce 0
[root@slave ~]# sed -ri 's/^(SELINUX=).*/\1disabled/g' /etc/selinux/config
配置网络源
[root@slave ~]# curl -o /etc/yum.repos.d/CentOS7-Base-163.repo http://mirrors.163.com/.help/CentOS7-Base-163.repo
[root@slave ~]# sed -i 's/\$releasever/7/g' /etc/yum.repos.d/CentOS7-Base-163.repo
[root@slave ~]# sed -i 's/^enabled=.*/enabled=1/g' /etc/yum.repos.d/CentOS7-Base-163.repo
[root@slave ~]# yum -y install epel-release vim wget gcc gcc-c++
安装keepalived
[root@slave ~]# yum -y install keepalived
备份配置文件
[root@slave ~]# cd /etc/keepalived
[root@slave keepalived]# cp keepalived.conf{,-bak}
[root@slave keepalived]# ls
keepalived.conf keepalived.conf-bak
1.编辑配置文件
[root@slave keepalived]# vim keepalived.conf
! Configuration File for keepalived
global_defs {
router_id lb02
}
vrrp_instance VI_1 {
state BACKUP
interface ens33
virtual_router_id 20 ##要与主服务器一致
priority 80
nopreempt
advert_int 1
authentication {
auth_type PASS
auth_pass zyy ##要与主服务器一致
}
virtual_ipaddress {
192.168.30.246
}
}
virtual_server 192.168.30.246 80 {
delay_loop 6
lb_algo rr
lb_kind DR
persistence_timeout 50
protocol TCP
real_server 192.168.30.244 80 {
weight 1
TCP_CHECK {
connect_port 80
connect_timeout 3
nb_get_retry 3
delay_before_retry 3
}
}
real_server 192.168.30.245 80 {
weight 1
TCP_CHECK {
connect_port 80
connect_timeout 3
nb_get_retry 3
delay_before_retry 3
}
}
}
2.重启服务
[root@slave ~]# systemctl enable keepalived
[root@slave ~]# systemctl start keepalived
网卡信息
[root@master ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> 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: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 00:0c:29:e2:be:9a brd ff:ff:ff:ff:ff:ff
inet 192.168.30.244/24 brd 192.168.30.255 scope global ens33
valid_lft forever preferred_lft forever
inet 192.168.30.246/32 scope global ens33 ##VIP在那台主机,那台主机时主服务器
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:fee2:be9a/64 scope link
valid_lft forever preferred_lft forever
[root@slave ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> 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: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 00:0c:29:c8:03:9e brd ff:ff:ff:ff:ff:ff
inet 192.168.30.245/24 brd 192.168.30.255 scope global ens33
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:fec8:39e/64 scope link
valid_lft forever preferred_lft forever
测试效果
[root@master ~]# systemctl stop httpd
[root@slave scripts]# ss -anlt
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 *:22 *:*
LISTEN 0 100 127.0.0.1:25 *:*
LISTEN 0 128 :::80 :::*
LISTEN 0 128 :::22 :::*
LISTEN 0 100 ::1:25 :::*
[root@slave ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> 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: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 00:0c:29:c8:03:9e brd ff:ff:ff:ff:ff:ff
inet 192.168.30.245/24 brd 192.168.30.255 scope global ens33
valid_lft forever preferred_lft forever
inet 192.168.30.246/32 scope global ens33
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:fec8:39e/64 scope link
valid_lft forever preferred_lft forever
3.让keepalived监控Apache负载均衡机
3.1.在master上编写脚本
[root@master ~]# mkdir /scripts/
[root@master ~]# cd /scripts/
[root@master scripts]# vim check_httpd.sh
#!/bin/bash
httpd_status=$(ps -ef|grep -Ev "grep|$0"|grep '\httpd\b'|wc -l)
if [ $httpd_status -lt 1 ];then
systemctl stop keepalived
fi
## httpd服务如果不存在,证明服务中断,需要切换主备
[root@master scripts]# vim notify.sh
#!/bin/bash
case "$1" in
master)
httpd_status=$(ps -ef|grep -Ev "grep|$0"|grep '\httpd\b'|wc -l)
if [ $httpd_status -lt 1 ];then
systemctl start httpd
fi
sendmail
;;
backup)
httpd_status=$(ps -ef|grep -Ev "grep|$0"|grep '\bhttpd\b'|wc -l)
if [ $httpd_status -gt 0 ];then
systemctl stop httpd
fi
;;
*)
echo "Usage:$0 master|backup VIP"
;;
esac
给权限
[root@master scripts]# chmod +x check_httpd.sh
[root@master scripts]# chmod +x notify.sh
[root@master scripts]# ll
总用量 8
-rwxr-xr-x 1 root root 141 8月 4 18:41 check_httpd.sh
-rwxr-xr-x 1 root root 662 8月 4 18:44 notify.sh
3.2.在slave编写脚本
[root@slave ~]# mkdir /scripts/
[root@slave ~]# cd /scripts/
[root@slave scripts]# vim notify.sh
#!/bin/bash
VIP=$2
case "$1" in
master)
httpd_status=$(ps -ef|grep -Ev "grep|$0"|grep '\httpd\b'|wc -l)
if [ $httpd_status -lt 1 ];then
systemctl start httpd
fi
sendmail
;;
backup)
httpd_status=$(ps -ef|grep -Ev "grep|$0"|grep '\bhttpd\b'|wc -l)
if [ $httpd_status -gt 0 ];then
systemctl stop httpd
fi
;;
*)
echo "Usage:$0 master|backup VIP"
;;
esac
4.将监控脚本加入到配置文件
4.1.添加脚本到主服务器配置文件
[root@master ~]# vim /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
router_id lb01
}
vrrp_script httpd_check { ##随时检测httpd服务情况
script "/scripts/check_httpd.sh" ##脚本位置
interval 1
weight -50 ##优先级减去50
}
vrrp_instance VI_1 {
state MASTER
interface ens33
virtual_router_id 20
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass zyy
}
virtual_ipaddress {
192.168.30.246
}
track_script { ##跟踪脚本
httpd_check
}
notify_master "/scripts/notify.sh master 192.168.30.246" ##为master时,所做操作
notify_backup "/scripts/notify.sh backup 192.168.30.246" ##为slave时,所做操作
}
virtual_server 192.168.30.246 80 {
delay_loop 6
lb_algo rr
lb_kind DR
persistence_timeout 50
protocol TCP
real_server 192.168.30.244 80 {
weight 1
TCP_CHECK {
connect_port 80
connect_timeout 3
nb_get_retry 3
delay_before_retry 3
}
}
real_server 192.168.30.245 80 {
weight 1
TCP_CHECK {
connect_port 80
connect_timeout 3
nb_get_retry 3
delay_before_retry 3
}
}
}
[root@master ~]# systemctl restart keepalived
4.2.添加脚本到备服务器配置文件
[root@slave ~]# vim /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
router_id lb02
}
vrrp_instance VI_1 {
state BACKUP
interface ens33
virtual_router_id 20
priority 80
nopreempt
advert_int 1
authentication {
auth_type PASS
auth_pass zyy
}
virtual_ipaddress {
192.168.30.246
}
notify_master "/scripts/notify.sh master 192.168.30.246" ##为master时,要做的操作
notify_backup "/scripts/notify.sh backup 192.168.30.246" ##为slave时,要做操作
}
virtual_server 192.168.30.246 80 {
delay_loop 6
lb_algo rr
lb_kind DR
persistence_timeout 50
protocol TCP
real_server 192.168.30.244 80 {
weight 1
TCP_CHECK {
connect_port 80
connect_timeout 3
nb_get_retry 3
delay_before_retry 3
}
}
real_server 192.168.30.245 80 {
weight 1
TCP_CHECK {
connect_port 80
connect_timeout 3
nb_get_retry 3
delay_before_retry 3
}
}
}
[root@slave ~]# systemctl restart keepalived
5.效果
此时 192.168.30.244是主服务器
[root@master ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> 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: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 00:0c:29:e2:be:9a brd ff:ff:ff:ff:ff:ff
inet 192.168.30.244/24 brd 192.168.30.255 scope global ens33
valid_lft forever preferred_lft forever
inet 192.168.30.246/32 scope global ens33
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:fee2:be9a/64 scope link
valid_lft forever preferred_lft forever
在master将httpd服务关闭,发现VIP不见了
在备服务器上查看,VIP实现了跳转,且80端口也已经开启
服务也在正常运行
3.keepalived配置文件解释
3.1.keepalived配置文件
[root@master ~]# cat /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs { //全局配置
notification_email { //定义报警收件人邮件地址
acassen@firewall.loc
failover@firewall.loc
sysadmin@firewall.loc
}
notification_email_from Alexandre.Cassen@firewall.loc //定义报警发件人邮箱
smtp_server 192.168.200.1 //邮箱服务器地址
smtp_connect_timeout 30 //定义邮箱超时时间
router_id LVS_DEVEL //定义路由标识信息,同局域网内唯一
vrrp_skip_check_adv_addr
vrrp_strict
vrrp_garp_interval 0
vrrp_gna_interval 0
}
vrrp_instance VI_1 { //定义实例
state MASTER //指定keepalived节点的初始状态,可选值为MASTER|BACKUP
interface eth0 //VRRP实例绑定的网卡接口,用户发送VRRP包
virtual_router_id 51 //虚拟路由的ID,同一集群要一致
priority 100 //定义优先级,按优先级来决定主备角色,优先级越大越优先
nopreempt //设置不抢占
advert_int 1 //主备通讯时间间隔
authentication { //配置认证
auth_type PASS //认证方式,此处为密码
auth_pass 1111 //同一集群中的keepalived配置里的此处必须一致,推荐使用8位随机数
}
virtual_ipaddress { //配置要使用的VIP地址
192.168.200.16
}
}
virtual_server 192.168.200.16 1358 { //配置虚拟服务器
delay_loop 6 //健康检查的时间间隔
lb_algo rr //lvs调度算法
lb_kind NAT //lvs模式
persistence_timeout 50 //持久化超时时间,单位是秒
protocol TCP //4层协议
sorry_server 192.168.200.200 1358 //定义备用服务器,当所有RS都故障时用sorry_server来响应客户端
real_server 192.168.200.2 1358 { //定义真实处理请求的服务器
weight 1 //给服务器指定权重,默认为1
HTTP_GET {
url {
path /testurl/test.jsp //指定要检查的URL路径
digest 640205b7b0fc66c1ea91c463fac6334d //摘要信息
}
url {
path /testurl2/test.jsp
digest 640205b7b0fc66c1ea91c463fac6334d
}
url {
path /testurl3/test.jsp
digest 640205b7b0fc66c1ea91c463fac6334d
}
connect_timeout 3 //连接超时时间
nb_get_retry 3 //get尝试次数
delay_before_retry 3 //在尝试之前延迟多长时间
}
}
real_server 192.168.200.3 1358 {
weight 1
HTTP_GET {
url {
path /testurl/test.jsp
digest 640205b7b0fc66c1ea91c463fac6334c
}
url {
path /testurl2/test.jsp
digest 640205b7b0fc66c1ea91c463fac6334c
}
connect_timeout 3
nb_get_retry 3
delay_before_retry 3
}
}
}
3.2.定制主配置文件
vrrp_instance段配置
nopreempt //设置为不抢占。默认是抢占的,当高优先级的机器恢复后,会抢占低优先 \
级的机器成为MASTER,而不抢占,则允许低优先级的机器继续成为MASTER,即使高优先级 \
的机器已经上线。如果要使用这个功能,则初始化状态必须为BACKUP。
preempt_delay //设置抢占延迟。单位是秒,范围是0---1000,默认是0.发现低优先 \
级的MASTER后多少秒开始抢占。
vrrp_script段配置
//作用:添加一个周期性执行的脚本。脚本的退出状态码会被调用它的所有的VRRP Instance记录。
//注意:至少有一个VRRP实例调用它并且优先级不能为0.优先级范围是1-254.
vrrp_script <SCRIPT_NAME> {
...
}
//选项说明:
script "/path/to/somewhere" //指定要执行的脚本的路径。
interval <INTEGER> //指定脚本执行的间隔。单位是秒。默认为1s。
timeout <INTEGER> //指定在多少秒后,脚本被认为执行失败。
weight <-254 --- 254> //调整优先级。默认为2.
rise <INTEGER> //执行成功多少次才认为是成功。
fall <INTEGER> //执行失败多少次才认为失败。
user <USERNAME> [GROUPNAME] //运行脚本的用户和组。
init_fail //假设脚本初始状态是失败状态。
//weight说明:
1. 如果脚本执行成功(退出状态码为0),weight大于0,则priority增加。
2. 如果脚本执行失败(退出状态码为非0),weight小于0,则priority减少。
3. 其他情况下,priority不变。
real_server段配置
weight <INT> //给服务器指定权重。默认是1
inhibit_on_failure //当服务器健康检查失败时,将其weight设置为0, \
//而不是从Virtual Server中移除
notify_up <STRING> //当服务器健康检查成功时,执行的脚本
notify_down <STRING> //当服务器健康检查失败时,执行的脚本
uthreshold <INT> //到这台服务器的最大连接数
lthreshold <INT> //到这台服务器的最小连接数
tcp_check段配置
connect_ip <IP ADDRESS> //连接的IP地址。默认是real server的ip地址
connect_port <PORT> //连接的端口。默认是real server的端口
bindto <IP ADDRESS> //发起连接的接口的地址。
bind_port <PORT> //发起连接的源端口。
connect_timeout <INT> //连接超时时间。默认是5s。
fwmark <INTEGER> //使用fwmark对所有出去的检查数据包进行标记。
warmup <INT> //指定一个随机延迟,最大为N秒。可防止网络阻塞。如果为0,则关闭该功能。
retry <INIT> //重试次数。默认是1次。
delay_before_retry <INT> //默认是1秒。在重试之前延迟多少秒。
实例
global_defs {
router_id LVS_Server
}
vrrp_instance VI_1 {
state BACKUP
interface ens33
virtual_router_id 51
priority 150
nopreempt
advert_int 1
authentication {
auth_type PASS
auth_pass wangqing
}
virtual_ipaddress {
172.16.12.250 dev ens33
}
}
virtual_server 172.16.12.250 80 {
delay_loop 3
lvs_sched rr
lvs_method DR
protocol TCP
real_server 172.16.12.129 80 {
weight 1
TCP_CHECK {
connect_port 80
connect_timeout 3
nb_get_retry 3
delay_before_retry 3
}
}
real_server 172.16.12.130 8080 {
weight 1
TCP_CHECK {
connect_port 8080
connect_timeout 3
nb_get_retry 3
delay_before_retry 3
}
}
}