HAProxy是一种免费、快速、可靠的反向代理,为基于TCP和HTTP的应用程序提供高可用性、负载平衡和代理,它非常适合应用在高并发大流量的网站上。这些年来,HAProxy已成为事实上的标准开源负载均衡,目前HAProxy已与大多数主流Linux发行版一起提供,很多云平台也默认集成了HAProxy。
LVS、Nginx、HAProxy是常用的三款负载均衡,网上有很多三种负载均衡详细的对比文章,下面一句话总结LVS、Nginx、HAProxy的优缺点:
通常我们把Keepalived和HAProxy一起使用,来实现Web服务器的高可用性和负载平衡。Keepalived是一个用C编写的路由软件,它使用虚拟路由冗余协议(VRRP)和健康检查机制的组合来确定服务器的状态,并在需要时触发故障转移。VRRP确保只有一个服务器在任何给定时间内 actively 响应请求,而健康检查则监视服务器的健康状态,并在主服务器失败时触发选举过程。
关闭SELinux,尽管SELinux可以增强生产服务器的安全性,它是为每个软件配置控制权限,使用它的前提是必须详细了解每个需要部署的软件并为它配置。很多国内云服务器默认安装的Linux环境也是禁用SELinux,否则在安装部署时会有很多问题。
# 首先临时关闭SELinux
setenforce 0
# 修改配置文件,永久关闭SELinux
vi /etc/sysconfig/selinux
# 设置
SELINUX=disabled
VIP(虚拟IP)有两种实现方式:一种是直接配置Linux服务器网络,还有一种是使用Keepalived,我们这里直接使用Keepalived的方式来实现。在实际部署中发现,如果多网卡时,不同的虚拟IP绑定在同一网卡,在虚拟IP切换时会发生无法访问的情况,所以尽量将虚拟IP设置为统一网段绑定在同一网卡。
yum list keepalived
yum install -y keepalived
# 安装编译源码所需依赖
yum -y install gcc openssl-devel libnl3-devel ipset-devel iptables-devel libnfnetlink-devel net-snmp-devel glib2-devel
# 下载源码包
wget https://www.keepalived.org/software/keepalived-2.2.8.tar.gz
# 解压源码包
tar zxvf keepalived-2.2.8.tar.gz
# 编译源码包
cd keepalived-2.2.8
./configure --prefix=/
make && make install
# 从解压的源码包中将开机启动文件复制到/etc/rc.d/init.d/
cp /opt/software/keepalived-2.2.8/keepalived/etc/init.d/keepalived /etc/rc.d/init.d/
# 给keepalived赋权限/etc/init.d/是/etc/rc.d/init.d/的软链接
chmod +x /etc/init.d/keepalived
# 设置开机启动
echo "/etc/init.d/keepalived start" >> /etc/rc.local
在生产环境中,高可用服务的状态变化需要及时通知系统管理员,以保障管理员及时处理服务故障,使服务正常运行。Keepalived提供notification_email、smtp_server等邮件发送配置,但是它不支持SMTP身份验证,也不支持SMTP的TLS,它是使用HELO且不使用身份验证的RFC821实现,所以Keepalived没有配置邮件服务器用户名、密码的方法,导致无法使用外部邮箱服务器,所以,这里选择网上大多数方法,编写脚本,当Keepalived状态切换时,调用Linux系统的mailx(mailx是一个命令行邮件客户端)进行邮件发送。
[root@localhost /]# which mailx
/usr/bin/which: no mailx in (/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/usr/local/java/bin:/root/bin)
yum install mailx -y
vi /etc/mail.rc
# 一下内容加在mail.rc文件底部
set [email protected]
set smtp=smtp.163.com
set [email protected]
set smtp-auth-password=密码
set smtp-auth=login
set ssl-verify=ignore
echo "虚拟IP发生浮动,请及时处理。" | mail -s "Keepalived告警邮件" [email protected]
vi /etc/keepalived/keepalived_notify.sh
keepalived_notify.sh内容如下
# 填写一下内容
#!/bin/bash
mailto=收件人邮箱1,收件人邮箱2
notify() {
mailsubject="【Keepalived状态切换告警邮件】$(hostname) 状态切换为 $1"
mailbody="$(date +'%F %T'): Keepalived状态发生切换, $(hostname) 状态切换为 $1,请检查服务器运行状态。"
echo "$mailbody" | mail -s "$mailsubject" $mailto
}
case $1 in
master)
notify master
;;
backup)
notify backup
;;
fault)
notify fault
;;
*)
echo "Usage: $(basename $0) {master|backup|fault}"
exit 1
;;
esac
keepalived_notify.sh赋可执行权限
chmod +x /etc/keepalived/keepalived_notify.sh
# 测试脚本是否可以发送
bash /etc/keepalived/keepalived_notify.sh master
vi /etc/hostname
#修改hostname,注意格式
localhost.ServerA
#立即生效
hostname $(cat /etc/hostname)
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
echo "net.ipv4.ip_nonlocal_bind = 1" >> /etc/sysctl.conf
sysctl -p
# 双网卡,网卡enp6s0f1
firewall-cmd --direct --permanent --add-rule ipv4 filter INPUT 0 --in-interface enp6s0f1 --destination 224.0.0.18 --protocol vrrp -j ACCEPT
firewall-cmd --direct --permanent --add-rule ipv4 filter OUTPUT 0 --out-interface enp6s0f1 --destination 224.0.0.18 --protocol vrrp -j ACCEPT
# 双网卡,网卡enp6s0f0
firewall-cmd --direct --permanent --add-rule ipv4 filter INPUT 0 --in-interface enp6s0f0 --destination 224.0.0.18 --protocol vrrp -j ACCEPT
firewall-cmd --direct --permanent --add-rule ipv4 filter OUTPUT 0 --out-interface enp6s0f0 --destination 224.0.0.18 --protocol vrrp -j ACCEPT
firewall-cmd --reload
! Configuration File for keepalived
global_defs {
router_id NODE_MASTER #名称唯一
vrrp_skip_check_adv_addr # 默认是不跳过检查。检查收到的VRRP通告中的所有地址可能会比较耗时,设置此命令的意思是,如果通告与接收的上一个通告来自相同的master路由器,则不执行检查(跳过检查)。
#vrrp_strict # 严格遵守VRRP协议
#vrrp_garp_interval 0 #在一个接口发送的两个免费ARP之间的延迟。可以精确到毫秒级。默认是0.
#vrrp_gna_interval 0 #在一个网卡上每组na消息之间的延迟时间,默认为0
script_user root
enable_script_security
max_auto_priority 1
}
vrrp_instance VI_1 {
state MASTER # 设置初始状态均主
interface enp6s0f1 enp6s0f0 # 设置绑定虚拟IP的网卡,多个网卡可以在后面添加
virtual_router_id 51 # 集群的virtual_router_id值,主备一致
priority 100 # 路由权重
advert_int 1 #检查间隔,默认1秒
notify_master "/etc/keepalived/keepalived_notify.sh master"
notify_backup "/etc/keepalived/keepalived_notify.sh backup"
notify_fault "/etc/keepalived/keepalived_notify.sh fault"
authentication {
auth_type PASS #认证方式
auth_pass 11111111 #认证密码(密码只识别前8位)
}
virtual_ipaddress {
内网虚拟ip dev enp6s0f1 # 内网虚拟ip,后面可以加网卡名称绑定不同网卡
公网虚拟ip dev enp6s0f0 # 公网虚拟ip,后面可以加网卡名称绑定不同网卡
}
}
备节点服务器192.168.1.195的keepalived.conf配置
! Configuration File for keepalived
global_defs {
router_id NODE_SLAVE #名称唯一
vrrp_skip_check_adv_addr # 默认是不跳过检查。检查收到的VRRP通告中的所有地址可能会比较耗时,设置此命令的意思是,如果通告与接收的上一个通告来自相同的master路由器,则不执行检查(跳过检查)。
vrrp_strict # 严格遵守VRRP协议
#vrrp_garp_interval 0 #在一个接口发送的两个免费ARP之间的延迟。可以精确到毫秒级。默认是0.
#vrrp_gna_interval 0 #在一个网卡上每组na消息之间的延迟时间,默认为0
script_user root
enable_script_security
max_auto_priority 1
}
vrrp_instance VI_1 {
state BACKUP # 设置初始状态均备
interface enp6s0f1 # 设置绑定虚拟IP的网卡
virtual_router_id 51 # 集群的virtual_router_id值,主备一致
priority 100 # 路由权重
advert_int 1 #检查间隔,默认1秒
notify_master "/etc/keepalived/keepalived_notify.sh master"
notify_backup "/etc/keepalived/keepalived_notify.sh backup"
notify_fault "/etc/keepalived/keepalived_notify.sh fault"
authentication {
auth_type PASS #认证方式
auth_pass 11111111 #认证密码(密码只识别前8位)
}
virtual_ipaddress {
内网虚拟ip/24 # 内网虚拟ip
公网虚拟ip/24 # 公网虚拟ip
}
}
systemctl start keepalived
# 查看启动状态
/etc/init.d/keepalived status
systemctl enable keepalived.service
[root@localhost ~]# ip addr | grep 192.168.1.200
inet 192.168.1.200/24 scope global secondary enp6s0f1
[root@localhost ~]# ip addr | grep 192.168.1.200
[root@localhost ~]#
通过以上验证,说明Keepalived虚拟IP配置成功,如果主备同时存在虚拟IP,那么说明没有配置成功,请检查防火墙firewall是否配置正确。同时,为了验证虚拟IP是否会自动漂移,可以使用systemctl stop keepalived 停止主节点的Keepalived,此时虚拟IP漂移到备节点。
HAProxy也有两种安装方式,yum和源码包。同样,因为yum源的原因,yum方式安装的不是最新稳定版本,所以我们这里选择采用编译源码包的方式安装。
cd /opt/software/
curl -R -O http://www.lua.org/ftp/lua-5.4.6.tar.gz
tar zxf lua-5.4.6.tar.gz
cd lua-5.4.6
make all test
yum install -y pcre-devel systemd-devel
cd /opt/software/
curl -R -O https://www.haproxy.org/download/2.8/src/haproxy-2.8.2.tar.gz
tar zxf haproxy-2.8.2.tar.gz
cd haproxy-2.8.2
make ARCH=x86_64 TARGET=linux-glibc USE_OPENSSL=1 USE_ZLIB=1 USE_PCRE=1 USE_SYSTEMD=1 USE_LUA=1 LUA_INC=/opt/software/lua-5.4.6/src/ LUA_LIB=/opt/software/lua-5.4.6/src/
make install PREFIX=/usr/local/haproxy
ln -s /usr/local/haproxy/sbin/haproxy /usr/sbin/
[root@localhost haproxy-2.8.2]# haproxy -v
HAProxy version 2.8.2-61a0f57 2023/08/09 - https://haproxy.org/
Status: long-term supported branch - will stop receiving fixes around Q2 2028.
Known bugs: http://www.haproxy.org/bugs/bugs-2.8.2.html
Running on: Linux 3.10.0-957.el7.x86_64 #1 SMP Thu Nov 8 23:39:32 UTC 2018 x86_64
mkdir /var/run/haproxy
vi /usr/lib/systemd/system/haproxy.service
[Unit]
Description=HAProxy Load Balancer
After=syslog.target network.target
[Service]
ExecStartPre=/usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -c -q
ExecStart=/usr/sbin/haproxy -Ws -f /etc/haproxy/haproxy.cfg -p /var/run/haproxy/haproxy.pid
ExecReload=/bin/kill -USR2 $MAINPID
[Install]
WantedBy=multi-user.target
mkdir /etc/haproxy
vi /etc/haproxy/haproxy.cfg
global
log 127.0.0.1 local6 info #info日志,有用的信息
log 127.0.0.1 local5 notice #notice日志,普通但重要的事件
pidfile /var/run/haproxy/haproxy.pid #pid文件
maxconn 20000 #最大连接数
user haproxy #用户 或者 uid
group haproxy #组 或者 gid
daemon #后台运行
nbproc 12 #工作进程数量
defaults #默认参数
mode http #模式 http or tcp
log global
retries 3 #重试次数
option redispatch #服务不可用后,重定向到其他健康服务器
option dontlognull #不记录健康检查的日志信息
maxconn 20000 #最大连接数
timeout client 60s # 客户端超时时间
timeout server 60s # 服务端超时时间
timeout connect 1s # haproxy与服务端超时时间
listen admin_stats # frontend and backend 监控
bind *:8118
stats uri /haproxy?stats #查看服务器状态路径
stats auth admin:123456 #用户认证,密码一定要改复杂,可以设置多个
stats hide-version #隐藏统计页面上的HAproxy版本信息
stats refresh 5s # 统计刷新频率
frontend web #listen 接收客户不同请求,并根据acl策略做不同的请求转发至backend处理
mode http
bind *:80 #端口
bind *:443 ssl crt /etc/ssl/certs/***.gitegg.com.pem #端口
option httplog #http格式日志
option forwardfor # 转发客户端真实地址
option httpclose #请求完即关闭
default_backend nginx_servers #默认服务器组
acl nginx_acl hdr_dom(host) -i **n.gitegg.com #定义ACL,根据域名判断
redirect scheme https code 301 if !{ ssl_fc } nginx_acl #nginx_acl http强制跳转ssl
use_backend nginx_servers if nginx_acl #调用ACL
backend nginx_servers #backend 定义Nginx服务器集群
balance roundrobin #基于权重的负载均衡的方式
option httpchk GET /test.html #心跳检测
server nginx1 192.168.1.210:8000 maxconn 10000 cookie server1 weight 1 check inter 1s rise 2 fall 2
server nginx2 192.168.1.195:8000 maxconn 10000 cookie server2 weight 1 check inter 1s rise 2 fall 2
backend nginx_servers_ssl #backend 定义Nginx服务器集群 SSL
balance roundrobin #基于权重的负载均衡的方式
option httpchk GET /test.html #心跳检测
server nginx1s 192.168.1.210:4443 ssl verify none check check-ssl maxconn 10000 cookie server1 weight 1 check inter 1s rise 2 fall 2
server nginx2s 192.168.1.195:4443 ssl verify none check check-ssl maxconn 10000 cookie server2 weight 1 check inter 1s rise 2 fall 2
vi /etc/rsyslog.conf
# Provides UDP syslog reception
$ModLoad imudp
$UDPServerRun 514
local6.info /usr/local/haproxy/logs/info.log
local5.notice /usr/local/haproxy/logs/notice.log
mkdir /usr/local/haproxy/logs
chmod 777 /usr/local/haproxy/logs
systemctl restart rsyslog
systemctl start haproxy
#查看启动状态,如果Active: active (running),表示启动成功
systemctl status haproxy.service
systemctl enable haproxy.service
Keepalived默认监测自身状态是否正常,如果不正常则切换主备,虚拟IP漂移到服务状态正常的服务器上。我们需要保持HAproxy高可用,也就是主HAproxy服务挂掉后,Keepalived也需要切换主备,将虚拟IP切换到HAproxy服务状态正常的服务器上。Keepalived通过调用自定义健康检查脚本实现以上功能。
mkdir /etc/keepalived/scripts
vi /etc/keepalived/scripts/haproxy_check.sh
#!/bin/bash
HA=`ps -C haproxy --no-header | wc -l`
if [ $HA -eq 0 ];then
systemctl start haproxy
sleep 3
if [ `ps -C haproxy --no-header | wc -l` -eq 0 ];then
systemctl stop keepalived
exit 1
fi
fi
exit 0
chmod +x /etc/keepalived/scripts/haproxy_check.sh
! Configuration File for keepalived
global_defs {
router_id NODE_MASTER #名称唯一
vrrp_skip_check_adv_addr # 默认是不跳过检查。检查收到的VRRP通告中的所有地址可能会比较耗时,设置此命令的意思是,如果通告与接收的上一个通告来自相同的master路由器,则不执行检查(跳过检查)。
#vrrp_strict # 严格遵守VRRP协议
#vrrp_garp_interval 0 #在一个接口发送的两个免费ARP之间的延迟。可以精确到毫秒级。默认是0.
#vrrp_gna_interval 0 #在一个网卡上每组na消息之间的延迟时间,默认为0
script_user root
enable_script_security
max_auto_priority 1
}
# 添加HAProxy监测脚本
vrrp_script check_haproxy {
script "/etc/keepalived/haproxy_check.sh"
interval 2 #检查间隔2s
weight 2 #权重
fall 1 # 2次失败代表服务不可用
rise 1 # 1次正确代表服务可用
}
vrrp_instance VI_1 {
state MASTER # 设置初始状态均主
interface enp6s0f1 enp6s0f0 # 设置绑定虚拟IP的网卡
virtual_router_id 51 # 集群的virtual_router_id值,主备一致
priority 100 # 路由权重
advert_int 1 #检查间隔,默认1秒
notify_master "/etc/keepalived/keepalived_notify.sh master"
notify_backup "/etc/keepalived/keepalived_notify.sh backup"
notify_fault "/etc/keepalived/keepalived_notify.sh fault"
authentication {
auth_type PASS #认证方式
auth_pass 11111111 #认证密码(密码只识别前8位)
}
virtual_ipaddress {
内网虚拟ip dev enp6s0f1 # 内网虚拟ip
公网虚拟ip dev enp6s0f0 # 公网虚拟ip
}
track_script {
check_haproxy
}
}
systemctl restart keepalived
通过以上配置之后,可以使用命令停止HAProxy,查看HAProxy服务是否能够重启,根据我们的监测脚本,即使手动停止,HAProxy仍然能够启动,Keepalived并不会发生状态转移。可以修改HAProxy的配置文件使服务无法启动,然后测试Keepalived状态转移情况。
cd /etc/ssl/certs
cat ***.gitegg.com.pem ***.gitegg.com.key | tee ***.gitegg.com.pem
firewall-cmd --zone=public --add-port=80/tcp --permanent
firewall-cmd --zone=public --add-port=443/tcp --permanent
firewall-cmd --zone=public --add-port=8118/tcp --permanent
firewall-cmd --zone=public --add-port=8000/tcp --permanent
firewall-cmd --reload
# 查看当前系统打开的所有端口
firewall-cmd --zone=public --list-ports