· 15 мин чтения

Create enabled: No в LLD-override Zabbix 7.4 не глушит уже обнаруженные Link down

Каждый, кто настраивал low-level discovery сети через Template Net Interfaces SNMP, рано или поздно ловит один и тот же парадокс: в override выставили Create enabled: No для триггер-прототипа Link down, а аварии по портам, обнаруженным до этой правки, как сыпались, так и продолжают сыпаться. Ниже — разбор, как LLD-overrides на самом деле применяются в Zabbix 7.4, и пошаговая схема, которой мы в ITfresh глушим уже обнаруженные интерфейсы без потери истории по метрикам.

Симптом: отключили создание триггеров, а старые Link down не молчат

Классическая ситуация в сетевом мониторинге: коммутатор с десятками портов, часть из которых декоративные (patch-панель, резерв, порты в down по проекту), часть — боевые аплинки. Правило LLD «Discovery of network interfaces» на базе шаблона Template Net Interfaces SNMP находит их все, создаёт item-прототипы и триггер-прототип «Interface {#IFNAME}({#IFALIAS}): Link down». Через неделю эксплуатации дежурный тонет в алертах с портов, которые физически никогда не будут подключены.

Логичное на первый взгляд решение — зайти в override правила LLD и для операции над триггер-прототипом Link down выставить Create enabled: No. Правка сохраняется, интерфейс успокаивается… для новых портов. А по портам, которые были обнаружены раньше этой правки, статус триггеров как был Enabled, так и остаётся — они продолжают открывать проблемы при каждом флапе линка.

Причина не в баге платформы, а в том, что операция override применяется не к правилу LLD целиком и не к уже созданным сущностям, а только к моменту материализации нового экземпляра прототипа для конкретного низкоуровневого объекта, который правило видит впервые (или который заново проходит по условиям override). Уже существующий триггер был создан в прошлом цикле обнаружения, когда действовало другое (или отсутствовавшее) правило override — и Zabbix не пересматривает статус задним числом.

У нас в практике этот тикет приходит в двух видах. Первый — «включили override только что, а старое всё ещё шумит». Второй, более коварный — «включили override месяц назад, вроде помогло, а сейчас снова посыпалось». Второй вариант почти всегда означает, что коммутатор пережил переобнаружение декоративных портов (например, после ребута или смены прошивки поменялись SNMP-индексы или имена интерфейсов), и LLD создало для них новые item/trigger — но уже без учёта override, если он на момент создания не покрывал новое имя порта или был написан под старый формат {#IFNAME}.

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

Create enabled и Discover — два разных рубильника в override

В конфигурации LLD-правила (Data collection → Hosts → Discovery → правило → вкладка Overrides → Operations) для каждого типа прототипа — item, trigger, graph, host — можно задать операцию update. У неё есть два принципиально разных поля, которые на слух звучат похоже, а работают по-разному.

Поле операцииЧто определяетКогда вычисляетсяЭффект на уже созданные сущности
Create enabledСтатус (Enabled/Disabled), с которым будет создан НОВЫЙ item/trigger/graph/host по прототипу для низкоуровневого объекта, подпадающего под условие overrideТолько в момент первого создания сущности LLD-правилом для конкретного обнаруженного объектаНикакого — существующая сущность статус не меняет
DiscoverБудет ли низкоуровневый объект вообще считаться «обнаруженным» в текущем и следующих циклах правилаНа каждом цикле опроса LLD-правила (по Update interval)Переводит связанные сущности в состояние «не обнаруживается», запуская таймеры Disable/Delete lost resources, заданные на самом правиле
Discovery rule statusГлобальный вкл/выкл всего правила LLD целикомПостоянно, пока правило активно или отключеноПри отключении правила обнаружение просто не выполняется — ни новых сущностей, ни перевода старых в lost; они замирают в текущем состоянии

Из таблицы видно ключевой вывод: единственный штатный механизм override, который способен воздействовать на уже обнаруженные интерфейсы, — это Discover, а не Create enabled. Но и он действует не мгновенно, а через жизненный цикл lost resources, который настраивается отдельно на самом правиле LLD, а не в override.

Обработкой правил LLD (в том числе применением overrides) на сервере занимаются отдельные рабочие процессы — начиная с Zabbix 6.4 это выделенный менеджер и пул воркеров, число которых задаётся параметром StartLLDProcessors в zabbix_server.conf (по умолчанию — 2). На инсталляциях, где discovery сети обслуживает десятки коммутаторов с сотнями портов каждый, при недостаточном числе воркеров цикл обработки правила может растягиваться, и правка override долетает до реально применённого состояния с задержкой, которая на глаз выглядит как «override не работает», хотя на деле просто не обработан следующий цикл LLD в очереди.

Анатомия правила: {#IFNAME}, {#IFOPERSTATUS}, {#IFADMINSTATUS} и макрос {$IFCONTROL}

Template Net Interfaces SNMP (в актуальных сборках поставляется в составе Generic SNMP templates под именем Network interfaces discovery) опрашивает IF-MIB и формирует набор LLD-макросов на каждый физический и виртуальный интерфейс: {#IFNAME} — имя интерфейса из ifName/ifDescr, {#IFALIAS} — описание порта, {#IFOPERSTATUS} и {#IFADMINSTATUS} — операционный и административный статус интерфейса на момент цикла discovery (используются прежде всего в условиях фильтра правила и overrides, а не как live-значение в триггере).

Живое значение статуса линка читает отдельный item-прототип с ключом вида net.if.status[ifOperStatus.{#SNMPINDEX}], а на него уже опирается триггер-прототип «Interface {#IFNAME}({#IFALIAS}): Link down». В его выражении заложена проверка контекстного пользовательского макроса {$IFCONTROL:"{#IFNAME}"}. По умолчанию для каждого обнаруженного интерфейса он равен 1 («порт важен, реагировать на обрыв»), и именно поэтому все вновь обнаруженные интерфейсы по умолчанию алертят.

Практическая ценность этого макроса в том, что он резолвится не на этапе discovery, а на каждом вычислении триггера. Если вручную выставить на хосте {$IFCONTROL:"GigabitEthernet0/7"} = 0, уже существующий и давно созданный триггер Link down по этому порту перестанет открывать проблему уже на следующем пересчёте — без пересоздания прототипа, без ожидания цикла LLD и без единой потери точки истории по item.

Ещё два макроса того же семейства, которые обычно настраивают на уровне хоста или шаблона, а не трогают в override: {$NET.IFNAME.MATCHES} и {$NET.IFNAME.NOT_MATCHES} — регулярные выражения, которыми фильтр самого LLD-правила ограничивает набор интерфейсов, попадающих в discovery в принципе (например, исключая loopback, null-интерфейсы и служебные тоннели). Если декоративный порт можно однозначно описать именем на уровне всего хоста, часто проще расширить {$NET.IFNAME.NOT_MATCHES}, чем городить отдельный override — но у этого подхода побочный эффект: порт вообще перестаёт обнаруживаться правилом, то есть подпадает под тот же жизненный цикл lost resources, что и override с Discover: No.

Три уровня, на которых можно погасить уже обнаруженный Link down

На практике мы комбинируем три механизма — они решают разные задачи и по-разному быстро действуют.

  1. Контекстный макрос {$IFCONTROL:"{#IFNAME}"} = 0 на уровне хоста. Точечное решение для конкретных портов конкретного устройства. Эффект — на следующем вычислении триггера (обычно секунды-минуты), история item не трогается, сам триггер остаётся в статусе Enabled, просто его выражение больше не «взводится».
  2. Override с условием фильтра и операциями Discover: No + Create enabled: No на тригер-прототипе. Работает группой — например, по regex {#IFNAME} для декоративных портов патч-панели или по {#IFADMINSTATUS}, если порт заведомо выключен административно. Эффект наступает только после следующего цикла правила LLD и только если на самом правиле настроены Disable/Delete lost resources — иначе объект уходит в «не обнаруживается», но триггер остаётся Enabled и физически может продолжать оцениваться, пока не сработает таймер disable.
  3. Прямое отключение уже существующих триггеров. Mass update в интерфейсе или пакетный вызов API trigger.update. Это единственный способ погасить конкретный уже открытый шторм алертов здесь и сейчас, не дожидаясь ни следующего цикла discovery, ни истечения lost-resources таймеров.

Для сценария «выключили Create enabled, а старое продолжает сыпаться» правильная последовательность — начать с пункта 3 (снять текущую боль), затем пункт 2 (закрыть создание новых по декоративным портам через override), и точечно пункт 1 там, где нужна гранулярность на один конкретный порт без правки override и без ожидания цикла.

Настройка override пошагово: закрываем будущие обнаружения

Путь в интерфейсе: Data collection → Hosts (или Templates) → выбранный хост/шаблон → Discovery → нужное LLD-правило → вкладка Overrides → Create override.

Важный нюанс: операция Create enabled не наследуется автоматически на graph prototype и host prototype — если для них тоже задан отдельный оператор в этом же override, статус нужно продублировать явно для каждого типа объекта, иначе график или зависимый прототип хоста создастся с настройками по умолчанию.

Тот же override можно завести через API методом discoveryrule.update, передав массив overrides с условиями (filter.conditions по макросу и оператору) и operations (operationobject: trigger prototype, operator: like, value: «Link down», opstatus.status: disabled). На практике так делают, когда список декоративных портов формируется не руками, а выгружается из внешней системы учёта портов (IPAM/учёт патч-панелей) — тогда список условий override пересобирается скриптом и заливается в правило автоматически при каждом изменении схемы коммутации, без ручного похода в веб-интерфейс.

Ещё один практический момент: у override есть порядок (Sort order) — они применяются последовательно сверху вниз, и, как уже отмечено выше, при отсутствии Stop processing на нужном override результат может «перебиваться» следующим по списку. Мы придерживаемся правила: overrides, которые сужают набор обнаруживаемого (декоративные порты, служебные VLAN-интерфейсы), ставим выше по списку и всегда со Stop processing, а overrides, которые только меняют оформление (severity, теги, группировку по хосту), — ниже, без остановки цепочки.

Массовое отключение уже существующих Link down: UI и API

Для немедленного гашения текущего шторма — без правки шаблона и без ожидания цикла discovery — используем два инструмента.

Через интерфейс: Data collection → Hosts → Triggers, в фильтре задаём Name «Link down» (и при необходимости Host groups/Tags, чтобы не задеть чужие площадки), отмечаем нужные строки чекбоксами и внизу списка выбираем Mass update → Status → Disable.

Через API — удобно, когда портов сотни и они размазаны по десяткам хостов. В Zabbix 7.4 токен API передаётся заголовком Authorization: Bearer, параметр auth в теле запроса для токенов больше не обязателен.

Практика: сначала trigger.get с фильтром по description и, если нужно, по hostids конкретной группы устройств, складываем список triggerid в файл, затем прогоняем trigger.update в цикле — это быстрее и безопаснее, чем гадать с regex по списку в UI, особенно когда нужно погасить порты по десяткам однотипных коммутаторов разом.

Здесь важно не спутать два похожих по названию API-метода. trigger.update меняет статус самого триггера (экземпляра, уже созданного из прототипа) — это именно то, что нужно для немедленного гашения. А правка дискавери-правила и его overrides делается методом discoveryrule.update — им меняют условия и операции для будущих циклов, но он не трогает уже созданные триггеры напрямую. Если автоматизировать зачистку регулярно (например, раз в сутки гасить всё, что подпадает под новый список декоративных портов), связку из этих двух методов удобно завернуть в отдельный скрипт и повесить по расписанию, отдельно от самого discovery.

Настройки самого правила LLD: интервал и lost resources

Параметры Disable lost resources и Delete lost resources настраиваются не в override, а в самом LLD-правиле — на той же вкладке, где Update interval и Filters. Именно они определяют, как быстро триггер, переставший «обнаруживаться» из-за override Discover: No (или из-за реального исчезновения порта), реально перейдёт в статус Disabled и когда, если вообще, будет удалена связанная с ним сущность.

ПараметрДопустимые значенияНаша практика для интерфейсной discoveryРиск при неверной настройке
Update interval правилавремя с суффиксом (например 1h — типовое значение по умолчанию для discovery сетевых интерфейсов)оставляем как есть, не гоняем правило чаще, чтобы не нагружать SNMP-поллер на устройствах с сотнями портов (оценка по практике)слишком редкий интервал — поздно замечаем новые/пропавшие порты
Disable lost resourcesNever / Immediately / After (значение должно быть больше update interval правила)After, с запасом в 2-3 цикла правила — чтобы не ловить ложные disable из-за разовых сбоев опроса (оценка по практике, не значение по умолчанию из документации)Never — триггер годами висит Enabled без живых данных; Immediately — риск ложного disable при кратковременном сбое SNMP
Delete lost resourcesNever / Immediately / After (должно быть больше периода disable)Never или длительный After — интерфейсы имеют свойство временно пропадать из discovery при флапе и переподключаться, терять историю по ним нежелательнопо официальной документации Immediately «не рекомендуется, так как ошибка в фильтре может привести к удалению сущности вместе со всей историей»

Отдельно подчеркну: для item-прототипов (сырые счётчики трафика, ошибок, статуса интерфейса) мы Delete lost resources почти никогда не ставим агрессивным — удаление item необратимо стирает историю, а именно её по условию задачи требовалось сохранить. Гасить нужно алерт (trigger), а не измерение (item).

Грабли, которые мы словили при внедрении этой схемы

Несколько наблюдений из практики настройки LLD-overrides на сетевом оборудовании разных вендоров — не из документации, а из реальных внедрений.

Чек-лист внедрения

Порядок действий, которым мы закрываем подобный тикет у клиента за одну сессию.

  1. Снимаем текущий шторм: Data collection → Hosts → Triggers → фильтр «Link down» → Mass update → Disable (или пакетно через trigger.update по API для больших парков).
  2. Определяем, какие порты декоративные системно (патч-панель, резерв, административно down), и описываем их регуляркой по {#IFNAME}/{#IFALIAS} — раздельно под каждый вендор.
  3. Создаём override с этим условием, Stop processing включён, операция на Trigger prototype «Link down»: Create enabled: No (и Discover: No, если не нужны даже item/graph по этим портам).
  4. Проверяем на самом LLD-правиле, что Disable lost resources стоит на After с разумным запасом, а Delete lost resources — на Never или очень длительный After, чтобы не терять историю по интерфейсам.
  5. Для единичных исключений (конкретный порт на конкретном устройстве) используем не override, а контекстный макрос {$IFCONTROL:"{#IFNAME}"} = 0 прямо на хосте — эффект мгновенный, без ожидания цикла discovery.
  6. Через один-два цикла Update interval правила проверяем, что новых Link down по декоративным портам больше не появляется, а история по item сохранена.

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

Чем Create enabled в override отличается от статуса самого триггер-прототипа в шаблоне?
Статус в самом прототипе — это значение по умолчанию для всех низкоуровневых объектов, которых не коснулось ни одно override. Create enabled внутри override — точечная подмена этого значения, но только для объектов, подпадающих под условие фильтра override, и только в момент их первого создания. Оба поля не трогают уже существующие созданные сущности.
Нужно ли перезапускать zabbix-server после правки override или контекстного макроса?
Нет. Изменения override вступают в силу на следующем цикле опроса LLD-правила (по его Update interval), а изменение контекстного макроса {$IFCONTROL} — на следующем вычислении соответствующего триггера, обычно в пределах интервала обновления item, без перезапуска службы.
Что произойдёт с историей item, если всё же выставить Delete lost resources: Immediately?
Сущность (item, а вместе с ней история и тренды) будет удалена сразу после того, как объект перестанет обнаруживаться LLD-правилом. Официальная документация прямо предупреждает, что это рискованно: ошибка в условии фильтра или override может привести к безвозвратной потере истории по объектам, которые на самом деле продолжают существовать.
Как отличить триггер, унаследованный от старого обнаружения, от пересозданного заново?
Прямого признака «старый/новый» в UI нет, но можно ориентироваться на поле Discovered in (связь с LLD-правилом и датой последнего обнаружения) в списке триггеров, а также на историю событий по конкретному triggerid — если запись стабильно фигурирует до момента правки override, она относится к объекту, обнаруженному раньше правки.
Можно ли применить override только к одному хосту, а не ко всему шаблону?
Да, если LLD-правило определено на уровне хоста (а не унаследовано жёстко без возможности расширения), override можно создать локально для этого хоста в Data collection → Hosts → Discovery конкретного хоста — тогда действие ограничится только им, остальные хосты по шаблону не затронутся.
📄
Скачайте подробный разбор в PDF Кейсы, статистика, типовые ошибки и чек-лист самопроверки — 12 страниц
Скачать PDF

Подпишитесь на разборы ITfresh

Раз в неделю — практичные материалы по ИТ для бизнеса: без спама, только польза.

Письмо придёт в течение минутыНе нашли его во «Входящих» — загляните в папку «Спам» или «Промоакции» и нажмите «Не спам». Так все следующие выпуски будут приходить прямо в основную почту.