文章目录
haproxy负载均衡
一、简介
HAProxy是一种开源的负载均衡和代理服务器软件,可以实现高可用性和性能优化。它通常用于将传入的请求分发到多个后端服务器,以达到负载均衡的目的。
二、工作原理
HAProxy的工作原理是通过分析传入的请求,并使用配置的规则来决定如何处理请求。它可以根据多种策略(如轮询、最小连接数、源IP地址等)将请求分发到后端服务器。HAProxy还支持会话保持,它可以确保具有相同会话标识符的请求都被发送到同一个后端服务器,以确保用户的一致性体验。
三、工作流程
HAProxy的工作流程如下:
- 监听端口:HAProxy监听一个或多个端口,接收传入的请求。
- 请求分发:根据配置的负载均衡规则,HAProxy将请求分发到一个或多个后端服务器。
- 响应返回:后端服务器处理请求并将响应返回给HAProxy。
- 响应传输:HAProxy将后端服务器的响应传输给客户端。
四、优缺点
优点:
- 高可用性:HAProxy支持故障检测和自动故障转移,可以确保系统的高可用性。
- 性能优化:HAProxy使用轻量级事件驱动的架构,具有高并发性和低延迟,可以提高系统的性能。
- 灵活性:HAProxy支持多种负载均衡算法和灵活的配置选项,可以根据需求进行定制和调整。
缺点:
- 单点故障:由于HAProxy是一个中心化的负载均衡器,如果HAProxy本身出现故障,整个系统的可用性会受到影响。
- 有限的协议支持:相比于其他负载均衡器,HAProxy的协议支持可能相对较少,特定的协议可能需要额外的配置或插件支持。
总的来说,HAProxy是一个高性能、灵活且可靠的负载均衡和代理服务器,适用于构建高可用性和高性能的应用系统。它的优点包括高可用性、性能优化和灵活性,但也需要注意其潜在的单点故障和有限的协议支持。
haproxy负载均衡实战
环境
主机名 | IP地址 | 角色 | 操作系统 | 软件版本 |
---|---|---|---|---|
haproxy | 192.168.179.10 | 负载均衡器 | centos-8 | haproxy-2.7.10 |
web1 | 192.168.179.11 | 后端服务器 | centos-8 | — |
web2 | 192.168.179.12 | 后端服务器 | centos-8 | — |
前期准备
所有主机都要做的操作
//配置yum源,推荐使用阿里云源
[root@haproxy ~]# rm -rf /etc/yum.repos.d/*
[root@haproxy ~]# curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-vault-8.5.2111.repo
[root@haproxy ~]# sed -i -e '/mirrors.cloud.aliyuncs.com/d' -e '/mirrors.aliyuncs.com/d' /etc/yum.repos.d/CentOS-Base.repo
[root@haproxy ~]# yum clean all
27 files removed
[root@haproxy ~]# yum makecache
(另外两台做一样的操作)
//永久关闭防火墙和selinux
[root@haproxy ~]# systemctl disable --now firewalld.service
Removed /etc/systemd/system/multi-user.target.wants/firewalld.service.
Removed /etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service.
[root@haproxy ~]# setenforce 0
[root@haproxy ~]# sed -i 's/^SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config
(另外两台做一样的操作)
//重启主机
[root@haproxy ~]# reboot
(另外两台做一样的操作)
安装haproxy
只在用于做负载均衡的主机上安装haproxy
//创建haproxy用户
[root@haproxy ~]# useradd -r -M -s /sbin/nologin haproxy
[root@haproxy ~]# id haproxy
uid=995(haproxy) gid=992(haproxy) groups=992(haproxy)
[root@haproxy ~]#
//安装依赖包
[root@haproxy ~]# yum -y install make gcc pcre-devel bzip2-devel openssl-devel systemd-devel vim wget --allowerasing
//在haproxy管网下载稳定的安装包
[root@haproxy ~]# wget https://www.haproxy.org/download/2.7/src/haproxy-2.7.10.tar.gz
[root@haproxy ~]# ls
anaconda-ks.cfg haproxy-2.7.10.tar.gz
//解压
[root@haproxy ~]# tar -xf haproxy-2.7.10.tar.gz
[root@haproxy ~]# cd haproxy-2.7.10/
[root@haproxy haproxy-2.7.10]# ls
addons CHANGELOG doc INSTALL Makefile scripts tests
admin CONTRIBUTING examples LICENSE README src VERDATE
BRANCHES dev include MAINTAINERS reg-tests SUBVERS VERSION
//编译
[root@haproxy haproxy-2.7.10]# make clean
[root@haproxy haproxy-2.7.10]# make -j $(nproc) TARGET=linux-glibc USE_OPENSSL=1 USE_ZLIB=1 USE_PCRE=1 USE_SYSTEMD=1
(编译过程省略...)
//指定目录安装
[root@haproxy haproxy-2.7.10]# make install PREFIX=/usr/local/haproxy
//设置环境变量
[root@haproxy haproxy-2.7.10]# ln -s /usr/local/haproxy/sbin/* /usr/sbin/
[root@haproxy ~]# which haproxy
/usr/sbin/haproxy
//配置内核参数
[root@haproxy ~]# echo 'net.ipv4.ip_nonlocal_bind = 1' >> /etc/sysctl.conf
[root@haproxy ~]# echo 'net.ipv4.ip_forward = 1' >> /etc/sysctl.conf
[root@haproxy ~]# sysctl -p
net.ipv4.ip_nonlocal_bind = 1
net.ipv4.ip_forward = 1
//配置加入systemctl管理
[root@haproxy ~]# vim /usr/lib/systemd/system/haproxy.service
[root@haproxy ~]# cat /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.pid
ExecReload=/bin/kill -USR2 $MAINPID
[Install]
WantedBy=multi-user.target
[root@haproxy ~]# systemctl daemon-reload //使其生效
//配置日志记录功能
[root@haproxy ~]# vim /etc/rsyslog.conf
[root@haproxy ~]# cat /etc/rsyslog.conf
# Save boot messages also to boot.log
local0.* /var/log/haproxy.log //添加此行
local7.* /var/log/boot.log
//重启日志服务
[root@haproxy ~]# systemctl restart rsyslog.service
配置http负载集群
配置用于测试的http页面
在后端服务器上准备测试的http页面(主机web1、web2)
//安装httpd服务,启动并设置开机自启
[root@web1 ~]# yum -y install httpd
[root@web1 ~]# systemctl enable --now httpd
Created symlink /etc/systemd/system/multi-user.target.wants/httpd.service → /usr/lib/systemd/system/httpd.service.
[root@web2 ~]# yum -y install httpd
[root@web2 ~]# systemctl enable --now httpd
Created symlink /etc/systemd/system/multi-user.target.wants/httpd.service → /usr/lib/systemd/system/httpd.service.
//准备一个测试用的web页面文件
[root@web1 ~]# echo "this is web1" > /var/www/html/index.html
[root@web1 ~]# systemctl restart httpd
[root@web2 ~]# echo "this is web2" > /var/www/html/index.html
[root@web2 ~]# systemctl restart httpd
配置http负载均衡规则
在负载均衡器上进行配置(主机haproxy)
//提供配置文件,全部内容都是手动添加的
[root@haproxy ~]# mkdir /etc/haproxy
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
[root@haproxy ~]# cat /etc/haproxy/haproxy.cfg
#--------------全局配置----------------
global
log 127.0.0.1 local0 info
#log loghost local0 info
maxconn 20480
#chroot /usr/local/haproxy
pidfile /var/run/haproxy.pid
#maxconn 4000
user haproxy
group haproxy
daemon
#---------------------------------------------------------------------
#common defaults that all the 'listen' and 'backend' sections will
#use if not designated in their block
#---------------------------------------------------------------------
defaults
mode http
log global
option dontlognull
option httpclose
option httplog
#option forwardfor
option redispatch
balance roundrobin
timeout connect 10s
timeout client 10s
timeout server 10s
timeout check 10s
maxconn 60000
retries 3
#--------------统计页面配置------------------
listen admin_stats
bind 0.0.0.0:8189 //访问状态页面的端口号
stats enable
mode http
log global
stats uri /haproxy_stats //访问状态页面的URI
stats realm Haproxy\ Statistics
stats auth admin:admin //登录状态页面的用户名和密码,可自行修改
#stats hide-version
stats admin if TRUE
stats refresh 30s
#---------------web设置-----------------------
listen webcluster
bind 0.0.0.0:80
mode http
#option httpchk GET /index.html
log global
maxconn 3000
balance roundrobin
cookie SESSION_COOKIE insert indirect nocache
server web1 192.168.179.11:80 check inter 2000 fall 5 //添加的后端服务器
server web2 192.168.179.12:80 check inter 2000 fall 5 //添加的后端服务器
#server web1 192.168.179.1:80 cookie web01 check inter 2000 fall 5
[root@haproxy ~]#
//启动或重启haproxy服务,并设置开机自启
[root@haproxy ~]# systemctl restart haproxy.service
[root@haproxy ~]# systemctl enable haproxy.service
Created symlink /etc/systemd/system/multi-user.target.wants/haproxy.service → /usr/lib/systemd/system/haproxy.service.
[root@haproxy ~]#
访问负载均衡器的http页面测试
访问haproxy的ip,会将请求转发给后端服务器,第一次分配给了web1
刷新几次,请求被转发到了web2上
配置https负载集群
配置用于测试的https页面
生成证书,并在所有后端服务器上安装证书
安装证书服务
//在web1上配置ssl证书
[root@web1 ~]# mkdir -p /etc/pki/CA
[root@web1 ~]# cd /etc/pki/CA
[root@web1 CA]# mkdir private
[root@web1 CA]# (umask 077;openssl genrsa -out private/cakey.pem 2048)
Generating RSA private key, 2048 bit long modulus (2 primes)
..........................+++++
.........................................+++++
e is 65537 (0x010001)
[root@web1 CA]# ls private
cakey.pem
[root@web1 CA]#
[root@web1 CA]# openssl req -new -x509 -key private/cakey.pem -out cacert.pem -days 365
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:CN
State or Province Name (full name) []:HB
Locality Name (eg, city) [Default City]:WH
Organization Name (eg, company) [Default Company Ltd]:www.wanf.com
Organizational Unit Name (eg, section) []:www.wanf.com
Common Name (eg, your name or your server's hostname) []:www.wanf.com
Email Address []:1@2.com
[root@web1 CA]# ls
cacert.pem private
[root@web1 CA]# ls private/
cakey.pem
//客户端(例如httpd服务器)生成密钥
[root@web1 CA]# mkdir certs newcerts crl
[root@web1 CA]# touch index.txt && echo 01 > serial
[root@web1 CA]# cd /etc/httpd/ && mkdir ssl && cd ssl
[root@web1 ssl]# (umask 077;openssl genrsa -out httpd.key 2048)
Generating RSA private key, 2048 bit long modulus (2 primes)
....................................................................................................+++++
...+++++
e is 65537 (0x010001)
[root@web1 ssl]#
//客户端生成证书签署请求
[root@web1 ssl]# openssl req -new -key httpd.key -days 365 -out httpd.csr
Ignoring -days; not generating a certificate
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:CN
State or Province Name (full name) []:HB
Locality Name (eg, city) [Default City]:WH
Organization Name (eg, company) [Default Company Ltd]:www.wanf.com
Organizational Unit Name (eg, section) []:www.wanf.com
Common Name (eg, your name or your server's hostname) []:www.wanf.com
Email Address []:1@2.com
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
[root@web1 ssl]#
//CA签署客户端提交上来的证书
[root@web1 ssl]# ls
httpd.csr httpd.key
[root@web1 ssl]# openssl ca -in httpd.csr -out httpd.crt -days 365
Using configuration from /etc/pki/tls/openssl.cnf
Check that the request matches the signature
Signature ok
Certificate Details:
Serial Number: 1 (0x1)
Validity
Not Before: Oct 9 13:54:55 2023 GMT
Not After : Oct 8 13:54:55 2024 GMT
Subject:
countryName = CN
stateOrProvinceName = HB
organizationName = www.wanf.com
organizationalUnitName = www.wanf.com
commonName = www.wanf.com
emailAddress = 1@2.com
X509v3 extensions:
X509v3 Basic Constraints:
CA:FALSE
Netscape Comment:
OpenSSL Generated Certificate
X509v3 Subject Key Identifier:
6C:78:10:1B:8F:25:05:EE:3A:4B:87:CA:71:99:43:A0:C7:65:2E:DD
X509v3 Authority Key Identifier:
keyid:E5:2C:7B:4B:77:8F:C1:53:6B:0B:BD:C0:F9:A1:11:B0:2B:D6:F0:DB
Certificate is to be certified until Oct 8 13:54:55 2024 GMT (365 days)
Sign the certificate? [y/n]:y
1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated
[root@web1 ssl]#
//安装证书服务
[root@web1 ssl]# yum -y install httpd-devel mod_ssl
//修改配置文件
[root@web1 ssl]# vim /etc/httpd/conf.d/ssl.conf
[root@web1 ssl]# grep -Ev '^$|^#' /etc/httpd/conf.d/ssl.conf
Listen 443 https
SSLPassPhraseDialog exec:/usr/libexec/httpd-ssl-pass-dialog
SSLSessionCache shmcb:/run/httpd/sslcache(512000)
SSLSessionCacheTimeout 300
SSLCryptoDevice builtin
<VirtualHost _default_:443>
DocumentRoot "/var/www/html/www.wanf.com" //取消注释,修改为自己域名
ServerName www.wanf.com:443 //取消注释,修改为自己域名
ErrorLog logs/ssl_error_log
TransferLog logs/ssl_access_log
LogLevel warn
SSLEngine on
SSLHonorCipherOrder on
SSLCipherSuite PROFILE=SYSTEM
SSLProxyCipherSuite PROFILE=SYSTEM
SSLCertificateFile /etc/httpd/ssl/httpd.crt //修改成对应路径
SSLCertificateKeyFile /etc/httpd/ssl/httpd.key //修改成对应路径
<FilesMatch "\.(cgi|shtml|phtml|php)$">
SSLOptions +StdEnvVars
</FilesMatch>
<Directory "/var/www/cgi-bin">
SSLOptions +StdEnvVars
</Directory>
BrowserMatch "MSIE [2-5]" \
nokeepalive ssl-unclean-shutdown \
downgrade-1.0 force-response-1.0
CustomLog logs/ssl_request_log \
"%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
</VirtualHost>
[root@web1 ssl]#
//创建https的网页文件
[root@web1 ~]# mkdir -p /var/www/html/www.wanf.com
[root@web1 ~]# echo "this is web1 https" > /var/www/html/www.wanf.com/index.html
[root@web1 ~]#
//重启服务
[root@web1 ~]# systemctl restart httpd
在RS2上安装同样的证书
//通过scp把刚刚web1生成的证书拉过来
[root@web2 ~]# cd /etc/httpd/ && mkdir ssl && cd ssl
[root@web2 ssl]# scp root@192.168.179.11:/etc/httpd/ssl/httpd.crt /etc/httpd/ssl/
The authenticity of host '192.168.179.11 (192.168.179.11)' can't be established.
ECDSA key fingerprint is SHA256:U1hP1QknHUuLXn71NCSh1JVmGkyNy4ZN6YQA4XF/VAw.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '192.168.179.11' (ECDSA) to the list of known hosts.
root@192.168.179.11's password:
httpd.crt 100% 4602 5.9MB/s 00:00
[root@web2 ssl]# scp root@192.168.179.11:/etc/httpd/ssl/httpd.key /etc/httpd/ssl/
root@192.168.179.11's password:
httpd.key 100% 1679 2.0MB/s 00:00
[root@web2 ssl]# ls
httpd.crt httpd.key
[root@web2 ssl]#
//安装证书服务
[root@web2 ssl]# yum -y install httpd-devel mod_ssl
//修改配置文件,和上面的一模一样
[root@web2 ssl]# vim /etc/httpd/conf.d/ssl.conf
[root@web2 ssl]# grep -Ev '^$|^#' /etc/httpd/conf.d/ssl.conf
Listen 443 https
SSLPassPhraseDialog exec:/usr/libexec/httpd-ssl-pass-dialog
SSLSessionCache shmcb:/run/httpd/sslcache(512000)
SSLSessionCacheTimeout 300
SSLCryptoDevice builtin
<VirtualHost _default_:443>
DocumentRoot "/var/www/html/www.wanf.com" //取消注释,修改为自己域名
ServerName www.wanf.com:443 //取消注释,修改为自己域名
ErrorLog logs/ssl_error_log
TransferLog logs/ssl_access_log
LogLevel warn
SSLEngine on
SSLHonorCipherOrder on
SSLCipherSuite PROFILE=SYSTEM
SSLProxyCipherSuite PROFILE=SYSTEM
SSLCertificateFile /etc/httpd/ssl/httpd.crt //修改成对应路径
SSLCertificateKeyFile /etc/httpd/ssl/httpd.key //修改成对应路径
<FilesMatch "\.(cgi|shtml|phtml|php)$">
SSLOptions +StdEnvVars
</FilesMatch>
<Directory "/var/www/cgi-bin">
SSLOptions +StdEnvVars
</Directory>
BrowserMatch "MSIE [2-5]" \
nokeepalive ssl-unclean-shutdown \
downgrade-1.0 force-response-1.0
CustomLog logs/ssl_request_log \
"%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
</VirtualHost>
[root@web2 ssl]#
//创建https的网页文件
[root@web2 ~]# mkdir -p /var/www/html/www.wanf.com
[root@web2 ~]# echo "this is web2 https" > /var/www/html/www.wanf.com/index.html
//重启服务
[root@web2 ~]# systemctl restart httpd
配置https负载均衡规则
//在负载均衡器(主机haproxy)上添加配置文件内容
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
[root@haproxy ~]# cat /etc/haproxy/haproxy.cfg
(省略)
listen webcluster-https
bind 0.0.0.0:443
mode tcp //这里的协议一定要改成tcp协议
#option httpchk GET /index.html
log global
maxconn 3000
balance roundrobin
cookie SESSION_COOKIE insert indirect nocache
server web3 192.168.179.11:443 check inter 2000 fall 5
server web4 192.168.179.12:443 check inter 2000 fall 5
#server web1 192.168.179.1:443 cookie web01 check inter 2000 fall 5
//重启haproxy服务
[root@haproxy ~]# systemctl restart haproxy.service
//已经监听443端口了
[root@haproxy ~]# ss -anlt
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 2048 0.0.0.0:80 0.0.0.0:*
LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
LISTEN 0 2048 0.0.0.0:443 0.0.0.0:*
LISTEN 0 2048 0.0.0.0:8189 0.0.0.0:*
LISTEN 0 128 [::]:22 [::]:*
[root@haproxy ~]#
访问负载均衡器的https页面测试
第一次访问,负载均衡器把请求分配给了web2
刷新几次,请求被分配到了web1上面
访问haproxy服务的状态页面
IP地址后接上8189/haproxy_stats就可以访问
里面是haproxy的负载集群主机的状态
登录的用户名和密码在上面配置负载集群的配置文件里面有
[root@haproxy ~]# cat /etc/haproxy/haproxy.cfg
(省略)
#--------------统计页面配置------------------
listen admin_stats
bind 0.0.0.0:8189 //访问状态页面的端口号
stats enable
mode http
log global
stats uri /haproxy_stats //访问状态页面的URI
stats realm Haproxy\ Statistics
stats auth admin:admin //登录状态页面的用户名和密码,可自行修改
#stats hide-version
stats admin if TRUE
stats refresh 30s
(省略)