NetBox: заполненность подсети без Container и is_pool
АйТи Фреш
Linux, Docker и DevOps

Почему NetBox неправильно показывает заполненность подсети: когда нужны Container, is_pool и mark_utilized

Автор: , директор ООО «АйТи-Фреш» · · ~13 мин чтения
Иллюстрация: родительская подсеть NetBox показывает 0% заполненности, хотя дочерние сегменты заняты частично
Container и active по-разному считают заполненность — 0% не всегда значит «пусто»

Если родительская подсеть в NetBox показывает 0 % заполненности, хотя дочерние подсети выделены и частично заняты, — дело не в баге, а в статусе префикса: обычный (active) префикс считает заведённые в NetBox IP-адреса внутри своего диапазона и не видит дочерние префиксы как таковые, а долю пространства, нарезанного на дочерние подсети, показывает только статус container. Разбираю логику расчёта, зачем нужны is_pool и mark_utilized, и как я развожу эти три механизма в IPAM у клиентов.

Симптом: родительская подсеть висит на 0 %, хотя всё пространство расписано

Классическая ситуация после того, как в компании внедрили NetBox для учёта IT-инфраструктуры: в IPAM заводят крупную подсеть, например 10.20.0.0/24, режут её на несколько /26 или /27 под разные VLAN и сегменты, а сама родительская /24 в списке префиксов продолжает показывать 0 % utilization. Администратор проверяет — дочерние подсети на месте, часть адресов в них занята, а сводная цифра по «большой» подсети как будто не замечает вложенной структуры вовсе.

Первая реакция — счесть это багом отображения и полезть чинить кэш или пересчитывать что-нибудь вручную. На деле проблема почти всегда не в NetBox, а в том, что у родительской подсети не выставлен статус container: у обычного статуса (active, reserved, deprecated и других) есть чёткое правило подсчёта, которое просто не смотрит на дочерние префиксы, а считает только объекты IP-адресов в своём диапазоне. И если адреса в NetBox ещё не заводились — а на старте внедрения так почти всегда, сначала переносят префиксы, — то с точки зрения этого правила /24 действительно занята на 0 %, сколько бы подсетей в ней ни было нарезано.

Как на самом деле считается utilization: два разных правила для двух ролей префикса

В модели Prefix у NetBox статус container означает, что префикс существует именно как контейнер для организации дочерних подсетей, а не как сегмент с реальными адресами. И расчёт заполненности для него принципиально другой: container-префикс учитывает объём адресного пространства, «нарезанного» в дочерние префиксы, — независимо от того, насколько заняты сами эти дочерние подсети. Если внутри container-префикса 10.20.0.0/24 выделен дочерний 10.20.0.0/26, container покажет 25 % — ровно долю пространства, а не долю занятых IP-адресов в этой четверти, даже если в /26 занят один-единственный адрес или не занято ни одного.

Все остальные статусы префикса — active, reserved, deprecated — считают заполненность иначе и полностью игнорируют дочерние префиксы как объекты: в расчёт идут реально созданные объекты IP-адресов в диапазоне префикса (той же VRF) плюс диапазоны IPRange с флагом mark_utilized, которые засчитываются целиком, — относительно числа адресов в подсети. Важная тонкость: адрес, заведённый внутри дочерней /26, одновременно лежит и в диапазоне родительской /24, поэтому родитель в статусе active его тоже посчитает. Отсюда два разных сценария. Если адреса в дочерних подсетях заводятся как объекты, родитель в active покажет долю занятых адресов — например, 12 %, хотя всё пространство уже расписано по сегментам. Если адреса не заводятся вовсе (живут только в DHCP), родитель законно покажет 0 %. Ни в одном из случаев active-процент не отвечает на вопрос «сколько места осталось под новые подсети» — на него отвечает только container.

Разработчики NetBox явно подтверждали эту логику в обсуждении на GitHub: пользователь спрашивал, почему родительский префикс не отражает уровень заполненности вложенных подсетей, и получил ответ, что «активные» префиксы считают IP-адреса и не учитывают дочерние префиксы, а «контейнерные» — ровно наоборот, считают долю пространства, отданного в дочерние префиксы, вне зависимости от их собственной заполненности.

Схема: active-префикс считает только свои адреса, container-префикс считает долю пространства дочерних подсетей
0% у родительской подсети — это не баг, а active-статус, который не видит детей

Ловушка: container и active с одинаковым диапазоном одновременно

Есть ещё один частый источник «нулевых» процентов — когда в базе одновременно существуют container-префикс и active-префикс с абсолютно тем же диапазоном адресов (например, оба на 10.20.0.0/24, потому что кто-то завёл рабочую подсеть поверх контейнера, не заметив дубликата). В таком случае расчёт для container-префикса по умолчанию исключает из подсчёта дочерние префиксы, полностью совпадающие с ним по границам, — и итоговая цифра тоже может уйти в 0 %, хотя визуально кажется, что всё выделено.

В обсуждении на GitHub с похожим кейсом (когда container и active-префикс совпадали по диапазону) разработчики подтвердили именно эту механику исключения точных дублей из подсчёта и предложили обходной путь через кастомный фильтр запроса (сравнение net_contained_or_equal вместо net_contained), — но это уже вмешательство в код фильтрации, а не штатная настройка через интерфейс. В актуальном коде это видно напрямую: для container выбираются дочерние префиксы строго внутри его границ (net_contained), а равный по размеру в эту выборку не попадает. Проще и правильнее для админа — не заводить дубликат: если подсеть нужна одновременно и как административный контейнер, и как рабочий сегмент с адресами, для рабочего слоя создаётся именно дочерний префикс меньшего размера, а не второй префикс с идентичными границами.

Вторая похожая ловушка — VRF. Container считает только дочерние префиксы из той же VRF, что и он сам. Если родительская /16 заведена в глобальной таблице, а дочерние подсети филиалов разнесены по VRF (или наоборот), container покажет 0 % или заметно меньше реального, хотя дочерние префиксы видны в дереве по адресам. Я при разборе таких жалоб первым делом сравниваю столбец VRF у родителя и у детей: либо переношу родителя в ту же VRF, либо держу отдельный container на каждую VRF — второй вариант честнее, если адресные пространства VRF действительно пересекаются.

Совпадающие по диапазону container и active-префикс — почти всегда ошибка ввода, а не осознанная схема. NetBox исключает точный дубль из подсчёта заполненности контейнера, и цифра уходит в 0 % даже при формально занятом пространстве.

Что делают is_pool и IPRange.mark_utilized

Флаг is_pool у префикса решает другую задачу — не про иерархию, а про то, какие адреса внутри одной подсети вообще считаются занимаемыми. По умолчанию первый адрес подсети (сетевой) и последний (широковещательный) не участвуют в расчёте доступных адресов, как и положено по классике IP-адресации. Если включить is_pool, оба этих адреса становятся доступными для использования — NetBox сам явно указывает, что это годится для документирования пулов NAT, где крайние адреса диапазона реально назначаются устройствам, а не служат служебными границами подсети. На процент это тоже влияет: в актуальных версиях для IPv4-префикса без is_pool знаменатель — размер подсети минус два адреса (для /24 это 254), а с is_pool — полный размер (256). Для /31 и /32 все адреса считаются используемыми и без флага, для IPv6 знаменатель — полный размер префикса. Разница в пару процентов на маленьких подсетях как раз и объясняет, почему «одинаково заполненные» /28 с флагом и без показывают разные цифры.

IPRange — отдельная сущность для документирования произвольного диапазона адресов (например, части подсети, выделенной под DHCP-пул или NAT), и у него собственный флаг mark_utilized: если включить, диапазон при подсчёте заполненности родительского префикса будет считаться занятым на 100 % независимо от того, сколько конкретных IP-адресов реально создано внутри него как объекты. Без этого флага заполненность диапазона считается по фактически заведённым в нём адресам — и если вы просто зарезервировали диапазон под DHCP, но не завели в NetBox ни одного адреса из него как объект, IPRange честно покажет 0 %, даже если в реальности DHCP-сервер раздал из него половину адресов.

Таблица: как разные настройки NetBox — статус, is_pool, mark_utilized — влияют на расчёт заполненности подсети
Прежде чем читать процент как факт, проверьте, какое из шести правил его считало

Таблица: что учитывается в расчёте заполненности для каждой конфигурации

Собрал итоговую логику в одну таблицу — именно её я показываю клиентам, когда они впервые сталкиваются с «неправильными» процентами в IPAM:

КонфигурацияЧто учитывается в utilizationТипичный результат
Prefix, статус active/reserved, без IPRangeОбъекты IPAddress в диапазоне (включая лежащие в дочерних подсетях), дочерние префиксы — нет0 %, если адреса не заведены, даже при полностью нарезанном пространстве
Prefix, статус containerОбъём пространства, отданный под дочерние префиксы той же VRFДоля от размера родителя, не зависит от занятости детей
Prefix container + active с тем же диапазономТочный дубль по границам исключается из подсчётаМожет показать 0 % при визуально «полном» пространстве
Prefix с is_poolПервый и последний адрес подсети становятся доступнымиРасчёт доступных адресов включает сетевой и broadcast
IPRange без mark_utilizedДля родителя диапазон не засчитывается, считаются только созданные IPAddress0 %, если адреса не заведены как объекты, даже если выданы по DHCP
IPRange с mark_utilizedИгнорирует фактические адреса, диапазон = 100 %Заполненность родителя учитывает весь диапазон целиком
Prefix.mark_utilizedИгнорирует и адреса, и дочерние префиксыВсегда 100 %, ручной override администратора

Кейс «КнигоДом»: перенумерация склада из-за неверно прочитанного процента

У клиента — сеть книжных магазинов «КнигоДом», 29 рабочих мест в центральном офисе и на складе. При переносе учёта сети в NetBox завели крупную подсеть склада 10.30.4.0/23 в статусе active (по умолчанию при импорте из старой Excel-таблицы), а внутри неё уже руками нарезали пять рабочих /27 под кассовые терминалы, Wi-Fi точки, принт-серверы, видеонаблюдение и резерв. Сетевой инженер, планируя подключение нового участка сортировки, открыл список префиксов, увидел у родительской /23 честные 0 % и решил, что всё адресное пространство свободно. Отдельные IP-адреса в NetBox на тот момент ещё не заводили — из Excel импортировали только префиксы, адреса планировали перенести «следующим этапом».

Он начал выделять из той же /23 ещё один /26 под новый участок — и через несколько дней обнаружил пересечение с уже работающим диапазоном видеонаблюдения: два устройства получили одинаковые IP по DHCP-резервации, и часть камер на складе отвалилась в течение рабочего дня. Причина была ровно в статусе: родительская /23 в active не показывает занятость пространства дочерними /27, сколько бы их ни завели, а адресов-объектов в ней не было ни одного — 0 % в её карточке не значил «пусто», а значил «здесь не заведено ни одного IP и этот префикс не смотрит на детей».

Исправили за один вечер: поменяли статус родительской /23 на container, для диапазона DHCP камер завели отдельный IPRange с включённым mark_utilized (адреса раздаются по DHCP-резервации, а не заводятся в NetBox по одному), а для пула управляющих IP на коммутаторах, где реально используются крайние адреса подсети, включили is_pool. После этого родительский префикс стал честно показывать долю выделенного пространства, а не пустой 0 %, и повторной коллизии за два месяца эксплуатации не было.

Дерево решений: три типичных симптома неверной заполненности подсети в NetBox, их причины и действия по исправлению
Три самых частых ложных нуля в IPAM решаются тремя разными действиями, а не одной настройкой

Что я проверяю в IPAM, прежде чем доверять проценту заполненности

Правило, которое я завёл после нескольких похожих случаев у разных клиентов: прежде чем читать процент заполненности как факт, смотрю статус префикса. Если это иерархический уровень («сеть филиала», «весь адресный план склада») — статус только container, и точка; если это рабочий сегмент с реальными адресами устройств — active или другой рабочий статус, но тогда я слежу, чтобы адреса реально заводились в NetBox как объекты IPAddress, а не жили только в DHCP-логах, иначе процент всегда будет врать в меньшую сторону.

Для диапазонов DHCP и NAT-пулов сразу завожу IPRange с mark_utilized, а не жду, пока кто-то попробует выделить из «свободного» на вид пространства новый сегмент. И отдельно проверяю на дубликаты границ между container и active-префиксами — это самый неочевидный источник ложных нулей, который не лечится настройками интерфейса, только аккуратной структурой самого адресного плана. Если у вас в IPAM много legacy-подсетей без единой схемы статусов, начать стоит именно с ревизии — это тот же принцип, с которого я начинаю любую документацию IT-инфраструктуры в NetBox: какие префиксы должны быть иерархией, а какие — рабочими сегментами, и уже под это раскладывать is_pool и mark_utilized, а не наоборот.

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

Почему родительская подсеть в NetBox показывает 0 %, хотя все дочерние подсети выделены?

Потому что расчёт заполненности зависит от статуса префикса. Обычные статусы (active, reserved и другие) считают только объекты IPAddress в своём диапазоне и игнорируют дочерние префиксы; если адреса ещё не заведены, выйдет 0 %. Чтобы родитель показывал долю выделенного пространства между детьми, ему нужен статус container — и дети в той же VRF.

Чем отличается заполненность container-префикса от обычного?

Container-префикс считает объём адресного пространства, отданного под дочерние префиксы той же VRF, независимо от заполненности самих детей: дочерний /26 внутри container /24 даёт 25 %. Обычный статус считает заведённые IP-адреса в своём диапазоне (включая лежащие в дочерних подсетях) и IPRange с mark_utilized, а сами дочерние префиксы не учитывает.

Что делает флаг is_pool у префикса?

Он делает первый (сетевой) и последний (широковещательный) адрес подсети доступными для использования вместо служебного резервирования. Подходит для документирования NAT-пулов, где эти крайние адреса реально назначаются устройствам.

Зачем нужен mark_utilized у IPRange, если можно просто завести все адреса вручную?

Mark_utilized заставляет NetBox считать диапазон занятым на 100 % без создания отдельного объекта IPAddress на каждый адрес — удобно для DHCP-пулов и NAT, где адреса выдаются динамически и заводить их по одному нецелесообразно. Без этого флага заполненность диапазона считается только по фактически созданным объектам адресов.

Может ли утилизация показать 0 %, даже если статус выставлен верно?

Да, если внутри базы одновременно существуют container-префикс и обычный префикс с абсолютно тем же диапазоном адресов — такой точный дубль по умолчанию исключается из подсчёта заполненности контейнера. Решение — не заводить второй префикс с идентичными границами, а использовать для рабочего слоя дочерний префикс меньшего размера.

Есть ли способ вручную зафиксировать 100 % заполненности префикса, не считая реальные адреса?

Да, поле Prefix.mark_utilized: если включить, префикс всегда будет показывать 100 % утилизации независимо от числа дочерних объектов или адресов внутри него — это ручной override для случаев, когда подсеть выведена из оборота, но формально ещё занята.

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

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

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

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

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

Источники

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