Вопрос или проблема
В последнее время у меня были проблемы с сетью (работаю на Debian, но это не связано с какой-либо дистрибуцией, см. ниже использование прямого манипулирования /sys), и я обнаружил, что причиной моих бед было то, что два сервера с объединенными сетевыми интерфейсами имели одинаковый аппаратный адрес на их связях. Этот MAC-адрес НЕ является одним из адресов аппаратных интерфейсов, хотя должен быть (согласно большинству документаций, таких как эта):
Интерфейс объединения имеет аппаратный адрес 00:00:00:00:00:00 до тех пор, пока не будет добавлен первый подчиненный. Если интерфейс VLAN создается до первого подчиненного, он возьмет полностью нулевой аппаратный адрес. После добавления первого подчиненного интерфейс объединения возьмет аппаратный адрес подчиненного, который станет доступен для устройства VLAN.
Более того, вопреки утверждению в этой документации, “пустое” объединение (без каких-либо подчиненных) не имеет аппаратного адреса 00:00:00:00:00:
# modprobe bonding
# echo +bond0 > /sys/class/net/bonding_masters
# ip link show bond0
3: bond0: <BROADCAST,MULTICAST,MASTER> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether d6:f5:8e:9f:c2:42 brd ff:ff:ff:ff:ff:ff
Однако этот аппаратный адрес изменяется на адрес подчиненного если и только если подчиненный добавляется непосредственно к объединению и адрес объединения не проверяется. Я тестирую с помощью очень простого скрипта (см. ниже) для манипулирования объединением.
- Сначала создается пустое объединение без подчиненных и отображается его аппаратный адрес (который по-видимому псевдослучайный, но имеет тенденцию оставаться неизменным — возможно, здесь играет роль udev?).
- Во-вторых, создается объединение, устанавливается его режим и добавляется подчиненный: объединение принимает аппаратный адрес подчиненного, как и ожидалось.
- В-третьих, создается объединение, считывается его аппаратный адрес, затем устанавливается режим и добавляется подчиненный: аппаратный адрес объединения не совпадает с аппаратным адресом подчиненного (но, выполняя скрипт снова и снова, время от времени он совпадает! попробуй догадаться).
- В-четвертых, создается объединение, ждет одну секунду, затем настраивается как в шаге 2. Поведение в основном такое же, как в шаге 3: объединение имеет тот же псевдослучайный аппаратный адрес, что и в шаге 1, который всегда отличается от аппаратного адреса подчиненного и всегда тот же самый.
Я точно не знаю, как настраивается псевдо-случайный аппаратный адрес объединения, но он оказывается относительно повторяющимся на нескольких аппаратных и программных конфигурациях (разное оборудование, разные версии ядра, разные релизы Debian).
Иногда, на шаге 3, MAC-адрес объединения изменяется на другие псевдо-случайные значения, иногда совпадает с адресом подчиненного. Однако, в большинстве случаев, он остается тем же, что и в шаге 1.
На шаге 4 MAC-адрес объединения всегда тот же, что и на шаге один.
Похоже, что настройка MAC-адреса объединения очень чувствительна ко времени?
Вот скрипт:
echo "unload / load bonding"
rmmod bonding
sleep 1
modprobe bonding
sleep 1
echo "create bond0"
echo +bond0 > /sys/class/net/bonding_masters
echo "bond0 hw address, no slaves:"
cat /sys/class/net/bond0/address
sleep 3
echo "################"
echo "unload / load bonding"
rmmod bonding
sleep 1
modprobe bonding
sleep 1
echo "create bond0 and configure it without delay"
echo +bond0 > /sys/class/net/bonding_masters
# cat /sys/class/net/bond0/address
echo 6 > /sys/class/net/bond0/bonding/mode
echo +enp1s0 > /sys/class/net/bond0/bonding/slaves
echo "Bond0 hw address:"
cat /sys/class/net/bond0/address
echo "enp1s0 hw address:"
ethtool -P enp1s0
echo "################"
sleep 3
echo "unload / load bonding"
rmmod bonding
sleep 1
modprobe bonding
sleep 1
echo "create bond0 and configure it, read its hw address first"
echo +bond0 > /sys/class/net/bonding_masters
cat /sys/class/net/bond0/address
echo 6 > /sys/class/net/bond0/bonding/mode
echo +enp1s0 > /sys/class/net/bond0/bonding/slaves
echo "Bond0 hw address:"
cat /sys/class/net/bond0/address
echo "enp1s0 hw address:"
ethtool -P enp1s0
echo "################"
sleep 3
echo "unload / load bonding"
rmmod bonding
sleep 1
modprobe bonding
sleep 1
echo "create bond0 and configure it after 1 second delay"
echo +bond0 > /sys/class/net/bonding_masters
# cat /sys/class/net/bond0/address
echo 6 > /sys/class/net/bond0/bonding/mode
sleep 1
echo +enp1s0 > /sys/class/net/bond0/bonding/slaves
echo "Bond0 hw address:"
cat /sys/class/net/bond0/address
echo "enp1s0 hw address:"
ethtool -P enp1s0
А вот его вывод:
unload / load bonding
create bond0
bond0 hw address, no slaves:
ea:dc:34:e6:7c:8d
################
unload / load bonding
create bond0 and configure it without delay
Bond0 hw address:
52:54:00:c8:76:09
enp1s0 hw address:
Permanent address: 52:54:00:c8:76:09
################
unload / load bonding
create bond0 and configure it, read its hw address first
d6:f5:8e:9f:c2:42
Bond0 hw address:
d6:f5:8e:9f:c2:42
enp1s0 hw address:
Permanent address: 52:54:00:c8:76:09
################
unload / load bonding
create bond0 and configure it after 1 second delay
Bond0 hw address:
d6:f5:8e:9f:c2:42
enp1s0 hw address:
Permanent address: 52:54:00:c8:76:09
Время от времени аппаратный адрес объединения изменяется на какое-то другое значение. Однако, чаще всего он возвращается к тому же самому (здесь “d6:f5:8e:9f:c2:42”) и, кажется, циклически перемещается по ограниченному числу MAC-адресов в течение перезагрузок.
Однако очень серьезной проблемой является то, что разные машины заканчивают с одним и тем же псевдослучайным аппаратным адресом; когда они подключены к одному и тому же сетевому коммутатору, наступает хаос. Фактически, проверяя среди нескольких разных машин, подключенных к различным сетям, по крайней мере, 4 имеют один и тот же MAC-адрес соединения (хотя, пока они не подключены вместе к одному коммутатору, это в основном безвредно).
Заметьте, что в этом случае я настроил соединение в режиме 6, но у меня была проблема на машине, работающей в режиме 4 (802.3ad) и других режимах. Это, кажется, не связано с режимом объединения – изменение режима на 1, 2 или 4 не меняет MAC-адрес.
Конечно, я мог бы принудительно задать MAC-адрес объединения на значение с помощью скрипта if-up.d или чего-то подобного, но я предпочел бы что-то, что работает из коробки 🙂
В течение некоторого времени имелись проблемы с MAC-адресами, используемыми в объединении Linux (режим 4); в прошлом использовался MAC первого интерфейса в объединении, что было нормально, когда новый активный агрегат определялся только при полном отказе/отключении активного агрегата.
Все изменилось, когда код был изменен для выбора нового активного агрегата при каждом изменении на объединенных интерфейсах, что позволило выбирать агрегат с наибольшей пропускной способностью/числом ссылок/и т. д. при каждом изменении.
И здесь начинаются проблемы; представьте следующее:
- объединение с 8 интерфейсами, работающее на 2 равных агрегатах через 2 простых коммутатора, где агрегат 1 (eth0/3) активен, а агрегат 2 (eth4/7) пассивен/не используется, и объединение/агрегат несет MAC первого интерфейса (eth0) в объединении.
- eth3 отключается, и агрегат 2 становится активным, перенося MAC объединения (=eth0).
Все было в порядке на активном агрегате 1, но после переключения на агрегат 2, eth0 все еще подключено с собственным MAC-адресом, и агрегат 2 также использует этот MAC на другом переключателе! Это потому, что (режим 4/802.3ad/lacp) держит их подключенными/контролирует изменения состояния, что приводит к потере пакетов на уровне около 20% и более…
Я наблюдал это на многих местах и даже с устройствами, такими как NetApp Filers, и в итоге обычно устанавливаю MAC для связи на частный MAC-адрес на основе MAC-адреса eth0, просто заменяя первый октет на 02
:
root@kc-host-01:~# ethtool -P eth0
Permanent address: 34:1a:4c:03:a0:95
root@kc-host-01:~# cat /etc/network/interfaces
auto lo
iface lo inet loopback
auto eth0
iface eth0 inet manual
auto eth1
iface eth1 inet manual
auto eth2
iface eth2 inet manual
auto eth3
iface eth3 inet manual
...
auto bond0
iface bond0 inet manual
bond-slaves eth0 eth1
bond-miimon 100
bond-mode 802.3ad
bond-xmit-hash-policy layer2+3
bond-downdelay 200
bond-updelay 200
up ip link set dev bond0 address 02:1a:4c:03:a0:95
auto vmbr0
iface vmbr0 inet static
address 192.168.100.253/24
gateway 192.168.100.254
bridge-ports bond0
bridge-stp off
bridge-fd 0
...
Таким образом, MAC-адрес на объединении уникален и отслеживаем/связан с фактически используемым оборудованием.
Я заметил, что некоторые дистрибуции недавно начали автоматически использовать/устанавливать частные MAC-адреса для объединенных интерфейсов, но я предпочитаю держать это под своим контролем…
.
Ответ или решение
Проблема с MAC-адресами и агрегацией каналов (bonding) на Linux-серверах — это достаточно частая и сложная ситуация, требующая глубокого понимания механизма работы сетей и конфигурации. Вопрос заключается в том, что два сервера имеют агрегацию каналов с одинаковым MAC-адресом, что вызывает проблемы в работе сети.
Теория
В сети, идентификация устройств происходит через MAC-адреса, и каждый интерфейс должен иметь уникальный MAC-адрес. В контексте "bonding" интерфейсов, который объединяет несколько физических сетевых интерфейсов в один логический интерфейс для увеличения пропускной способности или обеспечения отказоустойчивости, выбор MAC-адреса является критически важным.
Согласно документации, пока в "бонд" не добавлены слейвы, у агрегированного интерфейса должен быть адрес 00:00:00:00:00:00. После добавления первого слейва, переагрегированному интерфейсу присваивается MAC-адрес этого слейва, что становится доступным для VLAN-интерфейсов. Однако в реальной практике, как описывается в рассматриваемой ситуации, поведение системы может отличаться.
Пример
Ваша ситуация заключается в следующем: вы заметили, что адреса, назначаемые агрегированным интерфейсам, носят "псевдослучайный" характер, что приводит к дублированию MAC-адресов на разных машинах, особенно когда они подключены к одному коммутатору, вызывая сетевой хаос. Как было продемонстрировано на примере скрипта, созданного для тестирования, существует явный разрыв между ожидаемым поведением системы и её фактической работой. Когда MAC-адрес бонда читается до добавления слейва, или если происходит задержка в конфигурировании, система иногда сохраняет "псевдослучайный" адрес вместо ожидаемого.
Ваша ситуация также осложнена особенностями режима агрегации 802.3ad, где проблема сохранения MAC-адреса усугубляется при изменениях в состояниях каналов из-за выбора новой активной агрегации.
Применение
Чтобы обойти эти сложности, есть несколько подходов, которые могут помочь в решении этой проблемы:
-
Явное задание MAC-адреса: Хотя это и не автоматическое решение, это один из надежных способов избежать дублирования адресов. Вы можете заранее определить уникальный MAC-адрес для бонда на основании физического MAC-адреса одного из слейвов, заменяя первый октет на ’02’, что делает адрес "приватным" согласно стандарту IEEE. Например, для адреса 34:1a:4c:03:a0:95, задайте 02:1a:4c:03:a0:95 для интерфейса bond0.
-
Настройка через инициализационные скрипты: Включите контроль над установлением MAC-адресов в конфигурационных файлах системы, например, в ‘/etc/network/interfaces’. Это позволяет автоматизировать процесс при каждом запуске системы.
-
Муниципальные инструменты проверки и ограничений: Используйте инструменты управления конфигурацией для обеспечения соответствия всех сетевых настройках на уровне предприятия. Это помогает в отслеживании и управлении уникальностью MAC-адресов в сети.
-
Обновление документации и кода: Независимо от временных решений, важно уведомить разработчиков о данной проблеме через каналы получения поддержки от разработчиков или сообществ, чтобы в будущем такие ситуации могли быть проработаны на уровне кода ядра и документации.
Решение такой задачи требует времени и терпения, но с вниманием к деталям и точной настройкой ваших систем вы сможете минимизировать или устранить сетевые конфликты, вызванные MAC-адресами при агрегации интерфейсов. Это поддержит более стабильную и предсказуемую работу вашей сетевой инфраструктуры.