Как добавить несколько одинаковых сетевых модулей в NetBox, чтобы интерфейсы не конфликтовали по имени
Ставите второй такой же сетевой модуль в 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» из первого — если вы явно не скажете системе, откуда брать разницу. Дальше в статье — откуда её брать и как это выглядит в реальном шаблоне.
Из чего состоит модульность в NetBox: ModuleType, Module, ModuleBay
Три сущности, которые тут задействованы, разделены по смыслу. ModuleType — это шаблон: описание конкретной модели платы, карты расширения или трансивера с набором шаблонов компонентов (интерфейсов, портов питания, консольных портов), которые должны появиться при установке. ModuleBay — это отсек на устройстве или в другом модуле, физическое место, куда модуль устанавливается; у отсека есть имя, опциональная метка и поле position — позиция, которая используется именно для различения одинаковых отсеков между собой. Module — это уже установленный в конкретный ModuleBay экземпляр ModuleType.
Когда вы устанавливаете Module в ModuleBay, NetBox проходит по всем шаблонам компонентов из ModuleType и создаёт на устройстве реальные объекты — интерфейсы, консольные порты, порты питания — по этим шаблонам. Если в имени шаблона нет ничего, что зависит от того, в какой именно отсек попал модуль, все установки одного ModuleType сгенерируют абсолютно одинаковые имена, и вторая установка неизбежно столкнётся с первой на уровне уникальности имени интерфейса на устройстве.
Это разделение полезно держать в голове и при планировании закупок: один ModuleType в каталоге NetBox описывает модель железа один раз, вне зависимости от того, сколько экземпляров вы физически купите и в какие отсеки поставите. Ошибка в дизайне на этом уровне — задать имя компонента без учёта будущей множественности — не видна, пока в проекте установлен один экземпляр модуля; она проявляется ровно в момент, когда кто-то устанавливает второй, и чаще всего это происходит не при первичном проектировании, а спустя месяцы, при расширении.
Плейсхолдер {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, без перевода одной нумерации в другую.
Как я развёл конфликт у «Экран за час»
«Экран за час» — сеть точек ремонта экранов, 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}, а не чинить каждую следующую установку руками.
Вложенные отсеки и свой разделитель в номере
Отдельный случай — когда сам модуль тоже содержит отсеки под дочерние модули, например плата расширения с собственными разъёмами под трансиверы. По документации {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: второй позволяет «усыновить» уже существующие на устройстве интерфейсы с совпадающими именами вместо создания новых, и это спасает, когда интерфейсы заводили вручную до появления модуля.
Почему для трансиверов вообще стоит переходить с 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 несуществующий порт во время аварии.
- ModuleBay.position — осмысленная и совпадает с маркировкой слота на железе, не пустая.
- В имени шаблона компонента есть {module}, если тип модуля может быть установлен больше одного раза.
- Пример из документации: Gi{module}/0/[1-48], position=3 → Gi3/0/1…Gi3/0/48.
- Вложенные отсеки: {module}/1, {module}-1, {module}.1 — разделитель произвольный, унаследованная позиция обязательна.
- Для трансиверов и «умных» плат — Module, а не Inventory Item: связь с интерфейсом остаётся автоматической.
Частые вопросы
Почему второй одинаковый модуль в 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 такой связи не имеет и держится только на ручной дисциплине именования.
Что проверить перед тиражированием шаблона на прод?
Установить второй экземпляр модуля в тестовом окружении и убедиться, что имена компонентов различаются и совпадают с реальной маркировкой слотов на оборудовании.
Источники
- NetBox Labs Docs — Module Types — Механика плейсхолдера {module} (подстановка position ModuleBay), пример Gi{module}/0/[1-48] → Gi3/0/[1-48], вложенные отсеки {module}/1 с произвольным разделителем: https://docs.netbox.dev/en/stable/models/dcim/moduletype/
- NetBox Labs Docs — Module Bays — Поля ModuleBay (name, label, position), назначение position как признака различения отсеков: https://netboxlabs.com/docs/netbox/models/dcim/modulebay/
- GitHub Discussion #15051 — Several similar modules in a server/device — Сценарий с тремя одинаковыми PCIe-адаптерами по два SFP28-порта, ошибка «Interface - SFP28 Port 1 already exists», решение через {module} в шаблоне имени: https://github.com/netbox-community/netbox/discussions/15051
- NetBox Labs Blog — Moving SFP Modeling from Inventory Items to Modules — Причины перехода с Inventory Item на Module для трансиверов: автоматическая связь модуль↔интерфейс, обновление при замене: https://netboxlabs.com/blog/sfp-modeling-modules-over-inventory-items/
- NetBox Release Notes — v4.6 — #19796 — поддержка наследования позиции {module} для вложенных отсеков (v4.6.0, 2026-05-05); ранние исправления #19918 (v4.4) и #20467 (v4.5): https://netboxlabs.com/docs/netbox/release-notes/version-4.6/



