IPVS/SNAT: подключайтесь, когда директор и сервер совместно используют одни и те же хосты (автономный кластер)
Я пытаюсь настроить кластер из двух узлов, который использует IPVS для балансировки нагрузки. Оба узла являются директорами и серверами IPVS одновременно.
Это мои настройки (на самом деле они настроены с помощью keepalived, но для тестирования я воспроизвел проблему вручную):
- VIP 192.168.100.99
- Узел 1: 192.168.100.91
- Узел 2: 192.168.100.92
- Служба работает на порту 5555 (для тестирования, просто
nc -k -l 5555
на обоих узлах)
Конфигурация узла 1:
node1# ip addr add 192.168.100.99/24 dev ens192
node1# ip addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
2: ens192: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 00:50:56:94:ca:50 brd ff:ff:ff:ff:ff:ff
inet 192.168.100.91/24 brd 192.168.100.255 scope global ens192
valid_lft forever preferred_lft forever
inet 192.168.100.99/24 scope global secondary ens192
valid_lft forever preferred_lft forever
node1# modprobe ip_vs
node1# modprobe xt_ipvs
node1# sysctl net.ipv4.ip_forward=1
node1# sysctl net.ipv4.vs.conntrack=1
node1# ipvsadm -A -t 192.168.100.99:5555 -s wrr
node1# ipvsadm -a -t 192.168.100.99:5555 -r 192.168.100.91:5555 -m -w 100
node1# ipvsadm -a -t 192.168.100.99:5555 -r 192.168.100.92:5555 -m -w 100
node1# ipvsadm -ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 192.168.100.99:5555 wrr
-> 192.168.100.91:5555 Masq 100 0 0
-> 192.168.100.92:5555 Masq 100 0 0
node1# iptables -t nat -A POSTROUTING -m ipvs --vaddr 192.168.100.99 --vport 5555 -j SNAT --to-source 192.168.100.91
Доступ к сервису теперь работает с узла 1, узла 2 и других хостов.
Теперь я добавляю конфигурацию резервного копирования на узел 2, как если бы keepalived делал это:
node2# # ip addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
2: ens192: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 00:50:56:94:7c:21 brd ff:ff:ff:ff:ff:ff
inet 192.168.100.92/24 brd 192.168.100.255 scope global ens192
valid_lft forever preferred_lft forever
node2# modprobe ip_vs
node2# modprobe xt_ipvs
node2# sysctl net.ipv4.ip_forward=1
node2# sysctl net.ipv4.vs.conntrack=1
node2# ipvsadm -A -t 192.168.100.99:5555 -s wrr
Именно сейчас больше невозможно подключиться от узла 2 к VIP, поскольку IPVS перехватывает трафик, хотя VIP не настроен в этой системе. узел1 и другие хосты продолжают иметь доступ к сервисам на VIP.
node2# ipvsadm -a -t 192.168.100.99:5555 -r 192.168.100.91:5555 -m -w 100
node2# ipvsadm -a -t 192.168.100.99:5555 -r 192.168.100.92:5555 -m -w 100
node2# ipvsadm -ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 192.168.100.99:5555 wrr
-> 192.168.100.91:5555 Masq 100 0 0
-> 192.168.100.92:5555 Masq 100 0 0
node2# iptables -t nat -A POSTROUTING -m ipvs --vaddr 192.168.100.99 --vport 5555 -j SNAT --to-source 192.168.100.92
Доступ к услуге теперь возможен при любом другом подключении (благодаря циклическому перебору). Чтобы быть точным, соединение успешно выполняется всякий раз, когда IPVS балансирует его на node1.
Раздел 9.3, Два блока LVS: оба директора имеют активные записи ipvsadm в LVS-HOWTO, объясняет проблему более подробно, а также предлагает обходной путь, применяя некоторые правила искажения Netfilter. Однако мне интересно, есть ли более простое и элегантное решение, потому что оно становится немного неудобным, если Kubernetes или другие сервисы со сложными настройками Netfilter/IPVS работают на одном хосте.