我在公共子网中拥有两台服务器,它们分别具有公有和私有 IP。我想HAproxy
配置keepalived
并使其server1
充当master
和。server2
backup
如果server1
出现下滑,我想server2
接管。
我们将其分类如下:
server1: private_ip1 & public_ip1
server2: private_ip2 & public_ip2
virtual_public_ip
我在两台服务器上都有一个 Flask 应用程序,其代码如下:
app.py
from flask import *
import socket
app = Flask(__name__)
@app.route("/")
def index():
hostname = socket.gethostname()
ip = socket.gethostbyname(hostname)
return f"<h1>Hello from computer {hostname} with ip {ip}</h1>"
if __name__ == "__main__":
app.run(debug=False)
该代码基本上将显示服务器的主机名及其 IP 地址。
以下是每个服务器的 HAproxy 和 Keepalived 配置文件。
server1 HAproxy
global
log 127.0.0.1 local2
chroot /var/lib/haproxy
pidfile /var/run/haproxy.pid
maxconn 4000
user haproxy
group haproxy
daemon
# turn on stats unix socket
stats socket /var/lib/haproxy/stats
# utilize system-wide crypto-policies
ssl-default-bind-ciphers PROFILE=SYSTEM
ssl-default-server-ciphers PROFILE=SYSTEM
defaults
mode http
log global
option httplog
option dontlognull
option http-server-close
option forwardfor except 127.0.0.0/8
option redispatch
retries 3
timeout http-request 10s
timeout queue 1m
timeout connect 10s
timeout client 1m
timeout server 1m
timeout http-keep-alive 10s
timeout check 10s
maxconn 3000
frontend main
bind *:80
default_backend app_servers
backend app_servers
balance roundrobin
server haproxy-01 public_ip1:5000 check
server haproxy-02 public_ip2:5000 backup
server1 keepalived
global_defs {
enable_script_security
script_user th3pl4gu3
}
vrrp_script chk_haproxy {
script "pidof haproxy"
interval 2
weight 2
}
vrrp_instance VI_1 {
state MASTER
interface eth0
virtual_router_id 51
priority 101
virtual_ipaddress {
virtual_public_ip
}
track_script {
chk_haproxy
}
}
server2 HAproxy
global
log 127.0.0.1 local2
chroot /var/lib/haproxy
pidfile /var/run/haproxy.pid
maxconn 4000
user haproxy
group haproxy
daemon
# turn on stats unix socket
stats socket /var/lib/haproxy/stats
# utilize system-wide crypto-policies
ssl-default-bind-ciphers PROFILE=SYSTEM
ssl-default-server-ciphers PROFILE=SYSTEM
defaults
mode http
log global
option httplog
option dontlognull
option http-server-close
option forwardfor except 127.0.0.0/8
option redispatch
retries 3
timeout http-request 10s
timeout queue 1m
timeout connect 10s
timeout client 1m
timeout server 1m
timeout http-keep-alive 10s
timeout check 10s
maxconn 3000
frontend main
bind *:80
default_backend app_servers
backend app_servers
balance roundrobin
server haproxy-01 public_ip1:5000 backup
server haproxy-02 public_ip2:5000 check
server2 keepalived
global_defs {
enable_script_security
script_user th3pl4gu3
}
vrrp_script chk_haproxy {
script "pidof haproxy"
interval 2
weight 2
}
vrrp_instance VI_1 {
state BACKUP
interface eth0
virtual_router_id 51
priority 100
virtual_ipaddress {
virtual_public_ip
}
track_script {
chk_haproxy
}
}
如果我打开浏览器并输入http://public_ip1:5000
URL,我可以看到 server1 的主机名和virtual_public_ip
。
如果我打开浏览器并输入http://public_ip2:5000
URL,我可以看到 server2 的主机名,并且仍然可以看到virtual_public_ip
。
但是如果我尝试使用虚拟 IP 本身访问该应用程序,它是不起作用的http://virtual_public_ip
。
我究竟做错了什么 ?
答案1
我如何让我的 haproxy 监听我的公共 IP?
最简单的解决方案是不明确地将其绑定到特定的 IP 地址。而不是这样:
frontend main
bind private_ip1:80
default_backend app_servers
使用:
frontend main
bind :80
default_backend app_servers
这会将 haproxy 绑定到您主机上的所有可用地址。如果您确实不想在私有地址上使用端口 80,则可以将其明确绑定到公共 IP:
frontend main
bind public_ip1:80
default_backend app_servers
为了测试你的配置,我整理了一个docker compose 堆栈这将创建一个运行 haproxy 和 keepalived 的双节点环境。请随意使用它进行测试。