Linux 基于HAProxy+KeepAlived实现
- 1. 介绍
- 1.1 高可用(HA-High Avaialbility)
- 1.2 负载均衡(LB-Load Balance)
- 1.3 HAProxy
- 1.4 KeepAlived
- 2. 后端服务为Nginx
- 2.1 系统拓扑
- 2.2 环境说明
- 2.3 前提条件
- 2.4 详细步骤
- 2.4.1 机器初始化
- 2.4.2 部署Nginx
- 2.4.2.1 安装
- 2.4.2.2 配置
- 2.4.2.3 启动
- 2.4.2.4 验证
- 2.4.3 部署HAProxy
- 2.4.3.1 安装
- 2.4.3.3 启动
- 2.4.3.4 验证
- 2.4.4 第一次测试
- 2.4.4.1 测试LB能力
- 2.4.4.2 测试HA能力
- 2.4.5 部署KeepAlived
- 2.4.5.1 安装
- 2.4.5.2 配置
- 2.4.5.3 启动
- 2.4.6.1 测试VIP是否会漂移
- 2.4.6.2 测试LB+HA能力
- 2.4.7 配置健康检查
- 2.4.8 第三次测试
- 2.4.8.1 测试LB+HA+健康检查能力
- 3. 疑问和思考
- 3.1 keepalive是怎么通信选举出master节点?
- 3.2 keepalive的切换策略是怎么样的?
- 4. 参考文档
高可用(HA-High Avaialbility)
广义上理解,可以认为高可用是系统设计的目标,而容灾是达到高可用这一目标的手段。
高可用HA(High Availability)是分布式系统架构设计中必须考虑的因素之一,它通常是指,通过设计减少系统不能提供服务的时间。
负载均衡(LB-Load Balance)
负载均衡用于解决系统流量分发问题。客户端的流量首先会到达负载均衡服务器,由负载均衡服务器通过一定的调度算法将流量分发到不同的应用服务器上面,同时负载均衡服务器也会对应用服务器做周期性的健康检查,当发现故障节点时便动态的将节点从应用服务器集群中剔除,以此来保证应用的高可用。
1. 介绍
1.1 高可用(HA-High Avaialbility)
广义上理解,可以认为高可用是系统设计的目标,而容灾是达到高可用这一目标的手段。
高可用HA(High Availability)是分布式系统架构设计中必须考虑的因素之一,它通常是指,通过设计减少系统不能提供服务的时间。
1.2 负载均衡(LB-Load Balance)
负载均衡用于解决系统流量分发问题。客户端的流量首先会到达负载均衡服务器,由负载均衡服务器通过一定的调度算法将流量分发到不同的应用服务器上面,同时负载均衡服务器也会对应用服务器做周期性的健康检查,当发现故障节点时便动态的将节点从应用服务器集群中剔除,以此来保证应用的高可用。
1.3 HAProxy
HAProxy提供高可用性、负载均衡以及基于TCP和HTTP应用的代理,支持虚拟主机,它是免费、快速并且可靠的一种解决方案。根据官方数据,其最高极限支持10G的并发。
简单理解HAProxy的作用,就是承担LB负载均衡器的角色。
1.4 KeepAlived
KeepAlived是一个基于VRRP 协议来实现的 LVS 服务高可用方案,可以利用其来解决单点故障。
一个高可用的LB服务会有2台服务器运行Keepalived,一台为主服务(MASTER),一台为备份服务器(BACKUP),但是对外表现为一个虚拟IP,主服务器会发送特定的消息给备份服务器,当备份服务器收不到这个消息的时候,即主服务器宕机的时候, 备份服务器就会接管虚拟IP,继续提供服务,从而保证了高可用性。
2. 后端服务为Nginx
本章先以后台服务为Nginx时为例,说明基于KeepAlived+HAProxy实现的服务高可用方案的设计与详细搭建步骤。
2.1 系统拓扑
本次实验的拓扑如图所示。
说明如下:
-
后端服务器:
- 两台,分别是Backend-1和Backend-2。
- 均部署了Nginx服务,监听80端口。
-
负载均衡服务器:
- 两台,分别是LB-Master和LB-Backup,均部署了HAProxy。
- 每一台HAProxy上,绑定后端两台Nginx服务器,协议为HTTP即L7 LB,轮询算法,将流量负载到Backend-1和Backend-2的80端口。
- 在LB-Master和LB-Backup上,均部署了KeepAlived,配置其VIP为192.168.24。配置LB-Master的权重比LB-Backup高,那么选举时一般情况下会把LB-Master选举为主,所以VIP会优先漂移到LB-Master上。
- KA配置健康检查,定期查询本机HAProxy是否健康,如异常则将KA本身挂起,让出VIP,使其漂移到另外的KA节点上。
-
VIP:
- 一个虚拟IP,由KeepAlived软件来决定LB的哪个机器可以抢到。
-
业务流量:
- 业务对系统的访问地址为VIP,例如此处如果业务流量需要访问Nginx,则访问 http://192.168.0.24:80 即可。
- 正常工作情况下,只有LB-Master或LB-Backup作为复杂均衡器,对外提供服务
2.2 环境说明
本次实验的环境说明如下:
序号 | 类型 | 内网IP | 角色 | 部署内容 | 操作系统 | 内核版本 | CPU | 内存 | 系统盘 |
---|---|---|---|---|---|---|---|---|---|
1 | CVM | 192.168.0.14 | LB-master | Haproxy 1.5.18KeepAlived 1.3.5 | CentOS 7.7 | 3.10.0-1062.18.1.el7.x86_64 | 1c | 2g | 50g |
2 | CVM | 192.168.0.8 | LB-backup | Haproxy 1.5.18KeepAlived 1.3.5 | CentOS 7.7 | 3.10.0-1062.18.1.el7.x86_64 | 1c | 2g | 50g |
3 | CVM | 192.168.0.17 | Backend-1 | Nginx 1.16.1 | CentOS 7.7 | 3.10.0-1062.18.1.el7.x86_64 | 1c | 2g | 50g |
4 | CVM | 192.168.0.4 | Backend-2 | Nginx 1.16.1 | CentOS 7.7 | 3.10.0-1062.18.1.el7.x86_64 | 1c | 2g | 50g |
5 | HAVIP | 192.168.0.24 | VIP | VIP | 无 | 无 | 无 | 无 | 无 |
2.3 前提条件
- 本次实验均在云上环境进行,因此具备yum源,使用其来安装相关软件。如果私有化场景下,未提供yum源,则需要单独去下载各软件的rpm源来安装,或源码编译方式安装。具体安装方式参考网上指引。
- 所有环境资源(CVM、HAVIP等)准备就绪。
2.4 详细步骤
2.4.1 机器初始化
在所有服务器上面进行配置,关闭防火墙和Selinux,设置主机名。
#关闭防火墙
systemctl stop firewalld
#关闭selinux,临时生效
setenforce 0
vim /etc/hosts# 内容如下
192.168.0.14 LB-master
192.168.0.8 LB-backup
192.168.0.17 Backend-1
192.168.0.4 Backend-2
2.4.2 部署Nginx
在后端服务器部署Nginx服务,模拟后端提供服务。
2.4.2.1 安装
# 分别在Backend-1、Backend-2服务器上操作:
ssh Backend-1
yum install -y nginx
2.4.2.2 配置
写入nginx访问页面显示内容,并启动nginx,验证Nginx服务正常
# Backend-1服务器
ssh Backend-1
echo "Hello World server1" > /usr/share/nginx/html/index.html# Backend-2服务器
ssh Backend-2
echo "Hello World server2" > /usr/share/nginx/html/index.html
2.4.2.3 启动
配置完成后,启动Nginx
# Backend-1服务器
ssh Backend-1
systemctl start nginx
systemctl status nginx# Backend-2服务器
ssh Backend-2
systemctl start nginx
systemctl status nginx
2.4.2.4 验证
验证Nginx服务可用性
- 浏览器验证
http://192.168.0.17/
http://192.168.0.4/
- 服务器上curl验证
curl http://192.168.0.17:80
curl http://192.168.0.4:80
2.4.3 部署HAProxy
在负载均衡服务器LB-Master和LB-Backup上部署HAProxy,模拟LB调度器。
2.4.3.1 安装
分别在LB-Master、LB-Backup服务器上操作:
主HAProxy配置
# 主HAProxy
ssh LB-Master
yum -y install haproxy# 备 HAProxy
ssh LB-Backup
yum -y install haproxy
2.4.3.2 配置安装完成后,配置HAProxy,注意标红的关键信息。
cp -rf /etc/haproxy/haproxy.cfg{,.bak}
vim /etc/haproxy/haproxy.cfg# 配置如下,注意标红的关键的信息globallog 127.0.0.1 local2 infopidfile /var/run/haproxy.pidmaxconn 4000 #优先级低user haproxygroup haproxydaemon #以后台形式运行ha-proxynbproc 1 #工作进程数量 cpu内核是几就写几
defaultsmode http #工作模式 http ,tcp 是 4 层,http是 7 层 log globalretries 3 #健康检查。3次连接失败就认为服务器不可用,主要通过后面的check检查option redispatch #服务不可用后重定向到其他健康服务器。maxconn 4000 #优先级中contimeout 5000 #ha服务器与后端服务器连接超时时间,单位毫秒msclitimeout 50000 #客户端超时srvtimeout 50000 #后端服务器超时
listen statsbind *:81 # HAProxy自身使用的端口stats enablestats uri /haproxy #使用浏览器访问 http://172.16.0.10:81/haproxy,可以看到服务器状态 stats auth admin:xxxx #用户认证
frontend webmode httpbind *:80 #监听哪个ip和什么端口option httplog #日志类别 http 日志格式acl html url_reg -i \.html$ #1.访问控制列表名称html。规则要求访问以html结尾的url(可选)use_backend backend-nginx if html #2.如果满足acl html规则,则推送给后端服务器backend-nginxdefault_backend backend-nginx #默认使用的服务器组
backend backend-nginx #名字要与上面的名字必须一样balance roundrobin #负载均衡的方式server http1 192.168.0.17:80 maxconn 2000 weight 1 check inter 1s rise 2 fall 2server http2 192.168.0.4:80 maxconn 2000 weight 1 check inter 1s rise 2 fall 2
备 HAProxy
# 备 HAProxy
cp -rf /etc/haproxy/haproxy.cfg{,.bak}
vim /etc/haproxy/haproxy.cfg# 配置如下,注意标红的关键的信息
globallog 127.0.0.1 local2 infopidfile /var/run/haproxy.pidmaxconn 4000 #优先级低user haproxygroup haproxydaemon #以后台形式运行ha-proxynbproc 1 #工作进程数量 cpu内核是几就写几
defaultsmode http #工作模式 http ,tcp 是 4 层,http是 7 层 log globalretries 3 #健康检查。3次连接失败就认为服务器不可用,主要通过后面的check检查option redispatch #服务不可用后重定向到其他健康服务器。maxconn 4000 #优先级中contimeout 5000 #ha服务器与后端服务器连接超时时间,单位毫秒msclitimeout 50000 #客户端超时srvtimeout 50000 #后端服务器超时
listen statsbind *:81stats enablestats uri /haproxy #使用浏览器访问 http://172.16.0.8:81/haproxy,可以看到服务器状态 stats auth admin:UDC@Tencent2020 #用户认证
frontend webmode httpbind *:80 #监听哪个ip和什么端口option httplog #日志类别 http 日志格式acl html url_reg -i \.html$ #1.访问控制列表名称html。规则要求访问以html结尾的url(可选)use_backend backend-nginx if html #2.如果满足acl html规则,则推送给后端服务器backend-nginxdefault_backend backend-nginx #默认使用的服务器组
backend backend-nginx #名字要与上面的名字必须一样balance roundrobin #负载均衡的方式server http1 192.168.0.17:80 maxconn 2000 weight 1 check inter 1s rise 2 fall 2server http2 192.168.0.4:80 maxconn 2000 weight 1 check inter 1s rise 2 fall 2
2.4.3.3 启动
配置完成后,LB-Master和LB-Backup上分别启动haproxy
主HAProxy
# 主HAProxy
ssh LB-Master
systemctl start haproxy
systemctl status haproxy
备HAProxy
# 备HAProxy
ssh LB-Backup
systemctl start haproxy
systemctl status haproxy
2.4.3.4 验证
浏览器验证
http://192.168.0.14:81/haproxy
http://192.168.0.8:81/haproxy
2.4.4 第一次测试
2.4.4.1 测试LB能力
访问LB-Master的80端口,可以看到,已按预期轮询的转发到Backend-1和Backend-2的80端口上
测试LB-Backup,也是一样的效果
至此,已经解决负载均衡问题。
2.4.4.2 测试HA能力
但高可用问题仍未解决,即假如LB-Master(或LB-Backup,访问任意一台LB节点时)的HAProxy服务挂掉,即使底层的Nginx服务都正常,访问LB地址实际的服务亦不可达。
LB-Master停掉HAProxy,继续访问LB地址,Nginx服务不可达。
测试完后重启HAProxy。
2.4.5 部署KeepAlived
2.4.5.1 安装
在LB-Master和LB-Backup上安装KeepAlived
# 主KA
ssh LB-Master
yum install -y keepalived
# 备KA
ssh LB-Backup
yum install -y keepalived
2.4.5.2 配置
注意:需要参考腾讯云官方的指引来配置KA,否则可能会绑不上VIP。在官方指引给的示例中,注意修改本机IP、对端IP、VIP等配置项,以及后文提及的健康检查相关脚本设置。
主KA配置
# 主KA
ssh LB-Master
cp /etc/keepalived/keepalived.conf{,.bak}
vim /etc/keepalived/keepalived.conf# 注意标红配置
global_defs {# 路由id:当前安装keepalived的节点主机标识符,保证全局唯一router_id keep_01script_user rootenable_script_security
}vrrp_script checkhaproxy {script "/etc/keepalived/do_sth.sh"interval 5
}vrrp_instance VI_1 {# 表示状态是MASTER主机还是备用机BACKUPstate BACKUP# 该实例绑定的网卡名称interface eth0# 保证主备节点一致即可virtual_router_id 51# 权重,master权重一般高于backup,如果有多个,那就是选举,谁的权重高,谁就当选priority 100# 主备之间同步检查时间间隔,单位秒advert_int 2# 认证权限密码,防止非法节点进入authentication {auth_type PASSauth_pass 1111}unicast_src_ip 192.168.0.14 # 设置本机内网IP地址unicast_peer {192.168.0.8 # 对端设备的 IP 地址}# 虚拟出来的ip,可以有多个(vip)virtual_ipaddress {192.168.0.24}track_script {checkhaproxy}
}
备KA配置
# 备KA
LB-Backup
cp /etc/keepalived/keepalived.conf{,.bak}
vim /etc/keepalived/keepalived.conf
global_defs {router_id keep_02script_user rootenable_script_security
}vrrp_script checkhaproxy {script "/etc/keepalived/do_sth.sh"interval 5
}vrrp_instance VI_1 {# 备用机设置为BACKUPstate BACKUPinterface eth0virtual_router_id 51# 权重低于MASTERpriority 80advert_int 2authentication {auth_type PASSauth_pass 1111}unicast_src_ip 192.168.0.8 # 设置本机内网IP地址unicast_peer {192.168.0.14 # 对端设备的 IP 地址}virtual_ipaddress {# 注意:主备两台的vip都是一样的,绑定到同一个vip192.168.0.24}
}
2.4.5.3 启动
启动KA前,确认主备服务器上的IP地址,与启动后进行对比。
# LB-Master
ip a
# LB-Backup
ip a
LB-Master和LB-Backup上,分别启动KA
ssh LB-Master
systemctl start keepalived
systemctl status keepalived
ssh LB-Backup
systemctl start keepalived
systemctl status keepalived
启动KA后,查看VIP的绑定。由于优先度设置关系,可以看到绑定VIP(192.168.0.24)的是LB-Master服务器(192.168.0.14)
并创建了相关的路由表,因此master节点能够正常响应流量
Backup服务器没有绑定vip
因此访问vip是,相关的流量会转发到master节点,slave节点处于standby状态。
##2.4.6 第二次测试
2.4.6.1 测试VIP是否会漂移
将LB-Master的KeepAlived服务停止,验证VIP是否能正常漂移。
# 停止KA前,先查看各自的ip
# LB-Master节点
ip a
# LB-Backup节点
ip a
# LB-Master节点
systemctl stop keepalived
# 停止KA后,再查看各自的ip
# LB-Master节点
ip a
# LB-Backup节点
ip a
可以发现VIP已经从LB-Master漂移到了LB-Backup上。
之后重启LB-Master的KeepAlived服务,但是VIP是不会漂移到LB-Master上,还在LB-Backup上。
重启LB-Backup的KeepAlived服务,此时VIP会漂移到LB-Master上
2.4.6.2 测试LB+HA能力
此时,由于KA的加入,加上之前的HAProxy,整个架构已经具备了LB+HA的能力。
此时系统对外的高可用入口为VIP。通过VIP来访问Nginx服务(HTTP协议,80端口),看是否可以达到高可用+负载均衡的目标。
2.4.7 配置健康检查
上面的测试中,已经验证了同一时刻中单个KA的服务的不可用,另外一个KA的服务可以将VIP抢到对应所在的服务器,确保整个系统的高可用。但另外还有一个场景是,如果HAProxy宕机了,那么访问VIP就会有问题,因为HAProxy已经不能转发到后端服务上去了。
例如此处将LB-Master的HAProxy停止,但由于KA服务是正常的,VIP仍在LB-Master上,所以访问不到Nginx服务。
要解决该问题的话,需要考虑实现一个健康检查的脚本,让KeppAlived定期去检查本机HAProxy的状态,或者检查本机的HAProxy功能可用性(例如通过本地的HAProxy访问后端服务是否正常))。如果本机HAProxy已经挂掉或功能不可用,那么可以设置退出本机的KeepAlived,从而让对端的KeepAlived(LB-Backup)来承接起Master的角色。
例如在KeepAlived的配置文件中,定义一个do_sth.sh脚本,每隔5秒检查一次。如果发现haproxy访问不通,则停止本地KeepAlived服务。
/etc/keepalived/do_sth.sh脚本内容:
#!/bin/bash
# 检查通过本地的HAProxy访问后端服务是否正常
if ! /usr/bin/curl -I http://localhost:80 >/dev/null 2>&1; then
# 或者检查HAProxy的服务状态
# if ! systemctl status haproxy > /dev/null 2>&1; thensystemctl stop keepalived
fi
chmod +x /etc/keepalived/do_sth.sh
测试停止LB-Master上的HAProxy,查看LB-Master的KeepAlived服务是否会停止
此时验证确认配置无误。
2.4.8 第三次测试
2.4.8.1 测试LB+HA+健康检查能力
在一台客户端机器(如192.168.0.16)上不断的请求VIP上80 HTTP服务(curl http://192.168.0.24:80
),两秒超时。
watch -e "curl -m 2 http://192.168.0.24:80"
此时,在LB-Master上,停止HAProxy。会发现有一定时间的宕机窗口,过一小会再测,等VIP漂移到LB-Backup上后,服务访问就能恢复。
3. 疑问和思考
3.1 keepalive是怎么通信选举出master节点?
-
VRRP(Virtual Router Redundancy Protocol)心跳检测:
Keepalived的核心功能之一是实现了VRRP协议,多个节点之间形成一个虚拟路由器组,其中一个节点作为主节点(MASTER),其余节点为备份节点(BACKUP)。主节点会定期发送VRRP通告(heartbeat)给所有组内的节点,以证明自己仍在正常工作。备份节点监听这些心跳信息。如果在预定的时间内,备份节点没有接收到主节点的心跳,则认为主节点已失效,并按照VRRP优先级规则选举新的主节点。这种机制可以确保在主节点发生故障时,服务能够快速切换到备份节点,从而维持服务的高可用性。 -
自定义健康检查脚本:
Keepalived支持用户自定义健康检查脚本(vrrp_script),通过执行这些脚本来检测特定服务或者资源的状态。例如,可以编写一个脚本来ping某个IP地址、检查TCP端口是否打开,或者执行HTTP/HTTPS请求来测试Web服务的响应状态。一旦健康检查脚本返回非成功状态(如非零退出码),Keepalived可以根据配置减小该节点在VRRP组中的优先级,使得VIP(Virtual IP Address)转交给其他健康的节点。
vrrp_script chk_http_port {script "/usr/local/bin/check_http.sh" # 自定义脚本路径interval 2 # 检查间隔(单位:秒)weight 2 # 成功时增加的权重值fall 3 # 连续几次失败认为节点失效rise 2 # 连续几次成功认为节点恢复
}vrrp_instance VI_1 {...track_script {chk_http_port}...
}
3.2 keepalive的切换策略是怎么样的?
在Keepalived集群中,其实并没有严格意义上的主、备节点,虽然可以在Keepalived配置文件中设置“state”选项为“MASTER”状态,但是这并不意味着此节点一直就是Master角色。控制节点角色的是Keepalived配置文件中的“priority”值,但并它并不控制所有节点的角色,另一个能改变节点角色的是在vrrp_script模块中设置的“weight”值,这两个选项对应的都是一个整数值,其中“weight”值可以是个负整数,一个节点在集群中的角色就是通过这两个值的大小决定的。一个节点的权重公式如下
优先级 = p r i o r i t y + w e i g h t 优先级 = priority + weight 优先级=priority+weight
切换master节点的原则是: 优先级的值越大的节点,切换为master,其他节点降级为backup节点。
其中weight可以是正值也可以是负值,两者不同时,相关的计算有差异
-
weight值为正数时
-
如果检测成功,weight保持不变,优先级=priority + weight
-
如果检测失败,weight=0, 优先级 = priority
-
Master节点“vrrp_script”脚本检测失败时,如果Master节点“priority”值小于Backup节点“weight值与”priority“值之和,将发生主、备切换
-
Master节点“vrrp_script”脚本检测成功时,如果Master节点“weight”值与“priority”值之和大于Backup节点“weight”值与“priority”值之和,主节点依然为主节点,不发生切换。
-
-
weight值为负数时
-
如果检测成功,weight=0, 优先级 = priority
-
如果检测失败,weight保持不变(负值),优先级=priority - abs(weight)
-
Master节点“vrrp_script”脚本检测失败时,如果Master节点“priority”值与“weight”值之差小于Backup节点“priority”值,将发生主、备切换。
-
Master节点“vrrp_script”脚本检测成功时,如果Master节点“priority”值大于Backup节点“priority”值时,主节点依然为主节点,不发生切换。
-
下面列举一个实例来具体说明。
假定有A和B两节点组成的Keepalived集群,在A节点keepalived.conf文件中,设置“priority”值为100,而在B节点keepalived.conf文件中,设置“priority”值为80,并且A、B两个节点都使用了“vrrp_script”模块来监控mysql服务,同时都设置“weight”值为10,那么将会发生如下情况。
在两节点都启动Keepalived服务后,正常情况是A节点将成为集群中的Master节点,而B自动成为Backup节点,此时将A节点的mysql服务关闭,通过查看日志发现,并没有出现B节点接管A节点的日志,B节点仍然处于Backup状态,而A节点依旧是Master状态,切换失败,在这种情况下整个HA集群将失去意义。
再来分析一下刚才实例,由于A、B两个节点设置的“weight”值都为10,因此符合选举策略的第一种,在A节点停止Mysql服务后,A节点的脚本检测将失败,此时A节点的权值将保持为A节点上设置的“priority”值,即为100,而B节点的权值将变为“weight”值与“priority”值之和,也就是90(10+80),这样就出现了A节点权值仍然大于B节点权值的情况,因此不会发生主、备切换。
因此 对于“weight”值的设置很关键: 有一个简单的标准,即“weight”值的绝对值要大于Master和Backup节点“priority”值之差。
对于上面A、B两个节点的例子,只要设置“weight”值大于20即可保证集群正常运行和切换。由此可见,对于“weight值的设置,要非常谨慎,如果设置不好,将导致集群角色选举失败,使集群陷于瘫痪状态。
4. 参考文档
暂无