NetBox Circuits: канал провайдера через один наш порт
АйТи Фреш
Сети и VPN

Как описать канал провайдера в NetBox, если известен только наш порт, а оборудование оператора недоступно

Автор: , директор ООО «АйТи-Фреш» · · ~15 мин чтения
Кабель провайдера уходит в туман — известен только свой порт, оборудование оператора не видно, как в NetBox Circuit
Наш конец канала виден полностью, дальний — законно остаётся в тумане: NetBox для этого не требует выдумывать устройство.

Классический тупик при заведении канала провайдера в NetBox: наш конец — известный порт на свитче, а что там у оператора за оборудование — коммутатор, медиаконвертер или вообще безымянная точка в облаке MPLS — неизвестно и, как правило, не наше дело. Показываю, что Circuit в NetBox официально поддерживает одностороннее описание, когда реально использовать ProviderNetwork, а когда просто оставить Z-сторону пустой.

Симптом: администратор пытается придумать несуществующее устройство провайдера

Заявка от трастовой компании «КапиталХранитель» (18 рабочих мест) пришла с формулировкой «неправильно заводим провайдеров в NetBox». У клиента два магистральных канала — основной оптический ввод и резервный через другого оператора — оба заведены в NetBox как объекты Site и Device, а вот дальше администратор застрял: чтобы протянуть кабель от своего пограничного маршрутизатора до чего-то на другом конце, интерфейс редактирования кабеля требовал указать второе устройство. Пришлось заводить фиктивный Device с именем вроде «ISP-router-unknown», без реальных данных — просто чтобы кабель к чему-то подключился. Через полгода в базе висели два таких «призрачных» устройства с почти одинаковыми именами, и новый инженер уже не мог сказать, какое из них к какому реальному каналу относится. Мы разворачиваем и донастраиваем NetBox для учёта инфраструктуры как раз с прицелом на такие грабли — раздел Circuits в NetBox для этого спроектирован отдельно от Devices и Cables, и выдумывать оборудование провайдера в нём не нужно.

Смешение двух разных сущностей — это и есть корень проблемы. Кабель (Cable) в NetBox соединяет два физических порта, которые оба принадлежат вам и видны в инвентаре: патч-панель, интерфейс коммутатора, разъём на медиаконвертере. Канал провайдера (Circuit) — это принципиально другая модель: она описывает не физический кабель между двумя вашими портами, а услугу связи, которую вы покупаете у оператора, и у которой вы видите только свой конец. Пытаться натянуть Circuit на модель Cable — и есть причина, по которой администратор начинает придумывать несуществующие маршрутизаторы провайдера.

Что такое Circuit и CircuitTermination: A/Z-окончания

Circuit в официальной документации NetBox определён как «a physical point-to-point data connection, typically used to interconnect sites» — физическое соединение точка-точка, обычно используемое для связи между площадками. У объекта Circuit есть провайдер (Provider), идентификатор канала у этого провайдера (Circuit ID, уникальный в рамках провайдера), тип (интернет, MPLS/VPN и так далее), статус (по умолчанию Planned, Provisioning, Active, Offline, Deprovisioning, Decommissioned; список можно расширить через FIELD_CHOICES), даты ввода и отключения, коммит-скорость (commit rate) в кбит/с и опциональное расстояние между концами с единицей измерения.

Сами точки подключения канала описываются отдельной моделью — CircuitTermination, и у одного Circuit их может быть не более двух: сторона A и сторона Z. Это жёсткое ограничение модели, а не рекомендация — большего числа окончаний у одного Circuit создать нельзя. У CircuitTermination, помимо стороны (term_side), есть поле port_speed (скорость интерфейса в кбит/с), отдельное поле upstream_speed — если скорость асимметричная, как у кабельного модема, xconnect_id — идентификатор кросс-коннекта в дата-центре, mark_connected — булев флаг «считать подключённым» без требования реального кабеля, поле «Patch Panel & Port(s)» — чтобы записать патч-панель и порт на кроссе, не моделируя их отдельно, и связь cable — если этот конец канала физически подключён кабелем к вашему оборудованию.

Ключевое поле — termination: начиная с NetBox 4.2 (релиз 4.2.0 вышел 6 января 2025 года, issue #9604) это единый generic foreign key, который может указывать на Region, SiteGroup, Site, Location или ProviderNetwork. До 4.2 у CircuitTermination было два отдельных поля — site и provider_network, и это разделение создавало путаницу с тем, какое из них заполнять. Объединение в одно поле termination — не косметика: оно явно фиксирует, что сторона канала может быть либо точкой в вашей топологии (сайт, площадка, регион), либо абстрактной сетью провайдера — но это одно и то же по смыслу поле, просто с разным типом ссылки.

Схема модели Circuit в NetBox: сторона A всегда наш порт, сторона Z может быть пустой, сайтом или ProviderNetwork
У Circuit не более двух окончаний, и сторона Z законно может остаться незаполненной.

Главный ответ: Circuit с одной стороной — законный, задокументированный паттерн

Прямой ответ на вопрос «что делать, если известен только наш порт»: заводить только А-сторону CircuitTermination, а Z-сторону не заполнять вообще. Это не хак и не обход ограничений интерфейса — участник обсуждения на GitHub (discussion #17402 в основном репозитории netbox-community/netbox) сформулировал это предельно ясно: «You can have a circuit with a termination at one end but not the other» — можно иметь канал с окончанием на одном конце, но не на другом. Формы создания Circuit и CircuitTermination в NetBox не требуют обязательного заполнения обеих сторон — вы вводите провайдера, Circuit ID, тип и статус канала, затем создаёте ровно одну CircuitTermination на стороне A, привязанную к вашему Site (и, если нужно, к конкретному интерфейсу через Cable), и на этом можно остановиться.

В том же обсуждении другой участник, который сам работает в ISP и активно использует Circuits для кросс-коннектов в ЦОД, DSL и сотовых каналов, сделал важную оговорку: «they're billable items and procured from a provider» — то есть Circuit — это услуга, купленная у оператора, у них есть коммерческая сторона (счета, SLA, договор), которая никак не связана с физическим устройством на том конце. NetBox сознательно не требует описывать инфраструктуру оператора, потому что вы её не видите и не администрируете — и не должны пытаться её угадывать.

Второй вариант из того же обсуждения — использовать патч-панель (Device типа patch panel) как демаркационную точку, если у вас есть физическая точка сдачи-приёмки (кросс-коннект в дата-центре, распределительный щиток), где кабель провайдера физически подключается к вашей инфраструктуре. Это не альтернатива Circuit, а дополнение: сам канал по-прежнему описывается объектом Circuit с одной или двумя терминациями, а патч-панель — это устройство, к которому физически подходит кабель на вашей стороне, если такая точка у вас реально есть и вы её обслуживаете.

Практическая причина, почему это решение не выглядит очевидным с первого взгляда: интерфейс создания кабеля (Cable) в NetBox действительно просит указать оба конца, и по инерции кажется, что то же самое требование распространяется на Circuit целиком. Но Circuit и Cable — независимые сущности с разными правилами заполнения. Cable обязательно соединяет две реально существующие конечные точки, потому что кабель физически существует с двух сторон. CircuitTermination же можно создать в одном экземпляре, и уже к ней, если нужно, привязать Cable до вашего физического порта — при этом сама модель Circuit ничего не требует от второй стороны, потому что вторая сторона физически может быть вам вообще не видна.

Не нужно создавать фиктивный Device «за оператора» только ради того, чтобы протянуть кабель. Если второй конец канала не ваш — заводите только сторону A у CircuitTermination и оставляйте Z пустой. Это штатное, задокументированное поведение модели Circuit.
Дерево решений: что указать на стороне Z CircuitTermination в NetBox — пусто, Site или ProviderNetwork
ProviderNetwork нужен не всегда — только когда в одну и ту же сеть провайдера сходится несколько ваших каналов.

Когда всё же нужен ProviderNetwork

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

У модели ProviderNetwork три содержательных поля: Provider — привязка к оператору, ответственному за эту сеть, Name — уникальное в рамках провайдера человекочитаемое имя (например «Ростелеком MPLS Москва»), и Service ID — произвольный идентификатор, используемый как альтернативная ссылка на тип связности (может совпадать с внутренним кодом услуги у провайдера, а может быть придуман вами для удобства). Ничего похожего на модель устройства с интерфейсами — ProviderNetwork описывает именно сеть как единую точку, а не набор портов.

Разница между «оставить Z пустым» и «завести ProviderNetwork» — это разница между «неизвестно и не нужно» и «известно, но нам это не устройство, а сеть». Если у вас один канал в конкретную региональную MPLS-сеть провайдера и вы вряд ли когда-нибудь заведёте туда второй канал — можно обойтись и без ProviderNetwork, просто оставив Z-сторону незаполненной, разница на практике будет чисто декларативной. Но если у вас пять каналов от разных площадок сходятся в одну и ту же MPLS-сеть одного провайдера, ProviderNetwork стоит завести один раз и подключить к нему все пять CircuitTermination стороной Z — тогда в NetBox сразу видно, какие каналы логически связаны общей точкой провайдера, и при аварии в этой сети вы одним запросом поднимаете все пострадавшие каналы — та же логика, что я закладываю при настройке резервного канала с автоматическим переключением: сначала понять зависимость каналов друг от друга, потом уже настраивать реакцию на аварию.

Кейс «КапиталХранитель»: как я перезавёл два канала

У «КапиталХранителя» было два канала — основной оптический интернет-ввод от одного провайдера и резервный канал с автопереключением от другого, оба заведены как Circuit с фиктивными Device на стороне Z, придуманными администратором «для полноты картины». Первым шагом я удалил обе фиктивные записи устройств вместе с фиктивными кабелями к ним и пересобрал CircuitTermination заново: сторона A для обоих каналов — конкретные интерфейсы на пограничном маршрутизаторе клиента, привязанные Cable к реальным портам, сторона Z — не заполнена вообще, потому что ни один из двух провайдеров не был MPLS-сетью с несколькими подключениями клиента, просто два обычных интернет-ввода без видимости на инфраструктуру оператора.

Отдельно уточнил у клиента по договорам оба Circuit ID — у основного провайдера это оказался буквенно-цифровой номер договора вида «INET-2024-0847», у резервного — внутренний код услуги, который раньше просто не был записан нигде, кроме бумажного счёта. Занёс оба значения в поле Circuit ID, заполнил commit rate по факту тарифа (100 Мбит/с и 50 Мбит/с) и проставил статус Active обоим. Отдельно завёл третий Circuit — тестовый канал до дата-центра, где клиент арендует стойку под резервный сервер: этот канал реально приходит в MPLS-сеть провайдера дата-центра, к которой в перспективе подключится ещё один офис клиента с отдельным VLAN под серверный сегмент, поэтому для него я завёл ProviderNetwork «MPLS <провайдер ЦОД>, Москва» и привязал к нему сторону Z.

Вся работа заняла около трёх часов: час на разбор существующей путаницы с фиктивными устройствами и сверку договоров, час на пересборку двух простых каналов без Z-стороны, и час на третий канал с ProviderNetwork, включая проверку через API, что оба типа терминации (пустая Z и Z с ProviderNetwork) корректно отображаются в топологии. После этого в базе осталось ровно три объекта Circuit, ноль фиктивных устройств провайдеров и один ProviderNetwork, к которому в будущем можно будет добавлять новые каналы без пересборки существующих.

Чек-лист перенастройки трёх каналов провайдера в NetBox на кейсе компании КапиталХранитель, 18 рабочих мест
После пересборки в базе остались только реальные объекты — ни одного придуманного устройства провайдера.

Ограничения модели, о которые легко споткнуться

Первое: физический Circuit нельзя завершить на LAG-интерфейсе (агрегированном канале). Документация CircuitTermination прямо ограничивает физическое подключение только реальным физическим интерфейсом, исключая виртуальные типы вроде LAG. Если у вас на площадке два физических канала от одного провайдера объединены в агрегацию на вашей стороне, в NetBox это моделируется как два отдельных Circuit, каждый со своей физической CircuitTermination на отдельный физический интерфейс — а сама агрегация описывается уже на уровне интерфейсов устройства (LAG-интерфейс, к которому привязаны оба физических), а не на уровне Circuit. Пытаться привязать Cable от CircuitTermination напрямую к виртуальному LAG-интерфейсу система не позволит.

Второе: для топологий с несколькими точками подключения к одному каналу (не путать с двумя сторонами A/Z одного канала) документация рекомендует моделировать каждую ветку («leg») отдельным Circuit, где один конец обычно приходит в инфраструктуру провайдера — то есть многоточечные конфигурации вроде MPLS с несколькими подключёнными офисами превращаются в набор двухсторонних Circuit, у каждого из которых Z-сторона — это один и тот же ProviderNetwork. Именно для этого случая ProviderNetwork и существует: он даёт общую точку сборки для набора формально независимых объектов Circuit.

Третье, менее очевидное: raw-модель NetBox не проверяет коммерческую логику — она не запретит вам создать Circuit без единой CircuitTermination вообще, просто такой канал будет виден только в списке Circuits и карточке провайдера, а трассировка кабеля (Trace) от вашего интерфейса до него не дойдёт. Если цель — не просто зафиксировать факт существования договора, а получить пользу от связей (трассировка от порта до канала при аварии, выгрузка через API для мониторинга), минимум одна CircuitTermination — сторона A на вашей стороне — обязательна.

И последнее по счёту, но не по значимости: поле port_speed у CircuitTermination — это скорость интерфейса, а не гарантированная провайдером полоса. Для этого у самого Circuit есть отдельное поле commit_rate — коммит-скорость по договору, обычно она меньше физической скорости порта (например, оптический порт на 1 Гбит/с при коммите 100 Мбит/с). Путать эти два поля — частая ошибка при первом заведении канала: администратор вписывает в commit_rate скорость интерфейса, и потом графики утилизации во внешнем мониторинге, который берёт полосу из NetBox, выглядят так, будто клиент использует канал на 10 % от ёмкости, хотя на деле упирается в честный коммит по договору.

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

Обязательно ли заполнять обе стороны Circuit — A и Z?

Нет. NetBox официально поддерживает Circuit с заполненной только стороной A — это подтверждено в обсуждении сообщества (discussion #17402): «можно иметь канал с окончанием на одном конце, но не на другом». Если дальний конец канала вам не виден и не принадлежит вам, Z-сторону можно оставить пустой.

Чем ProviderNetwork отличается от простого пустого Z-конца?

Пустой Z-конец означает «дальняя сторона неизвестна и неважна». ProviderNetwork — это когда дальняя сторона известна как сеть провайдера (например, региональная MPLS), но её внутреннее устройство неважно. ProviderNetwork имеет смысл заводить, когда к одной и той же сети провайдера подключено или будет подключено несколько ваших каналов — тогда это общая точка сборки для их всех.

Можно ли завершить Circuit на LAG-интерфейсе?

Нет, физическая CircuitTermination подключается кабелем только к физическому интерфейсу. Если несколько физических каналов от провайдера объединены агрегацией на вашей стороне, в NetBox каждый физический канал заводится отдельным Circuit на отдельный физический интерфейс, а агрегация описывается на уровне LAG-интерфейса устройства, не на уровне Circuit.

Нужно ли заводить фиктивное устройство провайдера, чтобы протянуть кабель до канала?

Нет, и делать так не стоит — это и есть типичная ошибка, которую разбирает статья. Cable в NetBox соединяет ваш физический порт непосредственно с CircuitTermination, без необходимости в промежуточном фиктивном устройстве на стороне провайдера.

С какой версии NetBox поле termination заменило site и provider_network у CircuitTermination?

С версии 4.2, вышедшей 6 января 2025 года. До этого у CircuitTermination было два отдельных foreign key поля — site и provider_network; их объединили в единое generic foreign key поле termination, которое может ссылаться на Region, SiteGroup, Site, Location или ProviderNetwork.

Что делать, если у нас есть физическая демаркационная точка — патч-панель в дата-центре?

Патч-панель заводится как отдельный Device (с фронтальными и тыльными портами) на вашей стороне, а сам канал провайдера по-прежнему описывается объектом Circuit. Если моделировать кросс не нужно, у CircuitTermination есть поля Cross-connect ID и Patch Panel & Port(s) — в них достаточно записать номер кросс-коннекта и порт.

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

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

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

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

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

Источники

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