我将解释我的设置以及如何解决优雅的重载:
我有一个典型的安装程序,其中有2个节点运行HAproxy并保持活动状态。Keepalived跟踪接口dummy0,因此我可以执行“ ifconfig dummy0 down”来强制切换。
真正的问题是,我不知道为什么,“ haproxy reload”仍然会丢弃所有已建立的连接:(我尝试了gertas提出的“ iptables fliping”,但是我发现了一些问题,因为它在目标上执行了NAT IP地址,在某些情况下不是合适的解决方案。
相反,我决定使用CONNMARK脏hack标记属于NEW连接的数据包,然后将这些标记的数据包重定向到另一个节点。
这是iptables规则集:
iptables -t mangle -A PREROUTING -i eth1 -d 123.123.123.123/32 -m conntrack --ctstate NEW -j CONNMARK --set-mark 1
iptables -t mangle -A PREROUTING -j CONNMARK --restore-mark
iptables -t mangle -A PREROUTING -i eth1 -p tcp --tcp-flags FIN FIN -j MARK --set-mark 2
iptables -t mangle -A PREROUTING -i eth1 -p tcp --tcp-flags RST RST -j MARK --set-mark 2
iptables -t mangle -A PREROUTING -i eth1 -m mark ! --mark 0 -j TEE --gateway 192.168.0.2
iptables -t mangle -A PREROUTING -i eth1 -m mark --mark 1 -j DROP
前两个规则标记属于新流的数据包(123.123.123.123是在代理服务器上用于绑定前端的keepalived VIP)。
第三和第四条规则将数据包标记为FIN / RST数据包。(我不知道为什么,TEE目标“忽略”了FIN / RST数据包)。
第五条规则将所有标记数据包的副本发送到另一个HAproxy(192.168.0.2)。
第六条规则丢弃属于新流的数据包,以防止到达其原始目的地。
请记住在接口上禁用rp_filter,否则内核将丢弃那些火星数据包。
最后但并非最不重要的一点是,请注意返回的数据包!在我的情况下,存在非对称路由(请求到达客户端-> haproxy1-> haproxy2->网络服务器,而答复来自网络服务器-> haproxy1->客户端),但这并不影响。工作正常。
我知道最优雅的解决方案是使用iproute2进行转移,但它仅适用于第一个SYN数据包。当它收到ACK(3次握手的第3个数据包)时,它没有标记它:(我花了很多时间进行研究,一看到它与TEE目标一起工作,它就留在了那里。当然,请随时使用iproute2尝试一下。
基本上,“优美的重载”是这样的:
- 我启用了iptables规则集,并立即看到到另一个HAproxy的新连接。
- 我密切注意“ netstat -an | grep已建立| wc -l”以监督“排水”过程。
- 一旦只有几个(或零个)连接,请“ ifconfig dummy0 down”以强制keepalived进行故障转移,因此所有流量都将流向另一个HAproxy。
- 我删除了iptables规则集
- (仅用于“非抢占” keepalive配置)“ ifconfig dummy0 up”。
IPtables规则集可以轻松地集成到开始/停止脚本中:
#!/bin/sh
case $1 in
start)
echo Redirection for new sessions is enabled
# echo 0 > /proc/sys/net/ipv4/tcp_fwmark_accept
for f in /proc/sys/net/ipv4/conf/*/rp_filter; do echo 0 > $f; done
iptables -t mangle -A PREROUTING -i eth1 ! -d 123.123.123.123 -m conntrack --ctstate NEW -j CONNMARK --set-mark 1
iptables -t mangle -A PREROUTING -j CONNMARK --restore-mark
iptables -t mangle -A PREROUTING -i eth1 -p tcp --tcp-flags FIN FIN -j MARK --set-mark 2
iptables -t mangle -A PREROUTING -i eth1 -p tcp --tcp-flags RST RST -j MARK --set-mark 2
iptables -t mangle -A PREROUTING -i eth1 -m mark ! --mark 0 -j TEE --gateway 192.168.0.2
iptables -t mangle -A PREROUTING -i eth1 -m mark --mark 1 -j DROP
;;
stop)
iptables -t mangle -D PREROUTING -i eth1 -m mark --mark 1 -j DROP
iptables -t mangle -D PREROUTING -i eth1 -m mark ! --mark 0 -j TEE --gateway 192.168.0.2
iptables -t mangle -D PREROUTING -i eth1 -p tcp --tcp-flags RST RST -j MARK --set-mark 2
iptables -t mangle -D PREROUTING -i eth1 -p tcp --tcp-flags FIN FIN -j MARK --set-mark 2
iptables -t mangle -D PREROUTING -j CONNMARK --restore-mark
iptables -t mangle -D PREROUTING -i eth1 ! -d 123.123.123.123 -m conntrack --ctstate NEW -j CONNMARK --set-mark 1
echo Redirection for new sessions is disabled
;;
esac