Saya akan menjelaskan pengaturan saya dan bagaimana saya memecahkan ulang yang anggun:
Saya memiliki pengaturan khas dengan 2 node yang menjalankan HAproxy dan terus dihidupkan. Keepalived melacak antarmuka dummy0, jadi saya bisa melakukan "ifconfig dummy0 down" untuk memaksa beralih.
Masalah sebenarnya adalah bahwa, saya tidak tahu mengapa, "haproxy reload" masih menjatuhkan semua koneksi ESTABLISHED :( Saya mencoba "iptables flipping" yang diajukan oleh gertas, tapi saya menemukan beberapa masalah karena melakukan NAT pada tujuan. Alamat IP, yang bukan solusi yang cocok dalam beberapa skenario.
Sebagai gantinya, saya memutuskan untuk menggunakan hack kotor CONNMARK untuk menandai paket-paket milik koneksi BARU, dan kemudian mengarahkan paket-paket yang ditandai ke node lain.
Berikut adalah aturan dasar 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
Dua aturan pertama menandai paket-paket milik arus baru (123.123.123.123 adalah VIP yang disimpan tetap yang digunakan pada haproxy untuk mengikat frontend).
Paket tanda aturan ketiga dan keempat paket FIN / RST. (Saya tidak tahu mengapa, TEE menargetkan "mengabaikan" paket FIN / RST).
Aturan kelima mengirim duplikat dari semua paket yang ditandai ke HAproxy lainnya (192.168.0.2).
Aturan keenam menjatuhkan paket milik arus baru untuk mencegah mencapai tujuan awal mereka.
Ingatlah untuk menonaktifkan rp_filter pada antarmuka atau kernel akan menjatuhkan paket-paket martian itu.
Dan last but not least, keberatan paket kembali! Dalam kasus saya ada perutean asimetris (permintaan datang ke klien -> haproxy1 -> haproxy2 -> webserver, dan balasan pergi dari server web -> haproxy1 -> client), tetapi tidak mempengaruhi. Ini bekerja dengan baik.
Saya tahu solusi paling elegan adalah dengan menggunakan iproute2 untuk melakukan pengalihan, tetapi hanya bekerja untuk paket SYN pertama. Ketika menerima ACK (paket ke-3 dari jabat tangan 3 arah), itu tidak menandainya :( Saya tidak bisa menghabiskan banyak waktu untuk menyelidiki, begitu saya melihatnya bekerja dengan target TEE, ia meninggalkannya di sana. Tentu saja, silakan mencobanya dengan iproute2.
Pada dasarnya, "reload anggun" berfungsi seperti ini:
- Saya mengaktifkan iptables ruleset dan segera melihat koneksi baru pergi ke HAproxy lainnya.
- Saya mengawasi "netstat -an | grep ESTABLISHED | wc -l" untuk mengawasi proses "pengeringan".
- Setelah hanya ada beberapa (atau nol) koneksi, "ifconfig dummy0 down" untuk memaksa terus di-failover, sehingga semua traffic akan menuju keproxy HA lainnya.
- Saya menghapus aturan iptables
- (Hanya untuk "non-preempting" konfigurasi keepalive) "ifconfig dummy0 up".
Aturan IPtables dapat dengan mudah diintegrasikan ke dalam skrip start / stop:
#!/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