Я пытаюсь глубоко понять, как работает пересылка от публично выставленных VIP-пользователей уровня 2 балансировщика нагрузки к IP-адресам кластеров служб. Я прочитал общий обзор того, как MetalLB делает это , и я попытался скопировать его вручную, установив keepalived / ucarp VIP и правила iptables. Я должен что-то упустить, однако это не работает; -]
Шаги, которые я предпринял:
создал кластер с kubeadm
состоящий из мастера + 3 узла, работающих под управлением k8s-1.17.2 + calico-3.12 на виртуальных машинах libvirt / KVM на одном компьютере. все виртуальные машины находятся в 192.168.122.0/24
виртуальной сети.
создал простое развертывание с двумя модулями и выставил его как сервис NodePort
с externalTrafficPolicy
, установленным на cluster
:
$ kubectl get svc dump-request
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
dump-request NodePort 10.100.234.120 <none> 80:32292/TCP 65s
Я подтвердил что я могу связаться с ним с хост-машины по IP-адресу каждого узла на порту 32292.
создал VIP с ucarp
на всех 3 узлах:
ucarp -i ens3 -s 192.168.122.21 -k 21 -a 192.168.122.71 -v 71 -x 71 -p dump -z -n -u /usr/local/sbin/vip-up.sh -d /usr/local/sbin/vip-down.sh
(пример из knode1)
Я подтвердил, что могу пинговать 192.168.122.71
VIP. Я даже мог sh пройти через него к виртуальной машине, которая в настоящее время удерживала VIP.
Теперь, если бы kube-proxy находился в режиме iptables
, я мог бы также получить доступ к сервису через его узел-порт через VIP в http://192.168.122.71:32292
. Однако, к моему удивлению, в режиме ipvs
это всегда приводило к тайм-ауту соединения.
добавило правило iptables на каждом узле для пакетов, входящих на 192.168.122.71
, для пересылки на IP-адрес службы * 10.100.234.120
:
iptables -t nat -A PREROUTING -d 192.168.122.71 -j DNAT --to-destination 10.100.234.120
(позже я также попытался сузить правило только до соответствующего порта, но это никак не изменило результаты:
iptables -t nat -A PREROUTING -d 192.168.122.71 -p tcp --dport 80 -j DNAT --to-destination 10.100.234.120:80
)
Результаты:
в режиме iptables
все запросы к http://192.168.122.71:80/
привели к тайм-ауту соединения.
в режиме ipvs
он работал частично:
, если 192.168.122.71
VIP удерживался узлом, на котором был установлен модуль, то около 50% запросов выполнялись успешно, и они были всегда подаются местными стручками. приложение также получало реальный удаленный IP-адрес хост-машины (192.168.122.1
). остальные 50% (по-видимому, отправленные в модуль на другом пыльнике) истекли.
если VIP удерживался узлом без модулей, тогда все запросы истекали.
Я также проверил, влияет ли это на результаты в любом случае, чтобы правило всегда сохранялось на всех узлах, а не на том, чтобы оно оставалось только на узле, содержащем VIP и удаляющем его при освобождении VIP: результаты были одинаковыми в обоих случаях.
Кто-нибудь знает, почему это не работает и как это исправить? Я буду признателен за помощь в этом:)