Товарищ
klink0v в своём
посте писал про то, как нам Corosync сеть положил.
Спустя два месяца мне удалось ходу-бедно собрать этот кластер и сеть уже полторы недели не падает.
Напомню вводные.
У нас 29 нод, соединённые через кластер из двух коммутаторов Juniper. Каждая нода подключена двумя гигабитными линками к этому кластеру из свитчей. По линку в каждый свитч. Из линков собран LACP. Дальше этот объединённый линк нарезается на VLAN'ы и в одном из этих VLAN'ов живёт кластер corosync, в других VLAN'ах бегает в том числе и полезный прод. трафик.
Сам коросинк версий с 3.0.4 по 3.1.5. На разных нодых версии разные.
Сетевые карты: на части нод Broadcom BCM5719, на другой части Intel X722.
Коросинк никак не тюнили, как и сетевую подсистему.
Сам кластер коросинка используется в составе кластера Proxmox.
Собственно, во всех инструкциях на сайте Проксмокса говорится, что нет никаких ограничений на количество нод в кластере.
В итоге кластер в середине декабря прошлого года принял свой окончательным вид, т.е. в него были добавлены все 29 нод, и он успешно работал до примерно середины января.
На протяжении этого почти месяца были один или два раза какие-то странные сообщения от системы мониторинга, но они были кратковременные и единичные, плюс новогодние каникулы. В общем, списали на "космические лучи".
В день X ближе к вечеру начали сыпаться уведомления от системы мониторинга об отваливании прод. сервисов. Эти триггеры зажигались беспорядочно, на короткое время, буквально на период одного опроса метрики и поначалу относительно редко. Постепенно, часам к 2 или 3 ночи это приняло массовый характер, что обратило, наконец, на себя внимание админов.
Т.е. деградация не была резкой, она была плавной на протяжении 6-8 часов.
В ходе мучительной шестичасовой диагностики удалось выяснить, что Corosync генерирует по 300 мегабит/c входящего и столько же исходящего UDP траффика на каждой ноде. Пока он так делает, свитч сообщает о том, что линки этих нод падают и тут же поднимаются назад. Т.к. все ноды подключены двумя проводами, то не всегда ноды становятся недоступны. Вероятно, именно из-за этого и не было резкой деградации.
В итоге, на всех нодах был жёстко убит демон коросинка и сеть вернулась в рабочее состояние, флапы линков прекратились.
Дальше были длительные разборки, что с этим делать.
Пробовали заменить свитч на Cisco Catalyst 9200 - не помогло.
Копание в сторону коросинка показало, что разработчики Proxmox ещё те "суслики". В одной из веток форума (сейчас уже лень искать) они написали, что не рекомендуют кластеры больше 15, что ли, нод. А то, что у них есть пример кластера на 52 ноды, так там народ дико тюнил и сетку и коросинк. И этот пример единственный.
Но подавляющее большинство обсуждений проблем с коросинком сводится к тому, что у народа рассыпается кластер. В нашем же случае, хрен бы с этим кластером, пусть он вообще весь развалится. Нафига и почему флапают линки?
Решили попробовать вынести Corosync в отдельную физическую сеть. Выделили отдельный гигабитный свитч под это дело, подключили в него отдельные сетевые карты, по рекомендациям, подняли в этой сети MTU до 9000. Сеть полностью изолированная от остального мира. Никаких VLAN тегов, и т.к. кластер не сильно критичный, то и никаких LACP.
Так же, в ходе анализа траффика коросинка удалось выяснить, что львиную долю трафика создаёт механизм PMTUD, который раз в 30 секунд с каждой ноды в сторону каждого соседа отправляет фрагментированный пакет размером почти 64КБ. Уж не знаю, зачем оно это делает так часто, неужели у кого-то МТУ в сети меняется каждые 30 секунд? У нас такого нет, потому увеличил период PMTUD до 24 часов.
Попытка собрать кластер не увенчалась успехом. От части из-за того, что на паре нод я забыл убрать правила фаервола, которые блокировали фрагментированные SCTP пакеты (артефакты экспериментов).
Но больше расстроило не то, что кластер не собрался, а то, что снова начали флапать прод. линки. И вот этого в тот момент мы никак не ожидали.
В итоге, пришлось изучать пару статей про то, как работает сетевая подсистема Линукса на низком уровне:
- Приём данных
- Отправка данных
Не знаю, имеет ли смысл пересказывать эти статьи. Может быть, когда-нибудь и напишу по этому поводу что-нить. Хотя бы для себя, чтобы чуть лучше упорядочить полученные знания.
У нас же картина была следующая.
Большое количество дропнутых пакетов на отправку в выводе:
tc -s qdisc show dev eno1
На нодах с сетевыми карточками Broadcom были включены по 4 аппаратных очереди на приём и по одной на отправку. Кольцевые буферы карточек были выставлены и на приём и на передачу по 256 байт (?). Сами очереди от одной карточки и от разных были распределены по разным ядрам процессора.
На нодах с сетевыми карточками Intel аппаратных комбинированных очередей было по количеству ядер процессора для каждой карты. Т.е. если в сервере 40 ядер ЦПУ, то у каждой карты было по 40 очередей. И очереди каждой карты были распределены по всем ядрам. В итоге, каждое процессорное ядро обрабатывало по одной очереди с каждой сетевой карты.
XPS не использовался.
Очередь планировщика на отправку была стандартной и равнялась 1000.
Моя теория заключается в том, что corosync создавал такой поток трафика, что ядру попросту не хватало NAPI бюджета все это дело обработать. Плюс, у интеловских карт все сетевые карты делили этот бюджет между собой, т.к. обрабатывались на одних и тех же ядрах. А у броадкомовских была всего одна очередь на отправку. Всё это приводило к тому, что ядро не успевало вовремя отправлять LACP кадры.
Сделал следующее:
- Увеличил бюджет NAPI и приоритет Polling'а. Вместе с остальными рекомендациями для corosync файл с настройками ядра выглядит вот так:
net.core.wmem_max = 12582912
net.core.rmem_max = 12582912
net.ipv4.tcp_rmem = 10240 87380 12582912
net.ipv4.tcp_wmem = 10240 87380 12582912
net.core.netdev_max_backlog = 5000
net.sctp.association_max_retrans = 100
net.sctp.path_max_retrans = 50
net.core.dev_weight = 192
net.core.netdev_budget = 500 - На картах Broadcom увеличил количество очередей на отправку до четырёх (больше сделать нельзя)
- На картах Broadcom увеличил размер кольцевых буферов на приём и отправку до максимальных 2011 и 511 соответственно
- На картах Intel уменьшил количество очередей до 10. Т.к. карт у нас по 4 в сервере, а ядер 40 или больше, это позволило разнести обработку очередей по разным ядрам, и больше они не "пересекаются"
- На картах Intel увеличил размер кольцевых буферов до максимальных 4096
- Задействовал XPS и разнёс эти очереди по соответствующим ядрам процессора, чтобы они совпадали с соответствующей аппаратной очередью
- Увеличил очереди планировщика отправки до 3000
- В целях максимального снижения лишнего трафика, выключил на интерфейсах, задействованных в кластере corosync, IPv6. На свитче включил перманентное сохранение таблицы мак адресов, и на хостах перманентно прописал соответствение MAC-IP. Всё это позволило полностью исключить ARP трафик.
- Конфиг corosync принял следующий вид (описание нод опустил):
totem {
cluster_name: Proxmox
config_version: 55
interface {
linknumber: 0
knet_transport: sctp
}
token: 10000
join: 150
send_join: 20
token_retransmits_before_loss_const: 10
ip_version: ipv4
link_mode: passive
secauth: on
version: 2
knet_pmtud_interval: 86400
knet_compression_model: lz4
knet_ping_timeout: 45000
knet_ping_interval: 5000
knet_pong_count: 1
}
В итоге кластер собрался. Ведёт себя стабильно. Единственное, иногда в логах corosync возникают единичные ретрансмиты. С ними пока думаю, что делать, но главное, теперь не падает прод. сеть.
Возможно, часть из проделанного лишнее, но продолжать тестировать на проде как-то не хочется.