NetBox: конфликт имён интерфейсов при одинаковых модулях
АйТи Фреш
Linux, Docker и DevOps

Как добавить несколько одинаковых сетевых модулей в NetBox, чтобы интерфейсы не конфликтовали по имени

Автор: , директор ООО «АйТи-Фреш» · · ~13 мин чтения
Два одинаковых сетевых модуля в соседних слотах сервера — конфликт имён интерфейсов и его устранение подстановкой позиции
Одинаковые модули — не проблема, если имя интерфейса знает, в каком они слоте.

Ставите второй такой же сетевой модуль в NetBox — получаете «Interface - SFP28 Port 1 already exists» вместо готовых портов. Проблема не в модуле, а в шаблоне имени интерфейса: без подстановки позиции NetBox честно пытается создать два объекта с одинаковым именем. Показываю, как работает плейсхолдер {module} и как я развёл это клиенту с 13 рабочими местами.

Симптом: «Interface already exists» при установке второго модуля

Ошибка всплывает всегда в один и тот же момент: первый модуль устанавливается в отсек без вопросов, интерфейсы создаются, всё красиво. Второй модуль того же типа — и NetBox отказывает с текстом вроде «Interface - SFP28 Port 1 already exists». Первая реакция почти у всех одинаковая: создать для второго слота отдельный ModuleType с другими именами портов, скопировав первый и поправив цифры. Работает, но плодит дубли типов ради того, что на самом деле решается одной настройкой шаблона — этим я обычно и начинаю разговор, когда веду внедрение NetBox с DCIM-частью, где оборудование модульное.

Причина в том, что имя интерфейса в шаблоне компонента ModuleType задаётся один раз и без подстановки будет буквально одинаковым при каждой установке этого типа модуля — хоть в первый отсек, хоть в пятый. NetBox не умеет угадывать, что «SFP28 Port 1» из второго модуля должен как-то отличаться от «SFP28 Port 1» из первого — если вы явно не скажете системе, откуда брать разницу. Дальше в статье — откуда её брать и как это выглядит в реальном шаблоне.

«Interface already exists» при установке второго одинакового модуля — это не баг, а шаблон имени без подстановки позиции отсека.

Из чего состоит модульность в NetBox: ModuleType, Module, ModuleBay

Три сущности, которые тут задействованы, разделены по смыслу. ModuleType — это шаблон: описание конкретной модели платы, карты расширения или трансивера с набором шаблонов компонентов (интерфейсов, портов питания, консольных портов), которые должны появиться при установке. ModuleBay — это отсек на устройстве или в другом модуле, физическое место, куда модуль устанавливается; у отсека есть имя, опциональная метка и поле position — позиция, которая используется именно для различения одинаковых отсеков между собой. Module — это уже установленный в конкретный ModuleBay экземпляр ModuleType.

Когда вы устанавливаете Module в ModuleBay, NetBox проходит по всем шаблонам компонентов из ModuleType и создаёт на устройстве реальные объекты — интерфейсы, консольные порты, порты питания — по этим шаблонам. Если в имени шаблона нет ничего, что зависит от того, в какой именно отсек попал модуль, все установки одного ModuleType сгенерируют абсолютно одинаковые имена, и вторая установка неизбежно столкнётся с первой на уровне уникальности имени интерфейса на устройстве.

Это разделение полезно держать в голове и при планировании закупок: один ModuleType в каталоге NetBox описывает модель железа один раз, вне зависимости от того, сколько экземпляров вы физически купите и в какие отсеки поставите. Ошибка в дизайне на этом уровне — задать имя компонента без учёта будущей множественности — не видна, пока в проекте установлен один экземпляр модуля; она проявляется ровно в момент, когда кто-то устанавливает второй, и чаще всего это происходит не при первичном проектировании, а спустя месяцы, при расширении.

Схема связей ModuleType, ModuleBay и Module в модели данных NetBox DCIM
Имя компонента создаётся из шаблона ModuleType в момент установки Module в конкретный ModuleBay.

Плейсхолдер {module}: как шаблон превращается в реальные имена портов

Решение — плейсхолдер {module} в имени шаблона компонента. По документации он ссылается на поле position того ModuleBay, в который устанавливается экземпляр модуля, и подставляется в это место при генерации имени. Официальный пример из документации: шаблон интерфейса Gi{module}/0/[1-48] при установке модуля в отсек с position, равным «3», разворачивается в набор интерфейсов Gi3/0/1…Gi3/0/48. Квадратные скобки здесь — стандартный синтаксис диапазона в шаблонах именования NetBox, а {module} — именно то место, куда встаёт номер слота.

Отсюда и рецепт для конфликта имён: вместо SFP28 Port [1-2] в шаблоне интерфейса ModuleType пишем SFP28 Port {module}/[1-2] (или любой другой разделитель, который читается на вашем оборудовании). Тогда модуль в отсеке с position «1» даёт SFP28 Port 1/1 и SFP28 Port 1/2, а тот же тип модуля в отсеке с position «2» — SFP28 Port 2/1 и SFP28 Port 2/2. Имена больше не пересекаются, потому что они больше не одинаковые — они честно отражают, в какой физический слот встал модуль.

Важная деталь, о которую спотыкаются: position отсека — это не автонумерация по порядку добавления записей в интерфейсе, а значение, которое вы задаёте сами при создании ModuleBay (или ModuleBayTemplate у типа устройства). Если отсеки на реальном оборудовании подписаны, например, «SLOT1», «SLOT2», логично и position делать таким же читаемым — тогда {module} в имени интерфейса даст результат, который сразу узнаётся и на фото шасси, и в NetBox, без перевода одной нумерации в другую.

Сравнение шаблона имени интерфейса NetBox до и после добавления плейсхолдера {module}
Одна подстановка {module} в шаблоне убирает конфликт для любого числа одинаковых модулей.

Как я развёл конфликт у «Экран за час»

«Экран за час» — сеть точек ремонта экранов, 13 рабочих мест, где мы ведём документацию инфраструктуры в NetBox с прошлого года. Один физический сервер под 1С и файловый ресурс, подключённый к двум разным провайдерам для отказоустойчивости. Резервирование канала реализовано через два одинаковых двухпортовых сетевых адаптера в соседних PCIe-слотах сервера — типовая история, почти буквально повторяющая пример из обсуждения на GitHub, где у пользователя было три одинаковых PCIe-адаптера по два SFP28-порта и та же ошибка «Interface already exists» при установке второго.

Изначально коллега на месте завёл в NetBox один ModuleType на адаптер с шаблоном интерфейсов SFP28 Port [1-2] — для первого слота всё создалось, для второго прилетела ошибка. Я поправил шаблон компонентов на SFP28 Port {module}/[1-2], задал двум ModuleBay на device type позиции «1» и «2» по номерам PCIe-слотов на сервере, и переустановил модули — оба, без конфликта: SFP28 Port 1/1, SFP28 Port 1/2 для первого адаптера и SFP28 Port 2/1, SFP28 Port 2/2 для второго. Одна правка шаблона вместо второго ModuleType с переписанными вручную именами.

Итог для клиента практический: когда через полгода добавили третий адаптер под подключение видеорегистратора отдельным каналом, третий модуль встал в NetBox без единой ручной правки — просто новый ModuleBay с position «3», и шаблон сам развернул SFP28 Port 3/1, SFP28 Port 3/2. Именно ради этого стоит один раз аккуратно спроектировать шаблон с {module}, а не чинить каждую следующую установку руками.

Итоги внедрения резервного канала связи с SFP28-адаптерами в NetBox для сети Экран за час, 13 рабочих мест
Третий адаптер встал в схему без единой ручной правки шаблона — ради этого и делается {module} сразу правильно.

Вложенные отсеки и свой разделитель в номере

Отдельный случай — когда сам модуль тоже содержит отсеки под дочерние модули, например плата расширения с собственными разъёмами под трансиверы. По документации {module} можно использовать и в поле position шаблонов вложенных отсеков (официально это оформлено в NetBox 4.6.0 от 5 мая 2026 года, задача #19796; на 4.4–4.5 поведение дорабатывалось исправлениями #19918 и #20467, так что на старых версиях проверьте результат на тестовом устройстве), чтобы унаследовать позицию родительского отсека: если дочерние позиции заданы как {module}/1, {module}/2, а родительский модуль стоит в отсеке с position «3», они развернутся в 3/1, 3/2. Разделитель при этом полностью на усмотрение инженера — {module}-1 даст 3-1, {module}.1 даст 3.1, и никакой из вариантов не «правильнее» другого, кроме как с точки зрения того, что читаемо на конкретном оборудовании.

На практике до такой многоуровневой вложенности доходит не в каждом проекте — у большинства клиентов масштаба «Экран за час» достаточно одного уровня модулей на устройстве. Но правило то же самое: если в шаблоне позиции нет плейсхолдера, а отсеков несколько, NetBox рано или поздно создаст два объекта с одинаковым именем, и найти это в шаблоне проще заранее, чем разгребать по факту установки в проде.

И отдельная ловушка, на которую я сам наступал: исправление шаблона в ModuleType не переименовывает интерфейсы у модулей, которые уже установлены. Компоненты создаются по шаблону один раз — в момент установки модуля, — и дальше живут своей жизнью. Поэтому после правки шаблона старые экземпляры модулей надо переустановить: удалить Module и создать заново в том же ModuleBay. Удаление модуля удаляет и его компоненты, а с ними теряются подключения кабелей и назначения IP-адресов на этих интерфейсах, так что на живом устройстве я сначала выгружаю список подключений. В форме создания модуля есть два флажка — Replicate components и Adopt components: второй позволяет «усыновить» уже существующие на устройстве интерфейсы с совпадающими именами вместо создания новых, и это спасает, когда интерфейсы заводили вручную до появления модуля.

Правка шаблона ModuleType действует только на новые установки. Уже установленные модули сохраняют старые имена интерфейсов, пока вы их не переустановите.

Почему для трансиверов вообще стоит переходить с Inventory Item на Module

До появления полноценной модульности многие документировали SFP-трансиверы через Inventory Item — по сути отдельную инвентарную запись без автоматической связи с интерфейсом. По материалам блога NetBox Labs, такой подход изначально был вынужденным обходным путём: между записью трансивера и интерфейсом не было автоматической связи, и всё держалось на дисциплине именования, а не на логике системы. Итог знаком многим: трансивер физически переставили в другой порт, а инвентарная запись осталась привязана к старому — расхождение всплывает не сразу, а на следующем аудите. Причём это не абстрактная теория: у клиентов размера «Экран за час» именно так когда-то и вели учёт — блокнотом и парой инвентарных записей «на будущее», которые за год ни разу не сверяли с реальным железом.

Модуль устроен иначе: устанавливаете Module в ModuleBay — соответствующий интерфейс появляется по шаблону автоматически; меняете модуль — связанные компоненты обновляются вместе с ним. Это не только удобнее в моменте, но и правильнее методологически: система сама знает, что стоит физически, а не полагается на то, что кто-то не забыл переименовать инвентарную запись. При этом ничего не мешает совмещать Module для «умных» плат и Inventory Item — там, где действительно нужна просто инвентарная запись без собственных компонентов, например для блока питания без отдельных портов.

Чек-лист: проектируем шаблон модуля без будущих конфликтов

Перед тем как заводить ModuleType для оборудования, где отсеков больше одного, я прохожу по короткому списку. Во-первых, у каждого ModuleBay на device type должна быть осмысленная position — не пустая и не случайная, а совпадающая с тем, как промаркированы слоты на реальном железе. Во-вторых, в каждом шаблоне компонента, который создаётся при установке модуля (интерфейсы, порты питания, консольные порты), проверяю, что имя содержит {module}, если этот ModuleType когда-либо может быть установлен больше одного раза на устройство — а для сетевых карт и трансиверов это почти всегда так.

В-третьих, для многоуровневых конструкций — модуль с собственными отсеками под дочерние модули — задаю position дочерних шаблонов через {module} с разделителем, который однозначно читается: слэш для «слот/порт», дефис или точка, если так исторически подписано на оборудовании у клиента. И последнее: один раз проверяю результат на тестовой установке второго экземпляра модуля в песочнице, прежде чем тиражировать шаблон на прод — это дешевле, чем находить конфликт имён на живом устройстве во время работ.

После того как имена интерфейсов стабилизировались, я сверяю их с тем, что видит мониторинг. Там, где стоит мониторинг на Zabbix 7, низкоуровневое обнаружение берёт имена интерфейсов с самого железа по SNMP (ifName/ifDescr), а не из NetBox. Поэтому простая сверка «имена портов в NetBox против обнаруженных Zabbix» сразу показывает, где шаблон с {module} или position отсека не совпали с тем, как порты называет прошивка, — и это видно до того, как кто-то начнёт искать в NetBox несуществующий порт во время аварии.

Один ModuleType с {module} в имени интерфейса переживёт любое число установок. Отдельный ModuleType на каждый слот — это ручная синхронизация, которая рано или поздно разойдётся с реальностью.

Частые вопросы

Почему второй одинаковый модуль в NetBox выдаёт «Interface already exists»?

Потому что в шаблоне имени интерфейса ModuleType нет ничего, что зависит от отсека установки — оба модуля пытаются создать интерфейс с абсолютно одинаковым именем на одном устройстве.

Что делает плейсхолдер {module} в шаблоне компонента?

Подставляет значение поля position того ModuleBay, в который устанавливается модуль. Пример из документации: Gi{module}/0/[1-48] при позиции «3» разворачивается в Gi3/0/1…Gi3/0/48.

Нужно ли заводить отдельный ModuleType под каждый слот?

Нет, и в этом весь смысл {module} — один ModuleType с подстановкой позиции обслуживает любое число установок без дублирования типов и ручной синхронизации имён.

Как быть, если модуль сам содержит отсеки под дочерние модули?

{module} можно указывать и в поле position шаблонов вложенных отсеков — тогда дочерняя позиция наследует позицию родительского отсека с любым разделителем: {module}/1, {module}-1 или {module}.1. Официально механизм оформлен в NetBox 4.6.0; на более старых версиях проверьте результат на тестовом устройстве.

Чем Module лучше Inventory Item для SFP-трансиверов?

Module даёт автоматическую связь с интерфейсом: установили — компонент появился, заменили — обновился вместе с модулем. Inventory Item такой связи не имеет и держится только на ручной дисциплине именования.

Что проверить перед тиражированием шаблона на прод?

Установить второй экземпляр модуля в тестовом окружении и убедиться, что имена компонентов различаются и совпадают с реальной маркировкой слотов на оборудовании.

Столкнулись с похожей задачей? Обращайтесь — решим

Если у вас происходит что-то из описанного в этой статье — или любая другая проблема с ИТ-инфраструктурой, — обращайтесь в любое время. Мои специалисты и я лично разберём ситуацию, найдём настоящую причину и доведём до решения.

Возьмёмся и за разовую задачу, и за постоянное обслуживание. Первичная консультация — бесплатно и без обязательств.

📞 +7 903 729-62-41 ✈ Telegram @ITfresh_Boss

С уважением, Семёнов Евгений Сергеевич, директор «АйТи Фреш» — IT-аутсорсинг для компаний до 50 рабочих мест, 15+ лет практики

Источники

© ООО «АйТи-Фреш» · Москва · Все статьи