설정 내용과 우아한 리로드 문제를 해결하는 방법을 설명하겠습니다.
HAproxy를 실행하고 유지하는 2 개의 노드로 일반적인 설정이 있습니다. Keepalived는 dummy0 인터페이스를 추적하므로 "ifconfig dummy0 down"을 수행하여 강제로 전환 할 수 있습니다.
진짜 문제는, 왜 "하프 프록시 리로드"가 여전히 모든 ESTABLISHED 연결을 삭제하는지 모른다는 것입니다. 일부 시나리오에서는 IP 주소가 적합하지 않습니다.
대신 CONNMARK dirty 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은 프런트 엔드를 바인딩하기 위해 haproxy에서 사용되는 keepalived VIP입니다).
세 번째 및 네 번째 규칙은 패킷 FIN / RST 패킷을 표시합니다. TEE가 FIN / RST 패킷을 "무시"하는 이유를 모르겠습니다.
다섯 번째 규칙은 표시된 모든 패킷의 복제본을 다른 HAproxy (192.168.0.2)로 보냅니다.
여섯 번째 규칙은 원래 플로우에 도달하지 못하도록 새 플로우에 속하는 패킷을 삭제합니다.
인터페이스에서 rp_filter를 비활성화하면 커널에서 해당 화성 패킷을 삭제합니다.
마지막으로 돌아 오는 패킷을 염두에 두십시오! 필자의 경우 비대칭 라우팅이 있습니다 (요청은 클라이언트-> haproxy1-> haproxy2-> 웹 서버에오고 응답은 웹 서버-> haproxy1-> 클라이언트에서옵니다). 잘 작동합니다.
가장 우아한 해결책은 iproute2를 사용하여 전환을 수행하는 것이지만 첫 번째 SYN 패킷에서만 작동했습니다. ACK (3 방향 핸드 셰이크의 세 번째 패킷)를 받았을 때 표시하지 않았습니다. (TEE 대상과 작동하는 것을 보자 마자 조사에 많은 시간을 할애 할 수 없었습니다. 물론 iproute2로 자유롭게 사용해보십시오.
기본적으로 "유예 재 장전"은 다음과 같이 작동합니다.
- iptables 규칙 세트를 활성화하고 새 연결이 다른 HAproxy로 이동하는 것을 즉시 봅니다.
- "배수"프로세스를 감독하기 위해 "netstat -an | grep ESTABLISHED | wc -l"을 주시합니다.
- 연결이 몇 개 (또는 0 개) 만 있으면 "ifconfig dummy0 down"을 유지하여 강제로 장애 조치를 유지하므로 모든 트래픽이 다른 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