本文主要介绍高可用中的解决静态网关单点风险,采用技术keepalived。负载均衡采用lvs,haproxy技术,可点击链接参考作者相应文章。
一、keepalived介绍
Keepalived是一个轻量级的高可用解决方案,它是一个免费开源的,用C编写的类似于Layer3、Layer4和Layer7(或称为第3层、第4层和第7层)交换机制的软件。Keepalived主要提供负载均衡和高可用服务,其核心功能是通过VRRP(Virtual Router Redundancy Protocol,虚拟路由冗余协议)实现多台机器之间的故障转移服务。
1.1 Keepalived的主要特点
- 自动完成,无需人工干涉:Keepalived能够自动检测服务器的状态,并在检测到故障时自动将故障服务器从系统中剔除,同时启用其他服务器接替其工作。当服务器恢复正常后,Keepalived会自动将其重新加入到服务器群中。
- 高可用和负载均衡:通过VRRP协议,Keepalived能够在主服务器出现故障时,将流量自动切换到备份服务器,从而保证服务的高可用性。同时,它也可以与LVS(Linux Virtual Server)等负载均衡软件结合使用,提供更为强大的负载均衡能力。
- 多层次检测机制:Keepalived支持在网络层(Layer3)、传输层(Layer4)和应用层(Layer7)对服务器进行健康检查。这包括通过ICMP数据包检测IP地址的有效性、通过TCP端口状态检测服务是否正常运行,以及通过HTTP GET请求检查特定URL的响应情况。
1. 2 Keepalived的工作原理
- VRRP协议:Keepalived通过VRRP协议实现高可用。VRRP协议是一种容错的主备模式协议,它能够在主路由器出现故障时,由备份路由器接替其工作,从而保证网络的连续性和可靠性。
- 心跳机制:在Keepalived的主备模式下,主服务器会定期向备份服务器发送心跳信息,以表明其工作状态。如果备份服务器在一定时间内没有收到主服务器的心跳信息,就会认为主服务器已经出现故障,并接管其工作。
- 健康检查:Keepalived通过多层次的健康检查机制来确保服务器的可用性。这些检查机制包括ICMP数据包检测、TCP端口状态检测和HTTP GET请求检查等。如果检测到服务器出现故障,Keepalived就会将其从服务器群中剔除,并启用其他服务器接替其工作。
二、 keepalived部署配置
2.1 安装keepalived
# yum install keepalived
采用本地源安装即可
2.2 配置文件介绍
配置文件:/etc/keepalived/keepalived.conf
# 全局配置
global_defs {
# 邮件通知信息
notification_email {
# 定义收件人,keepalived发生故障切换时邮件发送的目标邮箱,可以按行区分写多个
acassen@firewall.loc
}
# 定义发件人
notification_email_from Alexandre.Cassen@firewall.loc
# SMTP服务器地址
smtp_server 192.168.200.1
smtp_connect_timeout 30
# 路由器标识,一般不用改,也可以写成每个主机自己的主机名
router_id LVS_DEVEL
#对所有通告报文都检查,会比较消耗性能。启用此配置后,如果收到的通告报文和上一个报文是同一个路由器,则跳过检查,默认值为全检查
vrrp_skip_check_adv_addr
#严格遵循vrrp协议。启用此项后以下状况将无法启动服务:无VIP地址;配置了单播邻居;在VRRP版本2中有IPv6地址
vrrp_strict
#报文发送延迟,0表示不延迟
vrrp_garp_interval 0
#消息发送延迟
vrrp_gna_interval 0
# VRRP的ipv4和ipv6的广播地址,配置了VIP的网卡向这个地址广播来宣告自己的配置信息,下面是默认值
vrrp_mcast_group4 224.0.0.18
vrrp_mcast_group6 ff02::12
}
# 定义用于实例执行的脚本内容,比如可以在线降低优先级,用于强制切换
vrrp_script SCRIPT_NAME {
}
# 一个vrrp_instance就是定义一个虚拟路由器的,实例名称
vrrp_instance VI_1 {
# 定义初始状态,可以是MASTER或者BACKUP
state MASTER
# 工作接口,通告选举使用哪个接口进行
interface ens33
# 虚拟路由ID,如果是一组虚拟路由就定义一个ID,如果是多组就要定义多个,而且这个虚拟
# ID还是虚拟MAC最后一段地址的信息,取值范围0-255
virtual_router_id 51
# 使用哪个虚拟MAC地址
use_vmac XX:XX:XX:XX:XX
# 监控本机上的哪个网卡,网卡一旦故障则需要把VIP转移出去
track_interface {
eth0
ens33
}
# 如果你上面定义了MASTER,这里的优先级就需要定义的比其他的高
priority 100
# 通告频率,单位为秒
advert_int 1
# 通信认证机制,这里是明文认证还有一种是加密认证
authentication {
auth_type PASS
auth_pass 1111
}
# 设置虚拟VIP地址,一般就设置一个,在LVS中这个就是为LVS主机设置VIP的,这样你就不用自己手动设置了
virtual_ipaddress {
# IP/掩码 dev 配置在哪个网卡
192.168.200.16/24 dev eth1
# IP/掩码 dev 配置在哪个网卡的哪个别名上
192.168.200.17/24 dev label eth1:1
}
# 虚拟路由,在需要的情况下可以设置lvs主机 数据包在哪个网卡进来从哪个网卡出去
virtual_routes {
192.168.110.0/24 dev eth2
}
# 工作模式,nopreempt表示工作在非抢占模式,默认是抢占模式 preempt
nopreempt|preempt
# 如果是抢占默认则可以设置等多久再抢占,默认5分钟
preempt delay 300
# 追踪脚本,通常用于去执行上面的vrrp_script定义的脚本内容
track_script {
}
# 三个指令,如果主机状态变成Master|Backup|Fault之后会去执行的通知脚本,脚本要自己写
notify_master ""
notify_backup ""
notify_fault ""
}
# 定义LVS集群服务,可以是IP+PORT;也可以是fwmark 数字,也就是防火墙规则
# 所以通过这里就可以看出来keepalive天生就是为ipvs而设计的
virtual_server 10.10.10.2 1358 {
delay_loop 6
# 算法
lb_algo rr|wrr|lc|wlc|lblc|sh|dh
# LVS的模式
lb_kind NAT|DR|TUN
# 子网掩码,这个掩码是VIP的掩码
nat_mask 255.255.255.0
# 持久连接超时时间
persistence_timeout 50
# 定义协议
protocol TCP
# 如果后端应用服务器都不可用,就会定向到那个服务器上
sorry_server 192.168.200.200 1358
# 后端应用服务器 IP PORT
real_server 192.168.200.2 1358 {
# 权重
weight 1
# MSIC_CHECK|SMTP_CHEKC|TCP_CHECK|SSL_GET|HTTP_GET这些都是
# 针对应用服务器做健康检查的方法
MISC_CHECK {}
# 用于检查SMTP服务器的
SMTP_CHEKC {}
# 如果应用服务器不是WEB服务器,就用TCP_CHECK检查
TCP_CHECK {
# 向哪一个端口检查,如果不指定默认使用上面定义的端口
connect_port <PORT>
# 向哪一个IP检测,如果不指定默认使用上面定义的IP地址
bindto <IP>
# 连接超时时间
connect_timeout 3
}
# 如果对方是HTTPS服务器就用SSL_GET方法去检查,里面配置的内容和HTTP_GET一样
SSL_GET {}
# 应用服务器UP或者DOWN,就执行那个脚本
notify_up "路径"
notify_down "/PATH/SCRIPTS.sh 参数"
# 使用HTTP_GET方法去检查
HTTP_GET {
# 检测URL
url {
# 具体检测哪一个URL
path /testurl/test.jsp
# 检测内容的哈希值
digest 640205b7b0fc66c1ea91c463fac6334d
# 除了检测哈希值还可以检测状态码,比如HTTP的200 表示正常,两种方法二选一即可
status_code 200
}
url {
path /testurl2/test.jsp
digest 640205b7b0fc66c1ea91c463fac6334d
}
url {
path /testurl3/test.jsp
digest 640205b7b0fc66c1ea91c463fac6334d
}
# 向哪一个端口检查,如果不指定默认使用上面定义的端口
connect_port <PORT>
# 向哪一个IP检测,如果不指定默认使用上面定义的IP地址
bindto <IP>
# 连接超时时间
connect_timeout 3
# 尝试次数
nb_get_retry 3
# 每次尝试之间间隔几秒
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
}
}
}
三、keepalived配置示例
3.1 主从设置
仅展示关键代码
K1:主
# vim /etc/keepalived/keepalived.conf
global_defs {
#vrrp_strict
vrrp_mcast_group4 224.0.0.18
......
}
vrrp_instance VI_1 {
state MASTER //设定为主
virtual_router_id 20
priority 100 //主设备优先级一定要比从设备要大
......
}
K2:从
global_defs {
#vrrp_strict
vrrp_mcast_group4 224.0.0.18
......
}
vrrp_instance VI_1 {
state BACKUP //设定为从
virtual_router_id 20 //与主设备的ID要一致
priority 80
......
}
3.2设置日志功能
# vim /etc/sysconfig/keepalived
KEEPALIVED_OPTIONS="-D -S 6"
#vim /etc/rsyslog.conf
local6.* /var/log/keepalived.log
#systemctl restart keepalived.service rsyslog.service
3.3 实现独立子配置文件
当生产环境复杂时, /etc/keepalived/keepalived.conf 文件中内容过多,不易管理 将不同集群的配置,比如:不同集群的VIP配置放在独立的子配置文件中利用include 指令可以实现包含子配置文件
# mkdir /etc/keepalived/conf.d
# mkdir /etc/keepalived/conf.d
global_defs {
......
}
include /etc/keepalived/conf.d/*.conf
#vim /etc/keepalived/conf.d/router.conf
vrrp_instance VI_1 {
......
}
3.4抢占模式和非抢占模式设置
默认为抢占模式preempt,即当高优先级的主机恢复在线后,会抢占低先级的主机的master角色,这样会使vip在KA主机中来回漂移,造成网络抖动, 建议设置为非抢占模式 nopreempt ,即高优先级主机恢复后,并不会抢占低优先级主机的master角色 非抢占模块下,如果原主机down机, VIP迁移至的新主机, 后续也发生down时,仍会将VIP迁移回原主机。
要关闭 VIP抢占,必须将各 keepalived 服务器state配置为BACKUP
vrrp_instance VI_1 {
......
nopreempt #非抢占模式
preempt_delay 10s #抢占延迟10s
}
3.5VIP单播配置
默认keepalived主机之间利用多播相互通告消息,会造成网络拥塞,可以替换成单播,减少网络流量
#启用 vrrp_strict 时,不能启用单播,否则服务无法启动
vrrp_instance VI_1 {
......
virtual_ipaddress {
172.25.250.100/24 dev eth0 label eth0:1
}
unicast_src_ip 172.25.250.20 //本机IP
unicast_peer {
172.25.250.10 //指向对方主机IP
}
}
3.6通知脚本
当keepalived的状态变化时,可以自动触发脚本的执行,比如:发邮件通知用户 默认以用户keepalived_script身份执行脚本 如果此用户不存在,以root执行脚本可以用下面指令指定脚本执行用户的身份
notify_master <STRING>|<QUOTED-STRING>
当前节点成为主节点时触发的脚本notify_backup <STRING>|<QUOTED-STRING>
当前节点转为备节点时触发的脚本notify_fault <STRING>|<QUOTED-STRING>
当前节点转为“失败”状态时触发的脚本notify <STRING>|<QUOTED-STRING>
通用格式的通知触发机制,一个脚本可完成以上三种状态的转换时的通知notify_stop <STRING>|<QUOTED-STRING>
当停止VRRP时触发的脚本
# vim /etc/keepalived/keepalived.conf
vrrp_instance VI_1 {
......
notify_master "/etc/keepalived/mail.sh master"
notify_backup "/etc/keepalived/mail.sh backup"
notify_fault "/etc/keepalived/mail.sh fault"
}
创建通知脚本
# vim /etc/keepalived/mail.sh
#!/bin/bash
mail_dest='123456789@qq.com'
mail_send()
{
mail_subj="$HOSTNAME to be $1 vip 转移"
mail_mess="`date +%F\ %T`: vrrp 转移,$HOSTNAME 变为 $1"
echo "$mail_mess" | mail -s "$mail_subj" $mail_dest
}
case $1 in
master)
mail_send master
;;
backup)
mail_send backup
;;
fault)
mail_send fault
;;
*)
exit 1
;;
esac
# chmod +x /etc/keepalived/mail.sh
安装邮件发送工具
# dnf install mailx -y
QQ邮箱配置
# vim /etc/mail.rc
#######mail set##########
set from=123456789@qq.com
set smtp=smtp.qq.com
set smtp-auth-user=123456789@qq.com
set smtp-auth-password=isjatjwmcxtxbefj //该值为QQ邮箱的授权码
set smtp-auth=login
set ssl-verify=ignore
3.7Keepalived 多主架构
master/slave的单主架构,同一时间只有一个Keepalived对外提供服务,此主机繁忙,而另一台主机却 很空闲,利用率低下,可以使用master/master的双主架构,解决此问题。
#第一个节点ka1配置:
Vrrp instance 1:MASTER,优先级100
Vrrp instance 2:BACKUP,优先级80
Vrrp instance 3:BACKUP,优先级60
#第二个节点ka2配置:
Vrrp instance 1:BACKUP,优先级60
Vrrp instance 2:MASTER,优先级100
Vrrp instance 3:BACKUP,优先级80
#第三个节点ka3配置:
Vrrp instance 1:BACKUP,优先级80
Vrrp instance 2:BACKUP,优先级60
Vrrp instance 3:MASTER,优先级100
四、keepalived+LVS实现高可用,负载均衡
1.RS1和RS2上做http服务,在lo网卡上配置vip,关闭ARP响应,关闭防火墙,SE
部分配置:
永久更改ARP响应:可在主配置文件中添加/etc/sysctl.conf 或者子配置文件/etc/sysctl.d/xx.conf
可先用sysctl -a | grep arp 查看服务,然后直接复制更改,防止手残敲错
添加内容为: net.ipv4.conf.all.arp_announce=2 net.ipv4.conf.all.arp_ignore=1 net.ipv4.conf.lo.arp_announce=2 net.ipv4.conf.lo.arp_ignore=1
2.K1和K2上做keepalived和安装ipvsadm,其中LVS的配置做在keepalived配置文件中
#vim /etc/keepalived/keepalived.conf
virtual_server 172.25.250.100 80 {
delay_loop 6
lb_algo wrr
lb_kind DR
protocol TCP
real_server 172.25.250.110 80 {
weight 1
HTTP_GET {
url {
path /
status_code 200
}
connect_timeout 3
nb_get_retry 2
delay_before_retry 2
}
}
real_server 172.25.250.120 80 {
weight 2
HTTP_GET {
url {
path /
status_code 200
}
connect_timeout 3
nb_get_retry 2
delay_before_retry 2
}
}
}
上述代码模块介绍:
virtual_server IP port {.......} #定义虚拟主机IP地址及其端口
{.....}中可写参数:
delay_loop <INT> #检查后端服务器的时间间隔
lb_algo rr|wrr|lc|wlc|lblc|sh|dh #定义调度方法
lb_kind NAT|DR|TUN #集群的类型,注意要大写
persistence_timeout <INT> #持久连接时长
protocol TCP|UDP|SCTP #指定服务协议,一般为TCP
sorry_server <IPADDR> <PORT> #所有RS故障时,备用服务器地址
real_server <IPADDR> <PORT> { #RS的IP和PORT
weight <INT> #RS权重
notify_up <STRING>|<QUOTED-STRING> #RS上线通知脚本
notify_down <STRING>|<QUOTED-STRING> #RS下线通知脚本
HTTP_GET|SSL_GET|TCP_CHECK|SMTP_CHECK|MISC_CHECK { ... } #定义当前主机健康状态检测方法
}#注意:括号必须分行写,两个括号写在同一行,如: }} 会出错
virtual_server fwmark int {.......} #ipvs的防火墙打标,实现基于防火墙的负载均衡集群
virtual_server group string {.......} #使用虚拟服务器组HTTP_GET|SSL_GET {
url {
path <URL_PATH> #定义要监控的URL
status_code <INT> #判断上述检测机制为健康状态的响应码,一般为 200
}
connect_timeout <INTEGER> #客户端请求的超时时长, 相当于haproxy的timeout server
nb_get_retry <INT> #重试次数
delay_before_retry <INT> #重试之前的延迟时长
connect_ip <IP ADDRESS> #向当前RS哪个IP地址发起健康状态检测请求
connect_port <PORT> #向当前RS的哪个PORT发起健康状态检测请求
bindto <IP ADDRESS> #向当前RS发出健康状态检测请求时使用的源地址
bind_port <PORT> #向当前RS发出健康状态检测请求时使用的源端口
}
五、keepalived+haproxy实现高可用,负载均衡
keepalived利用 VRRP Script 技术,可以调用外部的辅助脚本进行资源监控,并根据监控的结果实现优先动态调整,从而实现其它应用的高可用性功能。
定义脚本
vrrp_script:自定义资源监控脚本,vrrp实例根据脚本返回值,公共定义,可被多个实例调用,定
义在vrrp实例之外的独立配置块,一般放在global_defs设置块之后。
通常此脚本用于监控指定应用的状态。一旦发现应用的状态异常,则触发对MASTER节点的权重减至
低于SLAVE节点,从而实现 VIP 切换到 SLAVE 节点
vrrp_script <SCRIPT_NAME> {
script <STRING>|<QUOTED-STRING> #shell命令或脚本路径,此脚本返回值为非0时,会触发下面OPTIONS执行
OPTIONS
interval <INTEGER> #间隔时间,单位为秒,默认1秒
timeout <INTEGER> #超时时间
weight <INTEGER:-254~254> #默认为0,如果设置此值为负数,当上面脚本返回值为非0时会将此值与本节点权重相加可以降低本节点权重,即表示fall.
如果是正数,当脚本返回值为0,会将此值与本节点权重相加可以提高本节点权重,即表示 rise.通常使用负值
fall <INTEGER> #执行脚本连续几次都失败,则转换为失败,建议设为2以上
rise <INTEGER> #执行脚本连续几次都成功,把服务器从失败标记为成功
user USERNAME [GROUPNAME] #执行监测脚本的用户或组
init_fail #设置默认标记为失败状态,监测成功之后再转换为成功状态
}
调用脚本
track_script:调用vrrp_script定义的脚本去监控资源,定义在VRRP实例之内,调用事先定义的vrrp_script
track_script {
SCRIPT_NAME_1
SCRIPT_NAME_2
}
具体实现:
1.RS1和RS2上做http服务,关闭防火墙,SE
2.K1和K2上做keepalived和haproxy,在K1和KS上的haproxy配置文件中都做好策略,并设置内核参数
# vim /etc/sysctl.conf
net.ipv4.ip_nonlocal_bind = 1 该参数的作用是让主机即使没有VIP也能启动haproxy,即当VIP在K1上时,K2上没有VIP就无法启动haproxy服务,设置该参数即可正常启动。
k1上编写检测脚本,并赋予可执行权限,再在keepalived配置文件中添加高可用策略
#在两个ka1和ka2先实现haproxy的配置
# vim /etc/haproxy/haproxy.cfg
listen webserver
bind 172.25.250.100:80
server web1 172.25.250.110:80 check
server web2 172.25.250.120:80 check
#在ka1中编写检测脚本
# vim /etc/keepalived/test.sh
#!/bin/bash
killall -0 haproxy
# chmod +X /etc/keepalived/test.sh
#在ka1中配置keepalived
#cat /etc/keepalived/keepalived.conf
vrrp_script check_test {
script "/etc/keepalived/test.sh"
interval 1
weight -30
fall 2
rise 2
timeout 2
}
正常情况下由RS1提供harpoxy服务当,RS1上的haproxy服务断开后由RS2上的haproxy服务顶替
注:1.如果是写在子配置文件中的,脚本模块和路由模块要写在一个子配置文件中!
2.编写脚本时,记得查看脚本返回值和预期是否符合,提前测试一下再写进配置文件。例如这里的killall -0 haproxy 我的主机没有killall命令,导致脚本一直返回非0值。