Много слов было сказано про концепцию Source of Truth в мире сетей, много копий сломано в дискуссиях о том, как лучше её реализовать. Кто-то голосует за Git, кто-то жить не может без Netbox, а кто-то по старинке хранит всё в Excel и собственной памяти. Мы же в Hoff Tech вот уже больше года активно используем Nautobot, и нам есть чем поделиться с теми, кого гложут мысли: «Так, Nautobot установил, где у него кнопка что делать дальше?» Статья рассчитана на тех, кто собирается заняться сетевой автоматизацией, начинает ей заниматься или делает это уже давно. Если же вы не в курсе про Nautobot, но почитать очень хочется, вот документация — тыц, а вот демонстрация — тыц. Nautobot — это форк Netbox, и, хотя с момента ветвления прошло достаточно много времени и интерфейсы сильно различаются, всё приведённое в статье можно применить и к Netbox. Сделай в тексте ниже :%s/Nautobot/Netbox/g, суть останется такой же. Статья обзорная: вы не найдёте в ней ни строчки кода (ну почти). Конкретные реализации приведённых практик будут сильно зависеть от окружения. Расскажу на примере Hoff Tech. У нас на обслуживании enterprise-сеть, в которой под сотню филиалов и свой ЦОД (не один). Больше тысячи виртуальных машин, десятки тысяч IP-адресов, разбитых по функциональным сегментам и бизнес-юнитам, сотни единиц оборудования (и сетевого, и просто подключённого к сети). А если компания динамично расширяется, в том числе и за счёт поглощения новых структур? Присоединяешь к себе большую слабодокументированную сетевую инфраструктуру и понимаешь: хорошо, что у нас информация о сети хранится в удобном виде, её и достать легко, и актуализировать, и использовать в процессах автоматизации. Но так было не всегда. Используемые префиксы и VLAN хранились в Excel, более-менее актуальный список маршрутизаторов/коммутаторов можно было найти только в inventory-файле ansible, а свободен или нет IP-адрес — мог проверить исключительно сетевик. Не удивительно, что в определённый момент количество сетевой информации начало влиять на её качество и актуальность. В общем, боль сетевого инженера как она есть. И тут нам на помощь пришла система документирования сети. IPAM или, если брать шире, самый настоящий Network Source of Truth Весь процесс установки подробно описан в официальной документации. Отмечу только то, что базу данных мы вынесли на отдельную виртуальную машину. В дальнейшем планируем поступить так же и с воркерами, которые обеспечивают работу внутренних скриптов автоматизации. Что касается ресурсов, в этом плане Nautobot совсем не требователен. PostgreSQL с базой данных крутится на виртуалке с двумя ядрами и 4Gb памяти. Всё остальное — фронтенд, бэкенд, воркеры, реверс-прокси, брокер — на виртуалке 4 ядра/4 гига. Этого хватает, чтобы открыть без каких-либо задержек страницу с IP-адресами, коих у нас в базе больше 50 тыс. штук. Сразу небольшой лайфхак. Для тестирования новых релизов и обучения приёмам работы с Nautobot мы подняли тестовый сервер, на который периодически переносим данные с продуктового. Чтобы пользователи случайно не перепутали сервера, логотип и favicon на тестовом сервере перекрасили из синего цвета в оранжевый. Теперь пользователю сразу понятно, в песочнице ли он и можно ли тренировать навыки удаления критически важных данных. Для контроля доступа в Nautobot целесообразно использовать учетные данные корпоративного домена. В случае использования ADFS вам потребуется самостоятельно разработать плагин, например, на базе модуля django-adfs. Гораздо проще внедрить решения, аналогичные  Keycloak или Authelia, с ними не будет проблем. Во этом случае интеграция займет не более часа на чтение документации и правку конфигурационных файлов. Итак, Nautobot установлен и доступен, пришла пора наполнить его жизнью. Официальная документация гласит, что Nautobot — это в первую очередь Network Source of Truth. То есть логично, что первыми в нём поселились сетевые устройства: маршрутизаторы и коммутаторы. Конечно, никто и не помышлял вносить данные руками. В это интересное для сетевиков время практически каждый из нас умеет в Python, поэтому у нас быстренько родились несколько джобов, обеспечивающих процесс наполнения данными (jobs — скрипты на Python, запускаемые прямо из интерфейса Nautobot). AddDevices job. На входе получает список IP-адресов, тип устройства (коммутатор, роутер), платформу (Cisco IOS, Router OS, etc.) и сайт, к которому относятся добавляемые устройства. Джоб по SSH подключается к каждому девайсу из списка, парсит вывод show-команд и вносит структурированные данные в Nautubot. В результате получаем заполненные префиксы, вланы, устройства с интерфейсами и адресами. Этот джоб мы используем при появлении в сети новых устройств. Небольшой лайфхак номер два. Перед добавлением новых устройств мы максимально заполнили используемые нами модели устройств (device_type). Данные взяли с https://github.com/netbox-community/devicetype-library. Теперь у каждого нового девайса всегда будут правильные набор портов и данные по электропотреблению, которые наследуются при создании от выбранного device type. CheckDevices job. Проходит по всем сетевым устройствам и сравнивает информацию, хранящуюся в Nautobot (адреса интерфейсов, описания портов, разрешённые VLAN, etc.), с данными, полученными с девайса по SSH. Результаты работы джоба пушатся в git. Джоб регулярно выполняется по шедулеру и извещает сетевых инженеров об отличиях между ожидаемым и реальным состояниями устройства. SearchDevices job. Проходит по всем сетевым устройствам и обнаруживает соседние устройства, которые видны по CDP/LLDP, но о которых ещё нет данных в Nautobot. Результаты работы джоба пушатся в git. Джоб регулярно выполняется по шедулеру и извещает сетевых инженеров о девайсах, которые по какой-то причине не добавлены в Nautobot. UpdateDevices job. Проходит по всем сетевым устройствам и актуализирует данные в Nautobot в соответствии с реальным состоянием девайсов. Заодно джоб добавляет соединения между устройствами. Список обновляемых девайсов можно отфильтровать перед выполнением. GetConfigs job. Проходит по всем сетевым устройствам, получает с них running- и startup-конфигурации и пушит их в git. Джоб регулярно выполняется по шедулеру и позволяет в любой момент увидеть актуальную конфигурацию и всю историю изменений. Этот джоб заменил нам всем известные Rancid и Oxidized Все джобы используют под капотом модули scrapli и textfsm, под часть оборудования пришлось слегка адаптировать community-драйверы и подготовить собственные шаблоны textfsm. Общение с девайсами осуществляется по SSH, дополнительно рекомендую использовать asyncio, что может заметно уменьшить время работы джобов. Например, CheckDevices обходит все девайсы за пять минут, а это почти 800 единиц. При этом с каждого девайса он получает вывод в среднем шести команд, обрабатывает результаты и сравнивает с данными из Nautobot. Таким образом, в Nautobot у нас появилось точное отображение сетевого ландшафта. В одном месте теперь можно узнать, в каком сайте какой префикс используется, какие VLAN настроены на портах коммутаторов, как VLAN и префиксы связаны. Неплохим плюсом оказалась и информация о соединениях между коммутаторами. Эта стадия внедрения у каждого своя, к сожалению, универсального рецепта пока никто не придумал. У нас был развёрнут phpIPAM, из которого без особых усилий (2 модуля: phpypam и pynautobot, 1 вечер, 2 кружки кофе) были вытащены данные по статическим IP-адресам и серверным стойкам. Согласитесь, выполнять лишнюю работу никто не хочет, поэтому почему бы и не воспользоваться результатами чужого труда. При заполнении стоек, кстати, вскрылся один нюанс. Представьте себе стойку: Скрипт переноса вытащил данные по стойке из phpIPAM, создал необходимые типы устройств, серверные стойки. После этого добавил нужное количество устройств с названиями «панель коммутационная» и «организатор кабельный», разместил их в нужные юниты. Мы порадовались и забыли про эти элементы СКС. Ровно до того момента, когда кому-то из пользователей понадобилось добавить ещё одну коммутационную панель. Оказалось, имя устройства в Nautobot должно быть уникальным, и при сохранении изменений через веб-интерфейс он это проверил и выдал ошибку. Нумеровать все подобные устройства для уникальности — верх безумия. К счастью, Nautobot позволяет оставлять имя устройства пустым. Выглядит это так: Но в этой ложке мёда притаилась бочка дёгтя. Названия безымянных устройств в стойке выводятся как результат f"{self.device_type.manufacturer} {self.device_type.model} ({self.pk})", а это слишком длинно. Ну что же, пока ничего не остаётся, как править в коде Nautobot метод display() класса Device (совсем немножечко).  Для исправления ситуации мы после каждого обновления выполняем Небольшой лайфхак номер три. Не все изменения можно внести, используя Bulk edit в веб-интерфейсе. Для простых массовых действий мы часто используем nbshell. Например, для одноразовой очистки name у большого числа девайсов можно выполнить прямо в консоли следующую конструкцию: Не надо заморачиваться с подключением к API или импортом модулей. Среди прочего, в nbshell удобно смотреть справку по атрибутам и методам встроенных классов, используя стандартный help(). Знания о том, какие VLAN разрешены на портах коммутатора или в каком VRF и с каким адресом настроен интерфейс маршрутизатора, очень полезны. Но «что сетевику хорошо, обычному админу, может, и не нужно». Обычного админа (основного пользователя Nautobot) больше интересует, какой IP-адрес у принтера или камеры или из какого диапазона назначить статический адрес новому устройству. Часть этих вопросов мы закрыли, организовав регулярную синхронизацию данных в Nautobot с DHCP-серверами. DHCP у нас построен на базе Microsoft Windows Server, поэтому самый простой способ — использовать PowerShell: скрипт на PowerShell экспортирует диапазон выдаваемых адресов и зарезервированные адреса в XML-файл (командлет Export-DhcpServer); XML конвертируется в JSON; через API Nautobot вызывается джоб, которому передаётся сформированный JSON; джоб добавляет в Nautobot новые адреса и удаляет те, которые больше не выдаются. Небольшой лайфхак номер четыре. Авторизацию в Nautobot организуем по токену, тут мы Америку не открыли. Но прав у пользователя с данным токеном никаких нет, только на запуск джобов. А во всех джобах в методе run() первым делом выполняется стандартная проверка на принадлежность запускающего к нужной группе: Так мы минимизируем угрозы от утери токена. Таким образом, в Nautobot попадают все зарезервированные IP-адреса с заполненным полем "DNS name". Статус таких адресов определяется как DHCP reserved. А выдаваемые, но не зарезервированные, адреса имеют в Nautobot статус DHCP. Теперь мы можем определить степень заполненности подсети адресами: какие адреса действительно свободные, а какие могут быть выданы в любой момент. Но это работает только с динамическими адресами. Что делать со статическими? Они, хоть и называются так, имеют тенденцию постоянно меняться. Тут нам помогает аналог switchmap — плагин porthistory. Я уже писал о нём статью на «Хабр». Этот плагин добавляет возможность хранить информацию о связке IP-MAC и последнем появлении MAC-адреса на том или ином порту коммутатора. Джоб, входящий в состав плагина, выполняет следующие действия: по SNMP получает с маршрутизаторов таблицу ARP; по SNMP получает с коммутаторов таблицу MAC-адресов; если IP-адреса из таблицы ARP нет среди выдаваемых по DHCP, значит, это статический адрес и его надо добавить в Nautobot (естественно, если его ещё там нет) со статусом Static; по каждому статическому IP-адресу уточнятся DNS-имя и при необходимости актуализируется в Nautobot; данные о привязке IP к MAC-адресу и порту коммутатора сохраняются в соответствующие модели учёта. В результате данные по IP-адресам постоянно актуализируются, а админы не только могут посмотреть, какому устройству принадлежит этот адрес, но и к какому порту какого коммутатора это устройство было подключено последний раз. В Hoff Tech мы жить не можем без виртуальных машин: их легко создать, настроить, а удалить и того проще. Естественно, у каждой виртуальной машины есть интерфейс с IP-адресом, а то и не один. Хотя мы не ставили целью сделать Nautobot системой учёта виртуализации, но, как IPAM-система, Nautobot должен знать всё о кластерах, хостах, самих виртуальных машинах и их адресации. Тут нам опять на помощь приходит PowerShell, но теперь уже вместе с модулем VMware PowerCLI для управления ESXi и vSphere. Алгоритм синхронизации незначительно отличается от вышеописанных: скрипт на PowerShell через API Nautobot получает список адресов ESXi и VSphere; PowerCLI используется для подключения к API ESXi и VSphere; экспортируются данные (установленная ОС, интерфейсы, IP-адреса) обо всех рабочих ВМ в JSON; через API Nautobot вызывается джоб, которому передаётся сформированный JSON; джоб анализирует изменения и по результатам добавляет новые ВМ, изменяет существующие, назначает выключенным и удалённым соответствующий статус. Синхронизация выполняется по шедулеру каждый час, при любых изменениях, вносимых админами виртуальной инфраструктуры через консоль управления облаком, эти изменения зеркалируются в Nautobot. Синхронизируется всё необходимое: объём памяти и количество vCPU, интерфейсы с IP- и MAC-адресами, привязка интерфейсов к VLAN, описание серверов и теги. Существует готовый плагин для Nautobot — Nautobot SSoT vSphere. Он умеет практически всё то же самое, но нам не подошёл по внутренним причинам. В другом окружении использовать его как способ синхронизации данных с VSphere вполне реально. Ну и последний на сегодня лайфхак. Результаты многочисленных джобов копятся и копятся, страница с историей и логами запусков открывается всё медленнее. А ведь эта история не особо и нужна. Увы, встроенной очистки результатов по шедулеру в Nautobot ещё не завезли. Так что рекомендую написать простенький джоб-терминатор, который по заданному алгоритму будет аннигилировать лишние записи. В нашем насчитывается не больше 50 строчек кода: Согласно официальной документации, Nautobot обеспечивает три ключевых варианта использования: Flexible Source of Truth for Networking. Это основной кейс, и мы постарались максимально его реализовать. Сейчас подавляющая часть данных о сети доступна в Nautobot, информация актуальна и автоматически поддерживается в таком состоянии. Не забываем и про уточнение Flexible — необходимые нам модели учёта мы добавляем с помощью плагинов. Extensible Data Platform for Automation. Вебхуки, REST API, GraphQL: всё это используется у нас для передачи данных во внешние системы автоматизации. Такие, например, как системы сканирования уязвимостей. А одной из дальнейших тем для рассказов может стать то, как мы готовим dynamic inventory для Ansible. Platform for Network Automation Apps. Nautobot обеспечивает лёгкое внедрение Python-скриптов сетевой автоматизации. Для этого у него есть готовые модули интерфейсов, доступные данные о сети, нативная синхронизация с Git, поддержка разных секретов для разных устройств/групп. И пусть наши джобы пока только собирают информацию из внешнего мира — в планах уже изменить вектор сетевой автоматизации и минимизировать действия сетевых инженеров напрямую на устройстве через CLI. Сейчас могу смело сказать, что Nautobot отлично справляется с реализацией концепции Source of Truth. Но, конечно,  в основном это заслуга не выбранной системы, а людей, которые двигают автоматизацию. Уверен, что при наличии прямых рук и огонька в глазах абсолютно неважно, какую систему документирования сети вы выберете. Network Team Lead