Проблема одновременного доступа к двум сетям – интересный случай из нашей практики

13.01.2023

Интересный кейс сетевого менеджмента без простого решения

Конфигурация

Есть ноды на базе Raspberry PI. Используя несущие платы, каждый узел имеет два порта Ethernet. Узлы подключены к двум коммутаторам одновременно. Каждый порт Ethernet в сети имеет уникальный MAC-адрес. А также его имеют свитчи. Таким образом, имея 16 устройств, каждое с двумя портами Ethernet и двумя кабелями, мы получаем 64 mac-адреса. Но мы также соединяем два коммутатора друг с другом кабелем Ethernet и подключаем собственный компьютер. Таким образом 68 mac адресов.

Каждый узел Linux содержит таблицу arp, в которой указано, какие другие mac-адреса могут быть доступны с каждого интерфейса Ethernet. В этом случае ВСЕ mac-адреса доступны с каждого порта Ethernet. Мы настроили два порта Ethernet на узле Linux в режиме объединения для получения одного единственного IP-адреса. Каждый узел Linux также содержит таблицу маршрутизации, таблица маршрутизации сообщает вам, как вы можете связаться со всеми другими IP-адресами в локальной сети.

Для связывания используется Linux Ethernet Bonding Driver. Если используется либо «miimon», либо arp_ip_target для определения того, активен ли данный локальный порт, это решение «все или ничего + глобальное», которое применяется ко всему трафику от узла, а не к трафику конкретно от узла 6 к узлу 9. В частности, из-за этого ограничения был добавлен кабель между коммутаторами, поэтому в настоящее время мы используем активное резервное копирование, как описано в топологии высокой доступности с несколькими коммутаторами. Это работает в различных случаях, так как даже если узел 6 использует неправильный порт + коммутатор, чтобы попытаться достичь узла 9, трафик перенаправляется через канал между коммутаторами. В идеальном мире у нас не было бы этого кабеля, чтобы избежать отказа одного коммутатора, влияющего на другой. Если связь между коммутаторами обрывается, она вообще не работает, т. е. одни узлы продолжают использовать коммутатор 1, а другие — коммутатор 2 (учитывая пункт 2 выше + как работает активное резервное копирование).

На самом деле текущая конфигурация использует один и тот же MAC-адрес для ведомых устройств. Это связано с тем, что для параметра связывающего драйвера «fail_over_mac» используется значение по умолчанию nonde/0. Bonding драйвер может это сделать, потому что для этой сетевой карты драйвер управляет MAC-адресом.

Проблема

Проблема в том, что таблица маршрутизации и таблицы arp обновляются недостаточно быстро, когда коммутатор не работает или кабель отключен. Наши узлы Linux отправляют пакеты друг другу 10 раз в секунду, а иногда и быстрее. Таким образом, стек TCP/IP должен менее чем за одну секунду обнаружить, что линк, который он использовал ранее, не работает, и он должен попробовать другой вариант. Но этого не происходит достаточно быстро по какой-то странной причине, которую мы не понимаем.

Используется настройка Linux, в которой два порта связаны таким образом, что оба имеют один и тот же IP-адрес. Как-то это работает. Трафик может идти по тому или иному линку. Если один линк не работает, будет использован другой, и наоборот. Но если узел 6 обычно отправляет через один порт на узел 9, то когда этот кабель отключается, узел 6 не может автоматически определить, что теперь ему нужно связаться с узлом 9 через другой порт. На самом деле я не знаю, проблема ли это в коммутаторе или таблице arp на каждом узле или фундаментальная проблема с функцией бондинга в Linux.

В конце концов, наша цель состоит в том, чтобы иметь систему, которая может продолжать работать, даже если в каком-либо сетевом компоненте есть единая точка отказа. Мы также хотим иметь возможность обнаруживать это и отправлять на сервер сообщение о том, где произошла ситуация единственной точки отказа.

Вот сценарий событий, если нет кабеля, соединяющего 2 коммутатора: 

  1. узел b имеет сбой в своем порту 2 (также может быть на стороне коммутатора или просто поврежденный кабель)

– узел a должен использовать свой порт 1 для доступа к узлу b: узел a-порт 1 -> коммутатор 1 -> узел b-порт 1)

  1. узел c имел сбой в своем порту 1 (также может быть на стороне коммутатора или просто поврежденный кабель)

– узел a должен использовать свой порт 2 для доступа к узлу c: узел a-порт 2->коммутатор 2 -> узел c-порт 2

  1. узел d неисправен

Моя текущая конфигурация бондинга не работает, когда события 1 и 2 происходят одновременно (не может решить использовать один порт для доступа к узлу b и другой порт для доступа к узлу c). Кроме того, если произойдет событие 3, конфигурация, которая выдержит события либо 1, либо 2, перестанет работать из-за события 3 (требуется, чтобы все узлы были доступны через один из портов коммутаторов).

Идеальная конфигурация будет работать без проблем, когда все 3 события активны одновременно. Если узел d вернется в рабочее состояние, он также сможет возобновить подключение. Кроме того, идеальная конфигурация выдержала бы следующий 4-й сценарий, который может и невозможен на практике:

  1. узел e имеет рабочие связи с обоими коммутаторами, но коммутатор 1 имеет внутренний сбой, когда трафик от/к узлу e может достичь только подмножества других узлов, которое не включает узел a

- узел а должен использовать свой порт 2 для доступа к узлу е

С кабелем между коммутаторами сценарии 1-3 одновременно работают нормально (поскольку неважно, какой порт использует узел а, он все равно может дотянуться до обоих узлов b и c). Однако, если связь между коммутаторами обрывается, они больше не работают. Даже если связь между коммутаторами работает, также не может быть разрешен сценарий 4.

Решение

Полного решения нет. Все тесты проводились в виртуальной среде из-за отсутствия реальных тестовых PI. Невозможно было точно и просто проверить связь между двумя виртуальными «PI» из-за ограничений виртуальной среды. Вариант с созданием веб-сервера и настройкой клиент-серверной модели на двух виртуальных «PI» не тестировался. Вместо этого были проведены тесты стабильности на виртуальных ethernet-портах «PI», в режиме соединения 3 (широковещательный), который показал себя как наиболее надежное решение. На данный момент рекомендуется использовать режим соединения 3, но нам нужны отзывы о том, как он работает на реальном оборудовании.

Без бондинга в режиме 3 между коммутаторами необходимо использовать межсоединение, это обязательно в соответствии с документацией по топологии высокой доступности с несколькими коммутаторами.