Мне нужно сбалансировать нагрузку UDP-трафика между несколькими «реальными серверами» и сделать это по-настоящему циклическим способом. Я начал с keepalived, но неожиданно обнаружил, что LVS рассматривает трафик UDP как «соединение» (что бы это ни было в терминах UDP ..). На практике это означает, что весь трафик от конкретного клиента все время идет на один и тот же «реальный сервер» (это большое дело, потому что некоторые клиенты могут генерировать такой объем трафика, что единственный бэкэнд будет перегружен) .
По-видимому, это ожидаемое поведение, тем не мение более поздние версии LVS имеют флаг "--ops", который заставляет LVS обходить вышеупомянутое поведение, так что каждая дейтаграмма UDP обрабатывается независимо (это то, что я хочу!). Но (всегда есть «но» ...) эта функциональность не предоставляется из keepalived.conf.
Есть ли какое-то решение, которое позволит мне
Очевидно, он должен быть основан на Linux. Циклический перебор DNS в любой форме здесь не будет работать, потому что клиенты не знают DNS.
P.S. Я собираюсь попробовать pulse / piranha, но, судя по документации, которую я собрал, видно, что он также не показывает флаг «--ops». Я также собираюсь дать пн попытаться (сделать пн проверьте бэкенды и добавьте / удалите реальные серверы, напрямую вызвав ipvsadm).
Требование было удовлетворено следующим образом:
Я установил более свежую версию ipvsadm (и ее модули ядра), которая поддерживает --ops
флаг (1.26). Поскольку keepalived не выставляет этот флаг в своем файле конфигурации, вы должны применить его вручную. К счастью, ты можешь это сделать после создается "виртуальная служба" (в терминах простого ipvsadm вы можете сначала ipvsam -A
виртуальный сервис без --ops
, а потом ipvsadm -E
это добавить один пакет планирования).
Поскольку keepalived создает виртуальную службу для вас, все, что вам нужно сделать, это отредактировать ее после ее создания, что происходит, когда для этого виртуального сервера набирается кворум (в основном, имеется достаточное количество рабочих реальных серверов). Вот как это выглядит в keepalived.conf
файл:
virtual_server <VIP> <VPORT> {
lb_algo rr
lb_kind NAT
protocol UDP
...
# Enable one-packet scheduling when quorum is gained
quorum_up "ipvsadm -E -u <VIP>:<VPORT> --ops -s rr"
... realserver definitions, etc ...
}
Это работает, но я столкнулся с рядом проблем (вроде) с этой настройкой:
quorum_up
казнят. Любые дейтаграммы, которым удастся пройти через директор в течение этого времени, создадут запись подключения в ipvsadm, и дальнейшие дейтаграммы с этого исходного хоста / порта будут застрять на том же реальном сервере. даже после --ops
флаг добавлен. Вы можете минимизировать вероятность этого, убедившись, что виртуальная служба никогда не удаляется после создания. Вы делаете это, указав inhibit_on_failure
в определениях вашего реального сервера, чтобы они не удалялись, когда соответствующий реальный сервер не работает (когда все реальные серверы удаляются, виртуальная служба также удаляется), но вместо этого их вес равен нулю (тогда они перестают получать трафик). В результате дейтаграммы могут проскочить только во время запуска keepalived (при условии, что в это время у вас есть хотя бы один реальный сервер, так что кворум будет получен немедленно).--ops
активен, директор не перезаписывает исходный хост / порт дейтаграмм, которые реальные серверы отправляют клиентам, поэтому исходный хост / порт - это тот хост / порт реального сервера, который отправил эту конкретную дейтаграмму. Это могло быть проблемой (это было для мой клиентов). Вы можете исправить это, SNAT
'обрабатываем датаграммы с помощью iptables.--ops
. По-видимому, проблема в том, что алгоритм диспетчеризации пакетов запускается для каждой дейтаграммы, а не только для первой дейтаграммы в «соединении» (если это даже применимо к UDP ...). На самом деле я не нашел способа «исправить» это, но, возможно, я недостаточно старался. Система предъявляет определенные требования к нагрузке, и при такой нагрузке использование процессора не исчерпывается; нет и потерянных датаграмм, поэтому эта проблема не считается преградой. Однако это все еще вызывает тревогу.Резюме: установка определенно работает (также под нагрузкой), но обручи, которые нужно преодолеть, и проблемы, с которыми я столкнулся (особенно №3 .. может кто-то знает решение?), Означают, что со временем я бы » я использовал программу пользовательского пространства (написанную, вероятно, на C) для прослушивания UDP-сокета и распределения полученных датаграмм между реальными серверами, в сочетании с чем-то, что проверяет работоспособность реальных серверов для меня, SNAT
в iptables, чтобы перезаписать исходный хост / порт и поддерживать активность в режиме VRRP для HA.
Должен быть способ сделать это с помощью многопутевой маршрутизации ....
Балансировщик нагрузки и реальный сервер используют общие IP-адреса в подсети (10.0.0 / 24). Для обоих реальных серверов вы добавляете один и тот же IP-адрес из другой подсети в качестве вторичного для интерфейса обратной связи (172.16.1.1/32). Именно по этому адресу будет прислушиваться ваша служба.
+-------------------------------------+
+----|A: eth0:10.0.0.2/24 lo:172.16.1.1/32 |
+--------------------+ | +-------------------------------------+
|LB eth0:10.0.0.1/24 |---|
+--------------------+ | +-------------------------------------+
+----|B: eth0:10.0.0.3/24 lo:172.16.1.1/32 |
+-------------------------------------+
а затем вы можете использовать:
ip route add 172.16.1.1/32 nexthop via 10.0.0.2 nexthop via 10.0.0.3
Но пока что хорошие новости: очевидно, последние ядра Linux будут кэшировать маршруты, так что пакеты из одного источника по-прежнему будут попадать в один и тот же пункт назначения. Есть несколько патчей для отключения этого поведения, но все они, похоже, предназначены для старых ядер (например, патч выравнивания многопутевого кода для ядра 2.4, mpath в 2.6). Может быть, более тщательный поиск поможет найти рабочий патч для последнего ядра.
Аварийное переключение можно легко реализовать, запустив CARP как для 10.0.0.2, так и для 10.0.0.3. Таким образом, B берет на себя 10.0.0.2, когда A выходит из строя.