
HAProxy 是一款开源软件,为基于 TCP 和 HTTP 的高可用性负载均衡应用提供 代理 服务器服务。
Keepalived 是一款开源软件,能够为两台以上服务器提供 IP 故障转移 能力。Keepalived 内部使用 多播 通信技术。
在我们的架构中,我们将使用 HAProxy 作为负载均衡器,并使用 Keepalived 进行 IP 转移,即将 HAProxy 架构实现为 集群。
我们的场景中有 3 台服务器。我们将在这些服务器上安装 HAProxy,使其成为负载均衡器。然后安装 Keepalived 服务,当其中一台服务器宕机时,通过 IP 故障转移无缝切换到另一台服务器,从而保持负载均衡服务的运行。
为此,我们将使用 4 个 IP(这些 IP 完全是虚构的):
现在,按如下方式在三台服务器上安装 HAProxy 和 Keepalived 服务:
sudo add-apt-repository ppa:vbernat/haproxy-2.7 -y
sudo apt update
sudo apt install haproxy keepalived -y
sudo openssl dhparam -out /etc/haproxy/dhparams.pem 2048
注意 1:服务器上需要设置“net.ipv4.ip_nonlocal_bind=1”。否则,HAProxy 的配置将无法同时绑定相同的 IP,从而产生绑定错误,服务将无法启动。为此,您需要执行以下步骤:
首先,编辑“vi /etc/sysctl.conf”文件,粘贴以下参数,保存并退出:
net.ipv4.ip_nonlocal_bind=1
然后,运行以下命令:
sysctl -p
注意 2:如果使用 443 SSL,则需要在“/etc/ssl/private/”目录下准备名为“haproxy.pem”的 SSL 捆绑文件(包含 .crt、.ca、*.key)。
现在,我们来看一个示例 HAProxy 配置。您的所有 HAProxy 将使用相同的配置。
为此,您将编辑“/etc/haproxy/haproxy.cfg”文件。以下配置最低支持 HAv2。
vi /etc/haproxy/haproxy.cfg
以下是默认值:
global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
stats timeout 30s
user haproxy
group haproxy
daemon
# maxconn 100000 #replaceable
# Default SSL material locations
ca-base /etc/ssl/certs
crt-base /etc/ssl/private
# Default ciphers to use on SSL-enabled listening sockets.
# For more information, see ciphers(1SSL). This list is from:
# https://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/
# An alternative list with additional directives can be obtained from
# https://mozilla.github.io/server-side-tls/ssl-config-generator/?server=haproxy
ssl-default-bind-ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:RSA+AESGCM:RSA+AES:!aNULL:!MD5:!DSS
#ssl-default-bind-options no-sslv3
ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets
ssl-dh-param-file /etc/haproxy/dhparams.pem
#tune.ssl.default-dh-param 2048
# nbproc 1
# nbthread 8
tune.maxrewrite 16384
tune.bufsize 32768
defaults
log global
mode http
option httplog
option dontlognull
option forwardfor
# maxconn 1000000 #replaceable
timeout connect 3000000
timeout client 6000000
timeout server 6000000
errorfile 400 /etc/haproxy/errors/400.http
errorfile 403 /etc/haproxy/errors/403.http
errorfile 408 /etc/haproxy/errors/408.http
errorfile 500 /etc/haproxy/errors/500.http
errorfile 502 /etc/haproxy/errors/502.http
errorfile 503 /etc/haproxy/errors/503.http
errorfile 504 /etc/haproxy/errors/504.http
HAProxy 的 仪表板 配置部分(已添加用于监控的 prometheus 集成):
listen stats
bind fatlan.com:8989
mode http
stats enable
stats uri /stats
option http-use-htx
http-request use-service prometheus-exporter if { path /metrics }
#stats hide-version
stats realm HAProxy\ Statistics
stats auth admin:admin
以下两个区块中使用了 ACL。第一个区块:如果链接中任意位置包含“rest”一词,则触发 middleware-fatlan-backend 区块;第二个区块:如果是不同的域名请求(forum.fatlan.com),则触发 backend fatlan-forum-backend;除此之外的所有请求将进入 fatlan-backend443 区块。其他端口转发除外。
将 80 端口重定向到 443 端口 的部分:
frontend fatlan80
bind fatlan.com:80
mode http
redirect scheme https if !{ ssl_fc }
frontend fatlan443
bind fatlan.com:443 ssl crt /etc/ssl/private/haproxy.pem ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS
option httplog
option forwardfor
#http-request set-header X-Client-IP req.hdr_ip([X-Forwarded-For])
#option forwardfor except 127.0.0.0/8
option http-server-close
http-request set-header X-Forwarded-Proto https
# reqadd X-Forwarded-Proto:\ https #old config
mode http
default_backend fatlan-backend443
ACL 示例配置(代理传递):如果链接中任意位置出现 rest 一词则转发:
acl middleware-fatlan path_beg /rest
use_backend middleware-fatlan-backend if middleware-fatlan
ACL 不同 论坛 主机转发:
acl host_fatlanforum hdr(host) -i forum.fatlan.com
use_backend fatlan-forum-backend if host_fatlanforum
默认转发部分,用于 443:
backend fatlan-backend443
mode http
balance roundrobin
stick store-request src
stick-table type ip size 256k expire 30m
option forwardfor
# option httplog
option httpchk HEAD /
server frontend_01 10.10.37.12:8001 check port 8001 inter 3000 rise 2 fall 3
server frontend_02 10.10.37.13:8001 check port 8001 inter 3000 rise 2 fall 3
ACL 传入的 rest 转发部分:
backend middleware-fatlan-backend
mode http
balance roundrobin
stick store-request src
stick-table type ip size 256k expire 30m
option forwardfor
# option httplog
option httpchk OPTIONS /login HTTP/1.0
http-check expect status 200
http-request replace-path (.*)(?:rest\/)(.*) \1\2
# reqrep ^([^\ :]*)\ /rest[/]?(.*) \1\ //\2 #old config
server middleware_01 10.10.37.34:3000 check port 4000 inter 12000 rise 3 fall 3
server middleware_02 10.10.37.35:3000 check port 4000 inter 12000 rise 3 fall 3
ACL 传入的 论坛 转发部分:
backend fatlan-forum-backend
mode http
option forwardfor
# option httplog
option httpchk HEAD /
server forum_01 10.10.37.45:8080 check port 8080 inter 3000 rise 2 fall 3
其他示例可按如下方式配置。
5000 端口示例:
frontend Panel5000
bind fatlan.com:5000
# option httplog
option forwardfor except 127.0.0.0/8
#option http-server-close
http-request set-header X-Forwarded-Proto https
# reqadd X-Forwarded-Proto:\ https #old config
mode http
default_backend panel-backend5000
5000 端口转发部分:
backend panel-backend5000
mode http
balance roundrobin
stick store-request src
stick-table type ip size 256k expire 30m
option forwardfor
# option httplog
option httpchk HEAD /
server panel_01 10.10.37.43:5000 check port 5000 inter 12000 rise 3 fall 3
server panel_02 10.10.37.44:5000 check port 5000 inter 12000 rise 3 fall 3
3306 mysql 示例:
frontend fatlanmysql
bind fatlan.com:3306
mode tcp
default_backend fatlanmysql-backend3306
3306 端口转发部分:
backend fatlanmysql-backend3306
mode tcp
server mysql_01 10.10.37.60:3306 check
server mysql_02 10.10.37.61:3306 check backup
server mysql_03 10.10.37.62:3306 check backup
您也可以对其它域名、子域名或端口进行转发,均通过同一个 HAProxy 完成。实际上,上面已经看到了针对子域名的 ACL 转发配置。
针对 egitim.fatlan.com 子域名的 4444 端口示例:
frontend egitim4444
bind egitim.fatlan.com:4444
# option httplog
option forwardfor except 127.0.0.0/8
#option http-server-close
http-request set-header X-Forwarded-Proto https
# reqadd X-Forwarded-Proto:\ https #old config
mode http
default_backend egitim-backend4444