本章概要
集群Cluster
提供(构建高可用)服务的关键因素:
ip地址:进入服务器的接口。
如果使用固定ip地址提供服务,那么备用主机则必须能够拿到该固定ip才能够在活动主机故障后成为活动主机
process:用户空间的进程对客户端提供服务
相对于ipvs来说,没有进程的说法,仅是内核空间的规则
storage:数据同步问题
对于mysql数据库来说,主备只能解决设备问题,备用服务器无法获取数据库中的数据,因此需要解决数据同步的问题
数据同步:
主从复制:使用软件或某个服务脱离于系统本身,对数据进行数据主从复制完成数据同步
rsync_inotify 文件级同步
drbd kernel2.6.33 分布式复制块设备
在不安装第三方软件,基于内核模块的情况下,把两个主机之上的两个磁盘或磁盘分区做成跨主机的镜像设备,
当在其中一块磁盘写入数据时,会同步到另外一块镜像磁盘上,实现数据同步的功能,系统可用性最高达到99.5%
KeepAlived介绍
keepalived 协议
即vrrp的软件实现,能够安装在linux主机上,让linux主机像路由器一样能漂移ip地址,完成地址转移
第一个功能模块
keepalived基于VRRP(虚拟路由冗余协议)协议,仅用于ip地址转移
对于构建高可用服务来说,keepalived仅能够实现ip地址的功能,对于进程和存储,则无能为力
keepalived设计之初就是为ipvs提供高可用集群
第二个模块
IPVS wrapper
可以通过自身配置文件生成ipvs规则
第三个模块
Checkers
能对ipvs的后端服务器real server做健康状态检测,这就补充了ipvs不能做健康状态检测的缺点,为ipvs添加了在多个节点之上实现高可用的功能
扩展功能:
调用外置脚本,完成必要的管理操作,如通过脚本管理nginx或haproxy实现高可用
KeepAlived组成
知识扩展:
VRRP协议介绍
虚拟路由冗余协议
VRID 虚拟路由标识
由两个或两个以上的路由器组成,在虚拟路由器中存在一个master路由器,多个backup路由器
接收客户端请求的VIP地址配置在master路由器上,有master路由器承载报文的转发,当master出现故障,由backup路由器代替master路由器进行工作
虚拟ip地址,即VIP,一个虚拟路由器可以配置一个或多个虚拟ip地址
虚拟mac地址
master选举方式:
优先级
根据优先级确定虚拟路由器中每台物理路由器的地位
抢占式
根据优先级进行选举主节点和从节点
该模式导致网络格局出现不稳定
非抢占式
只要选举出主节点,并且主节点无故障,即使增加优先级更高的节点,也不会触发新的选举操作
KeepAlived实现
知识扩展:
如何完成ip地址转移
vrrp通过将多个物理设备组建为一个虚拟设备组并通过优先级和选举机制来确保始终有一个当下优先级最高的节点能持有并配置虚拟ip地址并接收并服务于用户请求,
一旦节点出现故障,会重新触发选举操作,选举出一个新的节点,并将ip地址配置在新的主节点上,进而保证有节点转发客户端的访问请求,实现高可用服务的效果
本地通信通过mac地址实现,当主节点设备出现故障后,从节点代替主节点进行报文的转发,拿到vip地址(虚拟ip地址),
但由于客户端记录mac地址为原主节点设备的mac地址,因此二者仍然无法通信
如何使二者能够通信呢?
gracious arp
当主节点出现故障后,从节点代替主节点,当从节点成为主节点之后,拿到vip地址,会通过免费arp发送广播报文宣告自己的mac地址,
当其他设备接收到该广播报文后发现mac地址与vip的对应关系不一致,就更新自己的arp表,从而实现与新的主节点通信
KeepAlived配置
查看配置文件man帮助信息:
查看配置文件具体信息:man keepalived.conf
GLOBAL和VRRP配置段:
Global definitions
global_defs # Block id
{
notification_email # To: #用于接收告警邮件的邮件地址,用于定义目标收件人
{
[email protected]
...
}
notification_email_from [email protected]
smtp_server 127.0.0.1 []
模拟发件人,由keepalived自动生成,调用mstp server向目标收件人发邮件
发送邮件场景:当主从节点发生转移,lvs中某个real server的上限或下限
vrrp_mcast_group4 224.0.0.18 定义组播域的ip地址,默认为224.0.0.18
主节点发送心跳信息,通过组播发送给组播域中的所有主机
如果生产环境中只有一个keepalived集群,使用默认即可
在ip地址分类中,组播地址段为:224.0.0.0-239.0.0.0
只有所有主机同用一个组播地址,才在一个组播域,组播地址可配置在多个主机之上
VRRP instance配置段
配置虚拟路由器:
vrrp_instance {
....
}
专用参数:
state MASTER|BACKUP:当前节点在此虚拟路由器上的初始状态;只能有一个是MASTER,余下的都应该为BACKUP
interface IFACE_NAME:绑定为当前虚拟路由器使用的物理接口
virtual_router_id VRID:当前虚拟路由器惟一标识,范围是0-255
priority 100:当前物理节点在此虚拟路由器中的优先级;范围1-254
advert_int 1:vrrp通告的时间间隔,默认1s
authentication { #认证机制
auth_type AH|PASS PASS指明文认证,AH认证方式尚未研发完成
auth_pass 仅前8字节有效,默认为1234
}
virtual_ipaddress { #虚拟IP
/ brd dev scope label
示例:
authentication { #认证机制
auth_type AH|PASS
auth_pass 仅前8位有效
}
virtual_ipaddress { #虚拟IP
/ brd dev scope label
VIP地址:192.168.32.200
主节点配置:
! Configuration File for keepalived
global_defs {
notification_email {
root@localhost #接收邮件通知的地址
}
notification_email_from keepalived@localhost #发件人地址,可以随便冒充,有没有该用户都可以
smtp_server 127.0.0.1 #指定真正的邮件服务器,这里实验以本机ip为例
smtp_connect_timeout 30
router_id k1 #当前物理设备的物理主机名
vrrp_skip_check_adv_addr #跳过检查通告地址
vrrp_strict #工作于严格模式下
vrrp_garp_interval 0
vrrp_iptables #当启动keepalived服务时,会自动在iptables中INPUT链增加一条防火墙规则:拒绝所有ip地址访问本机,防止其他主机通过访问本机对后端主机产生危害。添加vrrp_iptables 表示不会自动添加iptables规则
vrrp_gna_interval 0
vrrp_mcast_group4 224.0.45.1 #组播地址
}
注意:要查看本机是否支持组播,使用ifconfig查看是否出现MULTICAST字样,如果没有出现,进行以下设置开启组播:ip link set ens32
vrrp_instance VI_1 { #定义虚拟路由器实例VI_1,名称可自定义
state MASTER #定义初始状态,该节点为MASTER,其他节点必须为BACKUP
interface ens33 #虚拟ip地址接口
virtual_router_id 55 #虚拟路由id
priority 100 #主节点权限为100,其他节点必须低于该权限值
advert_int 1
authentication {
auth_type PASS #明文认证
auth_pass 1212 #密码默认为1111,可自定义
}
virtual_ipaddress { #配置VIP地址
192.168.32.200/16 brd 192.168.255.255 dev ens33 label ens33:0 #指定VIP地址,广播地址,网卡,别名
}
}
从节点配置:
! Configuration File for keepalived
global_defs {
notification_email {
root@localhost
}
notification_email_from keepalived@localhost
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id k1
vrrp_skip_check_adv_addr
vrrp_strict
vrrp_garp_interval 0
vrrp_iptables
vrrp_gna_interval 0
vrrp_mcast_group4 224.0.45.1
}
vrrp_instance VI_1 {
state BACKUP #指定初始状态
interface ens33
virtual_router_id 55
priority 98
advert_int 1
authentication {
auth_type PASS
auth_pass 1212
}
virtual_ipaddress {
192.168.32.200/16 brd 192.168.255.255 dev ens33 label ens33:0 #VIP地址不变,网卡名称根据本机网卡名称进行更改
}
}
测试:
在从节点抓取本地ens33网卡的信息,查看报文信息
tcpdump -i ens33 -nn host 224.0.45.1
启动从节点keepalived服务,报文信息:
16:20:27.176316 IP 192.168.32.130 > 224.0.45.1: VRRPv2, Advertisement, vrid 55, prio 98, authtype simple, intvl 1s, length 20
在从节点使用ifconfig命令查看ip地址
发现存在ens33:0,ip地址为192.168.32.200
注意:当启动keepalived服务时,会自动在iptables中INPUT链增加一条防火墙规则:拒绝所有ip地址访问本机,防止其他主机通过访问本机对后端主机产生危害。可以在全局配置文件中添加vrrp iptables 表示不会自动添加iptables规则
在主节点启动keepalived服务
查看从节点主机抓取的报文信息:
16:26:42.725777 IP 192.168.32.130 > 224.0.45.1: VRRPv2, Advertisement, vrid 55, prio 98, authtype simple, intvl 1s, length 20
16:26:43.728074 IP 192.168.32.129 > 224.0.45.1: VRRPv2, Advertisement, vrid 55, prio 100, authtype simple, intvl 1s, length 20
发现主节点会自动代替从节点,因为其权限为100
查看从节点主机keepalived服务状态
Nov 17 16:26:42 k2.magedu.com Keepalived_vrrp[50032]: VRRP_Instance(VI_1) Received advert with higher priority 100, ours 98 #接收优先级100的通告报文
Nov 17 16:26:42 k2.magedu.com Keepalived_vrrp[50032]: VRRP_Instance(VI_1) Entering BACKUP STATE #自动进入从节点状态
Nov 17 16:26:42 k2.magedu.com Keepalived_vrrp[50032]: VRRP_Instance(VI_1) removing protocol VIPs. #自动移除vip地址
Nov 17 16:26:42 k2.magedu.com Keepalived_vrrp[50032]: VRRP_Instance(VI_1) removing protocol iptable drop rule #自动移动添加的iptables规则
此时vip地址192.168.32.200自动转移到主节点上
KeepAlived双主配置
示例:KeepAlived双主配置
主节点配置:
! Configuration File for keepalived
global_defs {
notification_email {
root@localhost #接收邮件通知的地址
}
notification_email_from keepalived@localhost #发件人地址,可以随便冒充,有没有该用户都可以
smtp_server 127.0.0.1 #指定真正的邮件服务器,这里实验以本机ip为例
smtp_connect_timeout 30
router_id k1 #当前物理设备的物理主机名
vrrp_skip_check_adv_addr #跳过检查通告地址
vrrp_strict #工作于严格模式下
vrrp_garp_interval 0
vrrp_iptables #当启动keepalived服务时,会自动在iptables中INPUT链增加一条防火墙规则:拒绝所有ip地址访问本机,防止其他主机通过访问本机对后端主机产生危害。添加vrrp_iptables 表示不会自动添加iptables规则
vrrp_gna_interval 0
vrrp_mcast_group4 224.0.45.1 #组播地址
}
注意:要查看本机是否支持组播,使用ifconfig查看是否出现MULTICAST字样,如果没有出现,进行以下设置开启组播:ip link set ens32
vrrp_instance VI_1 { #定义虚拟路由器实例VI_1的主节点,名称可自定义
state MASTER #定义初始状态,该节点为MASTER,其他节点必须为BACKUP
interface ens33 #虚拟ip地址接口
virtual_router_id 55 #虚拟路由id
priority 100 #主节点权限为100,其他节点必须低于该权限值
advert_int 1
authentication {
auth_type PASS #明文认证
auth_pass 1212 #密码默认为1111,可自定义
}
virtual_ipaddress { #配置VIP地址
192.168.32.200/16 brd 192.168.255.255 dev ens33 label ens33:0 #指定实例1的VIP地址,广播地址,网卡,别名
}
}
vrrp_instance VI_2 { #定义虚拟路由器实例VI_2的从节点
state BACKUP #初始状态必须与示例1不同为,作为实例2的BACKUP
interface ens33
virtual_router_id 57 #虚拟路由器id号必须与实例1区分开
priority 98 #定义实例2的优先级,从节点需要小于100
advert_int 1
authentication {
auth_type PASS
auth_pass 3232
}
virtual_ipaddress {
192.168.32.201/16 brd 192.168.255.255 dev ens33 label ens33:1 #指定示例2的VIP地址,广播地址,网卡,别名。注意VIP地址,别名要与实例1区分开
}
}
从节点配置:
! Configuration File for keepalived
global_defs {
notification_email {
root@localhost
}
notification_email_from keepalived@localhost
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id k1
vrrp_skip_check_adv_addr
vrrp_strict
vrrp_garp_interval 0
vrrp_iptables
vrrp_gna_interval 0
vrrp_mcast_group4 224.0.45.1
}
vrrp_instance VI_1 {
state BACKUP #指定初始状态
interface ens33
virtual_router_id 55
priority 98
advert_int 1
authentication {
auth_type PASS
auth_pass 1212
}
virtual_ipaddress {
192.168.32.200/16 brd 192.168.255.255 dev ens33 label ens33:0 #VIP地址不变,网卡名称根据本机网卡名称进行更改
}
}
vrrp_instance VI_2 {
state MASTER
interface ens33
virtual_router_id 57
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 3232
}
virtual_ipaddress {
192.168.32.201/16 brd 192.168.255.255 dev ens33 label ens33:1
}
}
注意:双主模式中,192.168.32.200为实例1的VIP地址,且192.168.32.129主机在实例1权限为100,因此该vip地址在192.168.32.129主机上;
而192.168.32.201为实例2的VIP地址,且192.168.32.130主机在实例2权限为100,因此该vip地址在192.168.32.130主机上
keepalived可以高可用不需要存储服务的调度器服务,如haproxy,nginx,或者高可用其他集群服务中用于接入用户请求,但本地不存储状态的无状态服务,如k8s中的API server
cd /etc/keepalived/
vim notify.sh
#!/bin/bash
#
contact='root@localhost' #邮件接收者
notify() { #定义函数
local mailsubject="$(hostname) to be $1, vip floating" #定义邮件标题
local mailbody="$(date +'%F %T'): vrrp transition, $(hostname) changed to be $1" #定义邮件实体
echo "$mailbody" | mail -s "$mailsubject" $contact
}
case $1 in
master)
notify master
;;
backup)
notify backup
;;
fault)
notify fault
;;
*)
echo "Usage: $(basename $0) {master|backup|fault}"
exit 1
;;
esac
主节点配置文件:
vrrp_instance VI_1 {
state MASTER
interface ens33
virtual_router_id 55
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1212
}
virtual_ipaddress {
192.168.32.200/16 brd 192.168.255.255 dev ens33 label ens33:0
}
notify_master "/etc/keepalived/notify.sh master"
notify_master "/etc/keepalived/notify.sh master"
notify_fault "/etc/keepalived/notify.sh fault"
}
重启服务
systemctl restart keepalived
从节点配置文件:
vrrp_instance VI_1 {
state BACKUP
interface ens33
virtual_router_id 55
priority 98
advert_int 1
authentication {
auth_type PASS
auth_pass 1212
}
virtual_ipaddress {
192.168.32.200/16 brd 192.168.255.255 dev ens33 label ens33:0
}
notify_master "/etc/keepalived/notify.sh master"
notify_master "/etc/keepalived/notify.sh master"
notify_fault "/etc/keepalived/notify.sh fault"
}
重启服务
systemctl restart keepalived
当keepalived服务状态发生变化时,查看邮件服务器或本机(以实验为例)的邮件,可以看到通过脚本发送得状态转换信息
KeepAlived配置检测
以集群lvs-dr模式为例
实验环境:
虚拟路由器中两台物理服务器充当物理路由器分别是K1,K2
K1 192.168.32.129
K2 192.168.32.130
后端服务器RS1 192.168.32.131
后端服务器RS2 192.168.32.132
客户端:192.168.32.128
准备工作:
在keepalived主从节点(lvs调度器本身)设置sorry server
当启用nginx服务时,会自动监听80端口,这样还能否通过80端口做集群服务呢。
是可以的,因为客户端通过80端口访问后端服务器的所有请求首先通过VIP地址,通过PREROUTING链,然后才到达INPUT链,最后到达用户空间被nginx进程收到,但是一旦配置集群服务后,访问请求在达到INPUT之前就被ipvs模块转发出去,因此nginx无论是否监听80端口,都收不到报文请求,只有在后端服务器全部down掉之后,才会被转发给lvs调度器自身的nginx进程,因此本机开启nginx服务监听80端口并不影响集群服务
设置sorry server测试页面
K1:
安装nginx服务
设置测试页:
vim /usr/share/nginx/html/index.html
K1 Sorry Server!
K2:
安装nginx服务
设置测试页:
vim /usr/share/nginx/html/index.html
K2 Sorry Server!
设置后端服务器测试页面
RS1:
安装nginx服务
设置测试页:
vim /usr/share/nginx/html/index.html
RS1 Sorry Server!
RS2:
安装nginx服务
设置测试页:
vim /usr/share/nginx/html/index.html
RS2 Sorry Server!
测试:测试集群服务能够正常工作
配置脚本完成配置工作
vim lvs_dr_rs.sh
#!/bin/bash
#Author:wangxiaochun
#Date:2017-08-13
vip=192.168.32.200 #指定VIP地址变量
mask='255.255.255.255' #指定掩码的变量,为32位,本网段只有一个ip地址
dev=lo:1 #指定本地环回接口的变量
case $1 in
start) #写配置文件使环回接口不宣告不回应arp广播包
echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore
echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce
ifconfig $dev $vip netmask $mask broadcast $vip up #把VIP地址绑定到本地lo网卡,并启用广播功能
route add -host $vip $dev #添加路由:如果是请求VIP地址的请求通过lo网卡进入(可省略)
echo "The RS Server is Ready!"
;;
stop) #取消写入配置文件的参数
ifconfig $dev down
echo 0 > /proc/sys/net/ipv4/conf/all/arp_ignore
echo 0 > /proc/sys/net/ipv4/conf/lo/arp_ignore
echo 0 > /proc/sys/net/ipv4/conf/all/arp_announce
echo 0 > /proc/sys/net/ipv4/conf/lo/arp_announce
echo "The RS Server is Canceled!"
;;
*)
echo "Usage: $(basename $0) start|stop"
exit 1
;;
esac
在RS1和RS2上分别执行此脚本
bash bash lvs_dr_rs.sh start
在K1服务器配置lvs调度规则,测试是否能通
在K1服务器绑定VIP到ens33网卡子接口
ifconfig ens33:0 192.168.32.200 netmask 255.255.255.255 broadcast 192.168.32.200 up
配置ipvs规则
ipvsadm -A -t 192.168.32.200:80 -s wrr
ipvsadm -a -t 192.168.32.200:80 -r 192.168.32.131 -g
ipvsadm -a -t 192.168.32.200:80 -r 192.168.32.132 -g
在客户端测试是否能够正常工作
while true ;do curl http://192.168.32.200;sleep 0.5;done;
如果能够通过wrr算法调度成功说明K1作为lvs调度器没有问题
删除ipvs规则,删除绑定ens33:0接口的ip地址
在K2服务器上做同样的操作以测试K2作为lvs服务器是否可以正常调度
K1服务器(lvs调度器1)配置:
[root@k1 ~]# vim /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
notification_email {
root@localhost
}
notification_email_from keepalived@localhost
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id k1
vrrp_skip_check_adv_addr
vrrp_strict
vrrp_garp_interval 0
vrrp_iptables
vrrp_gna_interval 0
vrrp_mcast_group4 224.0.45.1
}
vrrp_instance VI_1 {
state MASTER
interface ens33
virtual_router_id 55
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1212
}
virtual_ipaddress {
192.168.32.200/16 brd 192.168.255.255 dev ens33 label ens33:0
}
notify_master "/etc/keepalived/notify.sh master"
notify_master "/etc/keepalived/notify.sh master"
notify_fault "/etc/keepalived/notify.sh fault"
}
virtual_server 192.168.32.200 80 {
delay_loop 2
lb_algo wrr
lb_kind DR
protocol TCP
sorry_server 127.0.0.1 80
real_server 192.168.32.131 80 {
weight 1
HTTP_GET {
url {
path /
status_code 200
}
connect_timeout 1
nb_get_retry 3
delay_before_retry 1
}
}
real_server 192.168.32.132 80 {
weight 1
HTTP_GET {
url {
path /
status_code 200
}
connect_timeout 1
nb_get_retry 3
delay_before_retry 1
}
}
}
K2服务器(lvs调度器2)配置:
[root@k2 html]# vim /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs { #全局配置
notification_email {
root@localhost
}
notification_email_from keepalived@localhost
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id k1
vrrp_skip_check_adv_addr
vrrp_strict
vrrp_garp_interval 0
vrrp_iptables
vrrp_gna_interval 0
vrrp_mcast_group4 224.0.45.1
}
vrrp_instance VI_1 { #虚拟路由器实例1配置
state BACKUP
interface ens33
virtual_router_id 55
priority 98
advert_int 1
authentication {
auth_type PASS
auth_pass 1212
}
virtual_ipaddress {
192.168.32.200/16 brd 192.168.255.255 dev ens33 label ens33:0
}
notify_master "/etc/keepalived/notify.sh master"
notify_master "/etc/keepalived/notify.sh master"
notify_fault "/etc/keepalived/notify.sh fault"
}
virtual_server 192.168.32.200 80 { #虚拟服务器配置
delay_loop 2
lb_algo wrr
lb_kind DR
protocol TCP
sorry_server 127.0.0.1 80
real_server 192.168.32.131 80 { #后端服务器(real server)1配置
weight 1
HTTP_GET {
url {
path /
status_code 200
}
connect_timeout 1
nb_get_retry 3
delay_before_retry 1
}
}
real_server 192.168.32.132 80 { #后端服务器(real server)2配置
weight 1
HTTP_GET {
url {
path /
status_code 200
}
connect_timeout 1
nb_get_retry 3
delay_before_retry 1
}
}
}
注意:如果想要实现双主模型,则需要配置两个虚拟路由实例,使用两个虚拟ip地址(即VIP),在后端服务器配置基于FQDN的网页
在客户端基于域名访问时,能够实现负载均衡
重启keepalived服务
查看vip地址是否存在
查看ipvs规则是否已经生成
测试:
测试ipvs调度规则
关闭后端服务器,查看调度情况
关闭所有后端服务器,查看sorry server情况
测试keepalived主备
关闭K1或K2中keepalived服务,查看是否能够实现ip地址转移
关闭后端服务器,查看是否能够实现健康状态检测,自动切换
注意:
如果是集群lvs-nat模式,要配置同步组,在面对互联网的接口配置VIP,在面对内网的接口也要配置VIP,并且两个VIP要在同一个主机之上
如果使用lvs-nat的场景,推荐使用nginx或haproxy,复杂度更低,使用更高级的其他功能
同步组
vrrp_sync_group VG_1 {
group {
VI_1 # name of vrrp_instance (below)
VI_2 # One for each moveable IP.
}
}
vrrp_instance VI_1 {
eth0
vip
}
vrrp_instance VI_2 {
eth1
dip
}
双主模式的lvs集群
双主模式的lvs集群,拓扑、实现过程;
配置示例(一个节点):
! Configuration File for keepalived
global_defs {
notification_email {
root@localhost
}
notification_email_from kaadmin@localhost
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id node1
vrrp_mcast_group4 224.0.100.100
}
vrrp_instance VI_1 {
state MASTER
interface eth0
virtual_router_id 6
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass f1bf7fde
}
virtual_ipaddress {
172.16.0.80/16 dev eth0 label eth0:0
}
track_interface {
eth0
}
notify_master "/etc/keepalived/notify.sh master"
notify_backup "/etc/keepalived/notify.sh backup"
notify_fault "/etc/keepalived/notify.sh fault"
}
vrrp_instance VI_2 {
state BACKUP
interface eth0
virtual_router_id 8
priority 98
advert_int 1
authentication {
auth_type PASS
auth_pass f2bf7ade
}
virtual_ipaddress {
172.16.0.90/16 dev eth0 label eth0:1
}
track_interface {
eth0
}
notify_master "/etc/keepalived/notify.sh master"
notify_backup "/etc/keepalived/notify.sh backup"
notify_fault "/etc/keepalived/notify.sh fault"
}
virtual_server fwmark 3 {
delay_loop 2
lb_algo rr
lb_kind DR
nat_mask 255.255.0.0
protocol TCP
sorry_server 127.0.0.1 80
real_server 172.16.0.11 80 {
weight 1
HTTP_GET {
url {
path /
status_code 200
}
connect_timeout 2
nb_get_retry 3
delay_before_retry 3
}
}
real_server 172.16.0.12 80 {
weight 1
HTTP_GET {
url {
path /
status_code 200
}
connect_timeout 2
nb_get_retry 3
delay_before_retry 3
}
}
}
KeepAlived调用脚本进行资源监控
VRRP script(s)
# Adds a script to be executed periodically. Its exit code will be
# recorded for all VRRP instances which are monitoring it.
vrrp_script { #脚本名称
script | #指定脚本内容,可以是命令本身,如果是复杂脚本,需要指定脚本路径
interval #每隔多久执行一次,周期性执行脚本,监测外部关键资源是否正常
timeout #每一次监测请求超时时长
weight #权重-254~254,默认为0。
针对于某一实例来说,根据当前设置调整当前节点优先级是多少,这里的优先级是指虚拟路由器中节点的优先级。
如,定义优先级为10,如果脚本执行失败,那么该节点的优先级减去10
rise #至少有几次启动时状态监测为成功才会判定为成功
fall #至少有几次启动时状态检测为不成功才会判定为失败
user USERNAME [GROUPNAME] #以哪个用户的身份执行脚本
init_fail #认为脚本初始状态应该为失败状态,只有检查以后为成功,才会将其置为成功状态
}
vrrp_script {
script ""
interval INT
weight -INT
rise 2
fall 3
}
track_script {
SCRIPT_NAME_1
SCRIPT_NAME_2
...
}
注意:
vrrp_script chk_down {
script "/bin/bash -c '[[ -f /etc/keepalived/down ]]' && exit 1 || exit 0"
interval 1
weight -10
}
[[ -f /etc/keepalived/down ]]要特别地作为bash的参数的运行!
示例:使用脚本进行资源监控
主节点配置:
[root@k1 ~]# vim /etc/keepalived/keepalived.conf
global_defs {
notification_email {
root@localhost
}
notification_email_from keepalived@localhost
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id k1
vrrp_skip_check_adv_addr
vrrp_strict
vrrp_garp_interval 0
vrrp_iptables
vrrp_gna_interval 0
vrrp_mcast_group4 224.0.45.1
}
vrrp_script maint { #定义脚本maint
script " "/bin/bash -c '[[ -e /etc/keepalived/down ]]' && exit 1
|| exit 0" #当存在/etc/keepalived/down文件时返回1(失败),否则返回0(成功)。注意:"-e /etc/keepalived/down"命令字串在新版本keepalived配置文件中,默认不会开启shell执行,因此需要'/bin/bash -c'指定
interval 1
fall 3
rise 2
weight -5 #如果返回失败,则权重值减5,结果为95小于从节点优先级98,即实现自动降级
timeout 1
}
vrrp_instance VI_1 {
state MASTER
interface ens33
virtual_router_id 55
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1212
}
virtual_ipaddress {
192.168.32.200/16 brd 192.168.255.255 dev ens33 label ens33:0
}
track script { #在虚拟路由器实例1中调用脚本
maint
}
notify_master "/etc/keepalived/notify.sh master"
notify_master "/etc/keepalived/notify.sh master"
notify_fault "/etc/keepalived/notify.sh fault"
}
从节点配置:
[root@k2 ~]# vim /etc/keepalived/keepalived.conf
global_defs {
notification_email {
root@localhost
}
notification_email_from keepalived@localhost
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id k1
vrrp_skip_check_adv_addr
vrrp_strict
vrrp_garp_interval 0
vrrp_iptables
vrrp_gna_interval 0
vrrp_mcast_group4 224.0.45.1
}
vrrp_script maint { #定义脚本
script " "/bin/bash -c '[[ -e /etc/keepalived/down ]]' && exit 1
|| exit 0" #当存在/etc/keepalived/down文件时返回1(失败),否则返回0(成功)。注意:"-e /etc/keepalived/down"命令字串在新版本keepalived配置文件中,默认不会开启shell执行,因此需要'/bin/bash -c'指定
interval 1
fall 3
rise 2
weight -5 #如果返回失败,则权重值减5,结果为95小于从节点优先级98,即实现自动降级
timeout 1
}
vrrp_instance VI_1 {
state BACKUP
interface ens33
virtual_router_id 55
priority 98
advert_int 1
authentication {
auth_type PASS
auth_pass 1212
}
virtual_ipaddress {
192.168.32.200/16 brd 192.168.255.255 dev ens33 label ens33:0
}
track script { #调用脚本
maint
}
notify_master "/etc/keepalived/notify.sh master"
notify_master "/etc/keepalived/notify.sh master"
notify_fault "/etc/keepalived/notify.sh fault"
}
测试:
在K1服务抓包查看报文转发信息
tcpdump -i ens33 -nn host 224.0.45.1
在主节点K1服务器
在/etc/keepalived目录下创建down文件
cd /etc/keepalived
touch down
查看是否会实现自动降级(查看抓包信息或日志信息)
K1服务器抓包信息如下:
09:54:43.889550 IP 192.168.32.129 > 224.0.45.1: VRRPv2, Advertisement, vrid 55, prio 100, authtype simple, intvl 1s, length 20
09:54:44.891154 IP 192.168.32.129 > 224.0.45.1: VRRPv2, Advertisement, vrid 55, prio 95, authtype simple, intvl 1s, length 20
09:54:44.892227 IP 192.168.32.130 > 224.0.45.1: VRRPv2, Advertisement, vrid 55, prio 98, authtype simple, intvl 1s, length 20
K1服务器日志信息如下:
Nov 18 09:54:41 centos7 Keepalived_vrrp[12448]: /bin/bash -c '[[ -e /etc/keepalived/down ]]' && exit 1 || exit 0 exited with status 1
Nov 18 09:54:42 centos7 Keepalived_vrrp[12448]: /bin/bash -c '[[ -e /etc/keepalived/down ]]' && exit 1 || exit 0 exited with status 1
Nov 18 09:54:43 centos7 Keepalived_vrrp[12448]: /bin/bash -c '[[ -e /etc/keepalived/down ]]' && exit 1 || exit 0 exited with status 1
Nov 18 09:54:43 centos7 Keepalived_vrrp[12448]: VRRP_Script(maint) failed
Nov 18 09:54:44 centos7 Keepalived_vrrp[12448]: VRRP_Instance(VI_1) Changing effective priority from 100 to 95 #权限减5
Nov 18 09:54:44 centos7 Keepalived_vrrp[12448]: /bin/bash -c '[[ -e /etc/keepalived/down ]]' && exit 1 || exit 0 exited with status 1 #退出码为1
Nov 18 09:54:44 centos7 Keepalived_vrrp[12448]: VRRP_Instance(VI_1) Received advert with higher priority 98, ours 95 #从节点权限98高于降级后的主节点权限95
Nov 18 09:54:44 centos7 Keepalived_vrrp[12448]: VRRP_Instance(VI_1) Entering BACKUP STATE #主节点切换为BACKUP状态
Nov 18 09:54:44 centos7 Keepalived_vrrp[12448]: VRRP_Instance(VI_1) removing protocol VIPs. #转移VIP
Nov 18 09:54:44 centos7 avahi-daemon[575]: Withdrawing address record for 192.168.32.200 on ens33. #VIP地址192.168.32.200从ens33解除绑定
Nov 18 09:54:44 centos7 Keepalived_vrrp[12448]: VRRP_Instance(VI_1) removing protocol iptable drop rule #删除自动添加的iptables规则
在K2服务器(从节点)查看虚拟ip地址是否自动转移
[root@k2 ~]# ifconfig
ens33:0: flags=4163 mtu 1500
inet 192.168.32.200 netmask 255.255.0.0 broadcast 192.168.255.255
ether 00:0c:29:ca:4f:3d txqueuelen 1000 (Ethernet)
在/etc/keepalived目录下删除down文件,然后查看状态转换
cd /etc/keepalived
rm -rf down
示例:高可用nginx服务
使用nginx做代理服务器,如何实现nginx的高可用
写一个脚本,当nginx进程出现故障,自动实现对主节点自动降级,启动从节点代替主节点进行nginx代理
killall -0 相当于检测进程状态,如果有nginx进程存在能够承接kill操作(接收该信号),退出码为0,如果没有nginx进程能够承接kill操作(不能接收该信号),则退出码为非0值
该命令来自于psmisc软件包
示例:
[root@k1 keepalived]# systemctl start nginx
[root@k1 keepalived]# killall -0 nginx && echo $?
0
[root@k1 keepalived]# systemctl stop nginx
[root@k1 keepalived]# killall -0 nginx && echo $?
nginx: no process found
因此可利用'killall -0'检测nginx进程是否存在,如果存在返回码为0,主节点不变,一旦检测到nginx进程不存在,则返回码为非0,将主节点自动降级,实现VIP地址自动转移
另外,当主从节点状态切换时,会执行脚本(/etc/keepalived/notify.sh)自动发送邮件通知用户
并执行脚本发送邮件,我们可以在脚本(/etc/keepalived/notify.sh)中添加一条启动nginx进程的命令。
这样就可以实现,当nginx进程出现问题后,会自动切换状态并自行脚本发送邮件,当执行脚本时会执行重启nginx进程的命令,实现自动修复的效果
当主节点nginx服务重启不起来,那么从节点会成为主节点,代替主节点进行工作
主节点配置:
[root@k1 keepalived]# vim keepalived.conf
! Configuration File for keepalived
global_defs {
notification_email {
root@localhost
}
notification_email_from keepalived@localhost
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id k1
vrrp_skip_check_adv_addr
vrrp_iptables
vrrp_gna_interval 0
vrrp_mcast_group4 224.0.45.1
}
vrrp_script ngxchk { #添加nginx检测脚本
script "killall -0 nginx"
interval 1
fall 3
rise 2
weight -5
timeout 1
user root
}
vrrp_script maint {
script "/bin/bash -c '[[ -e /etc/keepalived/down ]]' && exit 1 ||
exit 0"
interval 1
fall 3
rise 2
weight -5
timeout 1
}
vrrp_instance VI_1 {
state MASTER
interface ens33
virtual_router_id 55
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1212
}
virtual_ipaddress {
192.168.32.200/16 brd 192.168.255.255 dev ens33 label ens33:0
}
track_script { #调用ngxchk脚本
maint
ngxchk
}
notify_master "/etc/keepalived/notify.sh master"
notify_master "/etc/keepalived/notify.sh backup"
notify_fault "/etc/keepalived/notify.sh fault"
}
从节点配置:
! Configuration File for keepalived
global_defs {
notification_email {
root@localhost
}
notification_email_from keepalived@localhost
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id k1
vrrp_skip_check_adv_addr
vrrp_iptables
vrrp_gna_interval 0
vrrp_mcast_group4 224.0.45.1
}
vrrp_script ngxchk { #nginx进程检测脚本
script "killall -0 nginx"
interval 1
fall 3
rise 2
weight -5
timeout 1
user root
}
vrrp_script maint {
script "/bin/bash -c '[[ -e /etc/keepalived/down ]]' && exit 1 ||
exit 0"
interval 1
fall 3
rise 2
weight -5
timeout 1
}
vrrp_instance VI_1 {
state BACKUP
interface ens33
virtual_router_id 55
priority 98
advert_int 1
authentication {
auth_type PASS
auth_pass 1212
}
virtual_ipaddress {
192.168.32.200/16 brd 192.168.255.255 dev ens33 label ens33:0
}
track_script { #调用ngxchk脚本
maint
ngxchk
}
notify_master "/etc/keepalived/notify.sh master"
notify_master "/etc/keepalived/notify.sh backup"
notify_fault "/etc/keepalived/notify.sh fault"
}
分别在主从节点上更改发送邮件的脚本
[root@k1 keepalived]# vim notify.sh
#!/bin/bash
#
contact='root@localhost'
notify() {
local mailsubject="$(hostname) to be $1, vip floating"
local mailbody="$(date +'%F %T'): vrrp transition, $(hostnam
e) changed to be $1"
echo "$mailbody" | mail -s "$mailsubject" $contact
}
case $1 in
master)
notify master
;;
backup)
notify backup
systemctl restart nginx #添加重启命令
;;
fault)
notify fault
;;
*)
echo "Usage: $(basename $0) {master|backup|fault}"
exit 1
;;
esac
注意:在这种情况下,当测试时我们关闭nginx服务进程,主节点K1服务器会自动降级,权限更改为95,从节点K2服务器会代替主节点K1,VIP地址从主节点K1转移到从节点K2,但当主节点K1转换状态并发送邮件时,会自动执行重启nginx服务的命令,此时原主节点K1的权限又会恢复到100重新成为主节点,VIP地址又会回到主节点K1。这样一来就会出现K1主节点上的VIP地址丢失,然后又获取的现象
启动K1 K2服务器中的nginx反向代理服务
重启主从节点的keepalived服务
测试:
停止主节点的nginx服务
killall nginx
在K1服务器查看抓包信息
11:28:17.154637 IP 192.168.32.129 > 224.0.45.1: VRRPv2, Advertisement, vrid 55, prio 100, authtype simple, intvl 1s, length 20
11:28:18.155907 IP 192.168.32.129 > 224.0.45.1: VRRPv2, Advertisement, vrid 55, prio 95, authtype simple, intvl 1s, length 20
11:28:18.157329 IP 192.168.32.130 > 224.0.45.1: VRRPv2, Advertisement, vrid 55, prio 98, authtype simple, intvl 1s, length 20
11:28:19.157937 IP 192.168.32.130 > 224.0.45.1: VRRPv2, Advertisement, vrid 55, prio 98, authtype simple, intvl 1s, length 20
11:28:20.161351 IP 192.168.32.130 > 224.0.45.1: VRRPv2, Advertisement, vrid 55, prio 98, authtype simple, intvl 1s, length 20
11:28:21.162631 IP 192.168.32.130 > 224.0.45.1: VRRPv2, Advertisement, vrid 55, prio 98, authtype simple, intvl 1s, length 20
11:28:21.162854 IP 192.168.32.129 > 224.0.45.1: VRRPv2, Advertisement, vrid 55, prio 100, authtype simple, intvl 1s, length 20
发现主节点权限从100变为95,然后从节点98权限变为主节点,但随后,主节点又重新变为100权限,说明nginx进程实现重启
注意:当在双主模式下,不能通过更改脚本来实现nginx进程的重启,因此双主模型中,涉及到多个实例,一个实例出现问题,并不意味着另外一个实例也出现问题,因此通过更改脚本方式实现nginx进程的重启会带来风险,不推荐此种做法