← Blog

Мониторинг и безопасное управление парком систем питания постоянного тока через SNMP

DEENESRUUK

Каждое телекоммуникационное место питается от постоянного тока (DC). За радиостанциями и маршрутизаторами находится ректификационная стойка — установка Eltek, преобразующая сетевое напряжение в чистое −48 В и поддерживающая заряд батарейной батареи, которая должна обеспечить питание объекта во время отключения. Когда одна из этих установок начинает работать некорректно, вы хотите узнать об этом до того, как это сделает батарея. Это система, которую я построил для мониторинга целого парка таких установок — и, в конечном итоге, для управления ими.

От скрипта отчета к работающей системе

Инструментом, который она заменила, был единственный скрипт, генерирующий пару статических HTML-отчетов — история вчерашнего дня, застывшая во времени. Мне нужен был живой статус, история изменений и та часть, которая превращает панель мониторинга в инструмент: возможность действовать с контроллером без ручного входа в него.

Парк не однороден. Две линейки контроллеров (классический Smartpack-1 и более новый Smartpack-R / eNexus) — разные MIB, разные особенности. Поэтому ядром должна быть независимость от производителя (vendor-agnostic), позволяющая оператору обучить его новому контроллеру без изменения кода.

Обнаружение → Классификация → Опрос

Три запланированных модуля обеспечивают сбор всех данных:

  • Discovery извлекает список хостов из Zabbix (инвентаризация сети уже там) и кэширует его.
  • Classify опрашивает каждый хост: он выполняет SNMP-get identity OID для каждого известного профиля контроллера, и первый отвечающий профиль побеждает — этот хост становится известной системой питания данной линейки. Хосты, которые ничего не отвечают, попадают в корзину Unknown.
  • Poll выполняет SNMP-walk для каждой классифицированной системы каждые 15 минут, используя точные скалярные OID и столбцы таблиц, определенные в ее профиле, и отрисовывает панель мониторинга.

Что делает эту систему расширяемой, так это то, что classify и poll управляются профилем. Профиль — это просто словарь OID: identity OID, скалярные OID (входное напряжение, температура, заданные значения float/boost…) и столбцы таблиц (одна строка на каждый слот ректификатора). Они хранятся в базе данных и редактируются в пользовательском интерфейсе. Добавление нового производителя — например, установки Huawei — это определение профиля, а не выкатывание кода. Вы создаете его для образца устройства с кнопкой Probe, которая выполняет живые snmpget и показывает вам, что именно возвращается, а затем продвигаете соответствующий хост в рабочую систему.

Инвентаризация, которая не кричит ложными тревогами

Опрос генерирует две вещи: живые метрики и инвентаризацию компонентов — каждый модуль ректификатора и блок управления по серийному номеру, слоту, ревизии оборудования и прошивки. Сравнение двух последовательных опросов дает события installed / removed / changed, каждое из которых отправляется по электронной почте ответственному за данный объект.

Самая сложная часть инвентаризационного сравнения — это не само сравнение, а отсутствие ложных срабатываний. SNMP через нестабильную сеть теряет пакеты; один пропущенный опрос не должен вызывать тревогу в 3 часа ночи по поводу ректификатора, который никуда не уходил. Два механизма справляются с этим:

  • Проверка на аномалии (Sanity check) — если скаляр сообщает «8 ректификаторов», но таблица ректификаторов вернулась пустой, это частичный сбой SNMP, а не массовое удаление. Такой компонент помечается как ненадежный для этого прохода, и события removed не срабатывают.
  • Период снисхождения (Grace period) — компонент должен отсутствовать в течение трех последовательных опросов (~45 минут), прежде чем он будет объявлен удаленным. Отсутствие на короткое время остается незамеченным.

И первый опрос недавно подключенного объекта подавляет первоначальную загрузку (bootstrap-suppressed) — одновременное подключение сотни объектов не должно обрушить почтовый ящик сотней писем типа «новый компонент».

От чтения к записи — SNMP SET с предохранителями

Мониторинг — это простая половина. Интересная половина — это возможность позволить оператору изменить контроллер — напряжение float и boost, лимит тока заряда, пороговые значения тревог — из браузера, через SNMP, без SSH-подключения к работающей батарейной установке.

Запись в системы питания — это та область, где нужна максимальная паранойя. Каждый набор данных проходит один и тот же цикл:

edit a parameter
   │
   ├─ validate against the MIB     (type · enum · range → reject out-of-bounds)
   ├─ battery-critical? ───────────→ require an explicit confirm
   ├─ SET
   ├─ read the value BACK          (mismatch = the change FAILED, not succeeded)
   └─ write an audit record        (who · what · old → new) · one-click revert

Чтение обратного значения (read-back) — это критически важный шаг. Успешный ответ SNMP SET не означает, что контроллер принял значение — поэтому система считывает OID обратно и считает изменение совершенным только в том случае, если устройство теперь сообщает то, о чем вы просили. Значения вне диапазона отклоняются еще до того, как покинут приложение; критические для батареи значения — напряжения, которые определяют, закипит ли батарея или разрядится — не пройдут без явного подтверждения; и каждое изменение откатывается к предыдущему значению одним нажатием кнопки.

Каталог записываемых OID создается из MIB производителя, а не вводится вручную. MIB уже кодирует тип, диапазон и доступность каждого OID, поэтому правила безопасности исходят из источника истины, а не из догадки.

Тест батареи

Один контроль заслуживает отдельного абзаца. Тест батареи намеренно разряжает батарейную батарею для измерения ее реальной емкости — полезная функция и та вещь, которую вы не хотите триггерить случайно при уже нестабильном питании от сети. Это одна кнопка на панели мониторинга, которая предупреждает перед началом, затем повторно проверяет систему в режиме реального времени раз в минуту во время проведения теста; когда контроллер достигает минимального напряжения конца цикла (или срабатывает тревога), он сам завершает тест, и кнопка сама возвращается в исходное состояние. Интерфейс никогда не догадывается о состоянии — он считывает его с контроллера.

Доступ к устройству без пароля от него

Последняя часть связывает «трекер» и «собственный веб-интерфейс контроллера». Каждое устройство имеет нативный веб-интерфейс, но распространение паролей устройств не масштабируется и не ведет учет. Вместо этого аутентифицированный пользователь нажимает Web UI и попадает в собственный интерфейс контроллера, проксируемый за тем же входом — прокси защищен сессией трекера и внедряет сохраненные учетные данные устройства, поэтому оператор никогда их не видит. Конфигурация прокси для каждого устройства генерируется из инвентаризации, а не поддерживается вручную: парк меняется, конфигурация регенерируется, проверяется и перезагружается — или откатывается. Секреты устройств зашифрованы в состоянии покоя; чистый текст никогда не попадает в базу данных.

Общий вид

FastAPI + APScheduler, PostgreSQL, SNMP, UI на Jinja с серверным рендерингом, всё в Docker. Но фреймворк никогда не был главной целью. Главная идея — одна и та же: рассматривать устройство как источник истины и проверять по нему. Классифицировать по тому, что устройство действительно отвечает; объявлять компонент утерянным только тогда, когда он действительно потерян; считать параметр измененным только тогда, когда контроллер считывает его обратно. Мониторинг говорит вам, что есть — интересная инженерия заключается в том, чтобы что-то с этим сделать, не ухудшая ситуацию.

Прозрачность: большинство постов здесь написаны с помощью ИИ, а неанглийские версии переведены локальной LLM и вычитаны. Заметили ошибку? Напишите мне.