HAProxy 负载均衡
适用于 CentOS Stream 9 & 10 / AlmaLinux 9.x & 10.x / Rocky Linux 9.x & 10.x
HAProxy 是一款高性能的 TCP/HTTP 负载均衡器与反向代理。当一台后端服务器扛不住流量,或者你需要在升级、宕机时保持服务可用时,HAProxy 可以把请求分发到多台后端,实现横向扩展与高可用。本文带你在 EL 系统上从零搭起一套四层/七层负载均衡。
- 安装 HAProxy 并理解配置文件的四个核心段
- 配置 frontend 与 backend,把流量分发到多台后端服务器
- 使用
roundrobin/leastconn调度算法与健康检查 - 启用统计页面观察后端状态
- 处理 SELinux 与 firewalld 放行
- 配置 TLS 终止与 HTTP→HTTPS 跳转
- 了解如何配合 Keepalived 让 HAProxy 自身也高可用
- 一台运行 EL 9.x 或 EL 10.x 的系统作为负载均衡器
- 至少两台可访问的后端 Web 服务器(本文以
10.0.0.11/10.0.0.12为例) - sudo 权限
各发行版中的版本
Section titled “各发行版中的版本”安装 HAProxy
Section titled “安装 HAProxy”HAProxy 在 AppStream 仓库中提供,直接安装即可:
$ sudo dnf install haproxy确认版本:
$ haproxy -vHAProxy version 2.4.x ...配置文件结构
Section titled “配置文件结构”HAProxy 的主配置文件是 /etc/haproxy/haproxy.cfg,由四个核心段组成:
| 段 | 作用 |
|---|---|
global | 进程级全局设置:日志、运行用户、最大连接数、调优参数 |
defaults | 为后续的 frontend/backend 提供默认值,避免重复书写 |
frontend | 定义对外监听的地址、端口,以及把流量交给哪个 backend |
backend | 定义后端服务器池、调度算法与健康检查 |
frontend 接收客户端请求,backend 承载真实的后端服务器,两者通过名字关联。
一个完整的负载均衡示例
Section titled “一个完整的负载均衡示例”下面这份配置监听 80 端口,把 HTTP 请求轮询分发到两台后端 Web 服务器。编辑 /etc/haproxy/haproxy.cfg:
global log 127.0.0.1 local2 chroot /var/lib/haproxy pidfile /var/run/haproxy.pid maxconn 4000 user haproxy group haproxy stats socket /var/run/haproxy.sock mode 660 level admin daemon
defaults mode http log global option httplog option dontlognull retries 3 timeout connect 5s timeout client 30s timeout server 30s timeout http-request 10s
frontend web_front bind *:80 default_backend web_servers
backend web_servers balance roundrobin option httpchk GET / server web1 10.0.0.11:80 check server web2 10.0.0.12:80 check几个要点:
mode http表示工作在七层(HTTP),能解析 HTTP 头;改成mode tcp则是四层透传,适合数据库、SMTP 等非 HTTP 协议。balance roundrobin按顺序轮流分发请求。如果后端处理时长差异较大,改用balance leastconn更合适——它会把新连接交给当前连接数最少的后端。server web1 10.0.0.11:80 check中的check启用健康检查;HAProxy 会定期探测该后端,失败后自动摘除,恢复后再加回。option httpchk GET /把健康检查从默认的 TCP 探测升级为 HTTP 探测,向/发起GET请求,只有返回 2xx/3xx 才算健康。生产环境建议指向一个专门的健康检查路径(如/healthz)。
启用统计页面
Section titled “启用统计页面”HAProxy 自带一个实时统计页面,能看到每台后端的状态、流量和会话数。在配置中追加一个 listen 段(或写在某个 frontend 里):
listen stats bind *:8404 stats enable stats uri /haproxy?stats stats auth admin:password stats refresh 10s保存后访问 http://<负载均衡器IP>:8404/haproxy?stats,输入用户名 admin、密码 password 即可查看。
每次修改后,先校验语法再重启,避免把服务改坏:
$ sudo haproxy -c -f /etc/haproxy/haproxy.cfgConfiguration file is valid如果有错误,输出会直接指出出错的行号和原因,按提示修正即可。
SELinux 配置
Section titled “SELinux 配置”EL 系统默认启用 SELinux。HAProxy 运行在 haproxy_t 域下,默认只允许连接一组常见端口。如果你的后端使用非标准端口,连接会被 SELinux 拒绝,表现为后端始终 down 而网络本身却是通的。
打开布尔值,允许 HAProxy 连接任意端口:
$ sudo setsebool -P haproxy_connect_any on放行 HTTP/HTTPS 端口,让客户端能访问到负载均衡器:
$ sudo firewall-cmd --permanent --add-service=http$ sudo firewall-cmd --permanent --add-service=https$ sudo firewall-cmd --reload如果统计页面用了 8404,再放行该端口:
$ sudo firewall-cmd --permanent --add-port=8404/tcp$ sudo firewall-cmd --reload$ sudo systemctl enable --now haproxy查看状态:
$ sudo systemctl status haproxy之后每次改完配置,先 haproxy -c -f 校验,再 sudo systemctl reload haproxy 平滑重载(reload 不会中断已有连接)。
TLS 终止与 HTTPS 跳转
Section titled “TLS 终止与 HTTPS 跳转”让 HAProxy 直接终止 TLS(在负载均衡器上解密,再以明文转发给后端),客户端只与 HAProxy 建立加密连接。
-
准备证书。HAProxy 要求把完整证书链与私钥合并到同一个
.pem文件里(顺序为证书 + 中间证书 + 私钥):合并 fullchain 与私钥 $ sudo mkdir -p /etc/haproxy/certs$ sudo bash -c 'cat fullchain.pem privkey.pem > /etc/haproxy/certs/site.pem'$ sudo chmod 600 /etc/haproxy/certs/site.pem -
在
bind上启用 TLS,并把 80 端口的请求跳转到 HTTPS:/etc/haproxy/haproxy.cfg frontend web_frontbind *:80bind *:443 ssl crt /etc/haproxy/certs/site.pem# 非加密访问一律 301 跳转到 HTTPSredirect scheme https code 301 if !{ ssl_fc }default_backend web_serversssl_fc用来判断当前连接是否走了 TLS;!{ ssl_fc }即”明文请求”,对其执行redirect scheme https。 -
校验并重载:
校验后重载 $ sudo haproxy -c -f /etc/haproxy/haproxy.cfg$ sudo systemctl reload haproxy
让 HAProxy 自身高可用
Section titled “让 HAProxy 自身高可用”单台 HAProxy 仍然是单点故障。生产环境通常部署两台 HAProxy,用 Keepalived 在它们之间漂移一个虚拟 IP(VIP):客户端只访问 VIP,主节点宕机时 VIP 自动切换到备节点,实现负载均衡器自身的冗余。
具体的 Keepalived + VIP 配置、健康检查脚本与脑裂处理,参见 高可用基础。
503 Service Unavailable
Section titled “503 Service Unavailable”这是最常见的报错,几乎都意味着该 backend 没有可用的后端服务器:所有 server 都处于 down 状态,或健康检查全部失败。排查:
$ echo "show servers state" | sudo socat stdio /var/run/haproxy.sock这条命令依赖上面 global 段里配置的 stats socket;socat 来自 EPEL,用 sudo dnf install socat 安装。更直观的方式是打开统计页面,看哪几台是红色(DOWN)。常见原因:后端服务没起、防火墙挡了健康检查、option httpchk 指向的路径返回了非 2xx/3xx,或后端用非标准端口被 SELinux 拦截(见上文 haproxy_connect_any)。
绑定 443 失败 / 后端连接被拒
Section titled “绑定 443 失败 / 后端连接被拒”- 绑不上 443:先确认证书文件存在且包含私钥,
haproxy -c -f会报unable to load SSL certificate。再确认权限可读。如日志显示权限被拒,多半是 SELinux 上下文问题,可用sudo restorecon -Rv /etc/haproxy/修复。 - 后端连接被拒:后端用非标准端口时务必执行
sudo setsebool -P haproxy_connect_any on,否则 SELinux 会静默拒绝连接。
统计页面打不开
Section titled “统计页面打不开”依次检查:listen stats 段是否写了 stats enable;防火墙是否放行了对应端口(如 8404/tcp);访问的 URL 是否与 stats uri 完全一致(本文是 /haproxy?stats);以及用户名密码是否与 stats auth 匹配。
配置语法错误定位
Section titled “配置语法错误定位”启动失败时第一时间运行:
$ sudo haproxy -c -f /etc/haproxy/haproxy.cfg输出会标明出错的行号与原因。也可以查看 journal 获取启动失败的细节:
$ sudo journalctl -u haproxy -n 50 --no-pager- Nginx 反向代理
- 高可用基础
- SELinux 入门
man haproxy/ 官方文档