Автоматизируем мониторинг: низкоуровневое обнаружение

  • Tutorial
Мониторинг большого количества устройств требует в помощь инструменты автоматизации. Иначе, если все делать мышкой, то можно “укликаться”, пока добавишь и настроишь все, что требовалось. К тому же, обязательно где-нибудь ошибёшься, человек не робот. Благо, в Zabbix все эти инструменты есть: это шаблоны, API, обнаружение сетевых устройств, авторегистрация Zabbix-агентов.

И вот с версии 2.0 сюда добавилось Low-Level Discovery (LLD) или низкоуровневое обнаружение. Хотелось бы рассказать что это такое.

Низкоуровневое обнаружение


image

Обнаружение сетевых устройств (Network Discovery) — очень полезная штука, которая позволяет избежать ручного добавления новых узлов сети и связывания их с нужными шаблонами. При чем можно создавать довольно сложные сценарии. Например, автоматически связывать нового клиента(его CPE) базовой станции Wi-Fi c нужным шаблоном для CPE и даже автоматически добавлять этот узел в нужном месте на карте. В документации есть наглядный пример того как сетевое обнаружение настраивается.

LLD становится нужен на следующем этапе, после того как узел найден и прикреплён к шаблону. LLD позволяет находить объекты самого узла.

LLD позволяет нам автоматически создавать элементы данных, триггеры и графики для:

  • файловых систем компьютера
  • сетевых интерфейсов компьютера
  • данных из SNMP-таблиц с одномерным индексом

Можно расширить возможности LLD путем своих собственных скриптов, главное, чтобы на выходе скрипта для Zabbix был понятный ему вывод вида JSON.

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

Конечно можно обойтись и без LLD, ведь во всех предыдущих версиях обходились же шаблонами. Вот только все, кто Zabbix используют, сталкивались с ситуацией, что в одном сервере логических дисков два, а в другом четыре. Что у одного коммутатора Ethernet-портов 8, а у другого из той же линейки – 24. Остается писать шаблон на 24 порта (на 4 диска), а потом, после привязки устройства вручную отключать лишние элементы данных, триггеры. Вот мы уже и “укликались”. А тут кто-то новый сервер сделал, а в нем этих дисков 8… А еще кто-то из коллег в существующем сервере еще одну партицию создал с нестандартным путем и ничего не сказал…

Как это было раньше


Чтобы понять, что нам дает LLD, нет ничего лучше наглядного примера. Вспомним, что приходилось делать с многопортовыми коммутатороми в предыдущих версиях Zabbix.

Допустим, у нас есть коммутаторы Cisco, D-Link, Zyxel и прочий “зоопарк”. С количеством портов 5/8/16/24/50.

image

Будем мониторить состояние портов, используя SNMPv2 и счетчики, описанные в IF-MIB. LLD у нас пока нет, поэтому начнем писать обычный шаблон. Назовем его Template_IF_MIB_SNMPV2.

В шаблоне для одного порта нам нужно создать 14 элементов данных (можно конечно и меньше, но мы решим, что нам критически важно собирать практически все), а также некоторое количество триггеров, графиков. В веб-интерфейсе Zabbix на это уйдет минут 10, если активно махать мышкой и пользоваться кнопкой “Клонировать”.

image

Переведя дух, как-то продолжать не сильно хочется для других портов. Кому охота делать одно и то же 50 раз? Поэтому сразу возникают вопросы:

  • Как избежать траты времени при создании оставшихся портов (2-50)
  • Как избежать без ручного вмешательства заведомо обреченных на неудачу запросов к счетчикам с 6 по 50 порта, когда универсальный шаблон будет прикреплен к 5 портовому коммутатору
  • Как не засорять сеть опросами счетчиков портов, которые не используются

Первую проблему можно попробовать решить, например, выгрузкой шаблона в XML с последующим CTRL+C /CTRL+V в текстовом редакторе. Или даже написать небольшой внешний скрипт и генерировать XML им. Но…

Что можно сделать теперь при помощи LLD


Но с Low-Level Discovery у нас есть возможность сделать все гораздо проще. Вместо того, чтобы создавать элементы данных для одного порта, мы просто ОДИН раз создадим прототипы элементов данных, а также прототипы необходимых триггеров. Так как мы это делаем только один раз, то совсем не жалко потратить время и создать в дополнении также информативные графики, а точнее прототипы графиков.

Итак, чтобы создать в шаблоне LLD заходим в правила обнаружения:

image

Далее, нажимаем создать правило обнаружения и создаем новое правило, назовем его Network interfaces discovery:

image

Указываем все как на картинке. Некоторые поля стоит прокомментировать:
Ключ snmp.discovery.v2
SNMP OID OID, который будем использовать для критерия добавления интерфейса на мониторинг, в данном случае ifOperStatus.
SNMP community В данном примере используется макрос {$COMMUNITY}. В этом же шаблоне прописано значение по умолчанию, {$COMMUNITY}=public. Далее, для каждого конкретного узла сети, к которому мы прикрепим данный шаблон, мы можем либо переписать значение макроса, если его snmp community будет иным, либо ничего не делать, и тогда будет использоваться прописанное в шаблоне public. Данный прием помогает избежать необходимости изменять элементы данных на уровне узла сети.
Фильтр Значение специального макроса {#SNMPVALUE}, который соответствует результату запроса ifOperStatus.X к устройству, мы подвергаем очень сложному регулярному выражению: 1. Как мы знаем из IF-MIB, ifOperStatus.X = 1 соответствует up(1). Таким образом, мы будем ставить на мониторинг только те интерфейсы, которые на момент сканирования сети были в состоянии up(1). Это нас избавит от сбора счетчиков тех интерфейсов, которые не используются. Если же мы хотим добавлять на мониторинг все порты без разбора, то поле фильтр просто оставляем пустым.
Период сохранения потерянных ресурсов Через сколько дней удалить сетевой интерфейс с мониторинга, если сетевой интерфейс перестал находиться повторным сканированием LLD, или статус ifOperStatus.X перестал быть up(1). В данном случае выставлен ноль – не удалять.

Итак, мы создали правило, теперь мы должны создать прототипы элементов данных. Здесь все практически также, как при создании обычных элементов данных, но есть пара особенностей. Для примера добавим входящий трафик, ifInOctets:

image

Описание полей:
Имя if{#SNMPINDEX} ({$PORT{#SNMPINDEX}_DESC}) In. Расшифруем конструкцию. Как мы уже знаем {#SNMPINDEX} – системный макрос, который будет соответствовать индексу интерфейса в SNMP. Его мы и будем подставлять в название интерфейса, для понятных нам имен. Будет получаться: if1, if2, if3 и т.д. Второй макрос – пользовательский, {$PORT{#SNMPINDEX}_DESC}, в имя которого будет вставляться индекс интерфейса, динамически изменяя имя макроса. Он опционален, но я его использую, для того, чтобы можно было в Zabbix прописывать дополнительное описание каждого интерфейса, просто добавив на уровне узла сети макрос, например:

{$PORT1_DESC} = uplink, ISP1
Ключ В ключе должен присутствовать {#SNMPINDEX}, чтобы ключ всегда был уникален
SNMP OID Точно также, мы подставляем в наш SNMP OID макрос {$SNMPINDEX}, чтобы опрашивать счетчик нужного нам интерфейса.
Создадим прототипы и для остальных элементов данных, которые нам нужны для каждого интерфейса, получим примерно вот такой список:

image

создадим прототипы триггеров

image

… и прототипы графиков:

image

Прицепив наш шаблон к реальным узлам сети, через некоторое время мы получим результат. Вот так будут выглядеть последние данные для узла сети, после отработки LLD:

image

Как и предполагалось, данные собираются только для активных портов.

А вот и графики, также динамически созданные через LLD:

image

Итого


Подведем итог, что мы получили, используя LLD в шаблоне для многопортовых коммутаторов:

  • Универсальный шаблон для всех устройств, поддерживающих IF-MIB
  • Не требует донастройки на уровне узла сети после добавления шаблона. Максимум, что нужно, это заполнить макросы {$COMMUNITY} (если snmp community не public), заполнить ряд макросов {$PORTx_DESC) (если хочется видеть описание порта) и активировать триггеры [NET] if{#SNMPINDEX} ({$PORT{#SNMPINDEX}_DESC}) is down для ключевых портов, для которых требуется оповещение об изменении статуса с up на down (именно поэтому эти триггеры в прототипах деактивированы, чтобы не быть засыпанным сработавшими триггерами от access портов пользователей, который то включают, то выключают свои компьютеры).

А ведь, как уже упоминалось, точно такой же фокус можно провернуть и с файловыми системами, и сетевыми интерфейсами компьютера (еще пример здесь), а также со многим другим, что хранится в SNMP. Правда, есть ограничения. Например, к сожалению, LLD не будет работать в случае, если таблица SNMP содержит несколько индексов. Есть возможность это ограничение обойти при помощи макросов, однако, это уже, как говорится, из разряда “костылей”.

Вот так. И никакой больше возни с однотипными элементами данных, триггерами, графиками. Просто настраиваем LLD и наслаждаемся плодами автоматизации. Или настраиваем LLD + сетевое обнаружение и вообще уходим в отпуск :)
Zabbix
Company

Comments 26

    0
    Алексей, спасибо, что пишете о новых возможностях Z.
    Очень хотелось бы увидеть еще подобную автоматизацию для JMX интерфейсов и шаблоны на Web мониторинг.
      +1
      Присоединяюсь к просьбе написать про JMX и JVM мониторинг,
        +1
        Написать про JMX и JVM мониторинг в новой версии я вам и самостоятельно могу насписать:) Вопрос в количестве желающих наверное.
        +1
        Поддержка шаблонов для Web мониторинга уже реализована, но будет доступна только в следующей версии — Zabbix 2.2. Пока существует только шестая альфа доступная для предварительного тестирования.
        0
        Когда-то писал простой скрипт создания кастомного LLD ответа для Zabbix-агента под винду — pastebin.com/gFXdhj5Y
        Использовать в агенте можно создав UserParameter. Пример работы:

        $services = Get-Service | Select-Object -Property «Name», «Status»
        New-JsonForZabbix -Format $true -Objects $services;

        Создаст LLD ответ со всеми сервисами в системе с макросов, которые совпадают с именами выбранных NoteProperty — {#Name} и {#Status} Сразу отвечу за плохой код — это должно было работать под PS 2.0 и .NET 2.0, где не было штатных средств работы с json, а таскать за собой dll'ку очень не хотелось.
          0
          Если бы оно еще умело строить карту с указанием соединений между устройствами, как это делает NetXMS…
            +2
            Оно умеет, если использовать ZabbixAPI.

            map.createSelements, map.updateSelements, map.deleteSelements
            0
            LLD — совершенно шикарная штука!
            Вот жаль только, что Zabbix не различает длинные динамические индексы (например, .40.112.104.121.115.105.99.97.108.32.109.101.109. 111.114.121.32.54.102.50.56.48.49.102.52.54.48.49.102.50.48.49.102.52.53.48.49.102.53.99.48)

            Из-за этого приходится при каждом обновлении Заббикса неофициальный патч накатывать, чтобы работал мониторинг блоков питания, состояния жестких дисков, модулей оперативной памяти на серверах IBM.

            Искренне не понимаю, почему этот патч не внесут в официальную ветку Zabbix.
              0
              Дело в том, что мы стараемся не вносить никаких изменений в стабильные версии Заббикса за исключением исправления багов. Бывают редкие исключения. Поддержка длинных динамических индексов уже реализована и будет доступна в 2.2.
              0
              Теперь половину моих скриптов можно будет выкинуть — их функционал заменен LLD :))

              Я правильно понимаю что критерием уникальности обнаруженного интфейса является snmp interface index. Т.е. если я добавлю новую лайнкарту и у меня все индексы «поплывут» то LLD сотоворить что-то плохое?
                +1
                «Из коробки» в шаблонах Zabbix используются индексы как критерий уникальности.

                Но если на устройстве индексы не статичны, то нужно эти шаблоны подправить используя динамические индексы — в правиле обнаружения нужно указать OID, возвращающее уникальное значения (например ifDescr), а в прототипах элементов использовать не индекс "{#SNMPINDEX}", а значение "{#SNMPVALUE}" (например ifInOctets[index,ifDescr,{#SNMPVALUE}])
                  0
                  Я всё это прекрасно знаю. Вопрос в том, можно ли эти динамические индексы использовать в LLD как критерий уникальности?
                    0
                    Да, их даже нужно использовать в таких случаях :)
                0
                Было бы очень хорошо если бы вы выложили готовый шаблон, что бы народу вручную не набивать его.
                  0
                  Шаблоны для низкоуровневого обнаружения включены в Zabbix 2.0.x. Можно скачать с Zabbix wiki.
                  0
                  Большое спасибо за статью. Благодаря ей наконец-то нашел время для создания собственных LLD шаблонов.

                  Подскажите, Вы в статье упоминаете про макрос {$PORT{#SNMPINDEX}_DESC}. Вы самостоятельно прописываете его значение в параметрах узла или Zabbix заполняет его динамически? Например у меня есть данные порта ifAlias, могу ли я создать конструкцию вроде этой: "if.{#SNMPINDEX} {{HOST:HOST}:ifAlias.["{#SNMPINDEX}"].last(0)} on {HOST.NAME} is down" для более наглядного описания порта в триггере?
                    0
                    И ещё вопрос:

                    Если я использую правило обнаружения с фильтром, то в случае, если порт перешел в состояние "down (2)" и в это время отработало это правило, то порт встаёт в очередь на удаление потерянных ресурсов. Всё бы ничего, но удаляется триггер, который после восстановления порта уже имеет статус «Disabled» (так как мы выше отключили их по умолчанию). Есть способ побороть эту проблему?
                      0
                      Это баг, который должен быть исправлен. Его можно видеть здесь: ZBX-6315
                      0
                      Да, Zabbix позволяет делать такие конструкции в имени триггера. При создании триггера на основе такого прототипа получится триггер с промерно таким названием: «if.1 {{HOST.HOST}:ifAlias.[»1"].last(0)} on {HOST.NAME} is down". В секции мониторинга остальные макросы тоже будут раскрыты.
                        0
                        У меня на выходе получается if.10146 {{HOST:HOST}:ifAlias.["10146"].last(0)} is down on CISCO1. В чём может быть проблема?
                          0
                          У вас опечатка. Замените {HOST:HOST} на {HOST.HOST}.
                            0
                            Ох, чёрт. Тем не менее, теперь на выходе:

                            if.10146 {CISCO1:ifAlias.["10146"].last(0)} is down on CISCO1

                            а хотелось бы видеть алиас интерфейса.
                              0
                              Сразу не осилил. Zabbix не подерживает составные макросы "{host:key.func()}" в имени триггера.

                              Если вы хотите увидеть алиас интерфейса, то лучше будет сделать так:
                              * в правило обнаружения в поле OID вписать ifAlias
                              * а название прототипа триггера сделать таким: "if.{#SNMPINDEX} {#SNMPVALUE} on {HOST.NAME} is down"
                                0
                                Ну да, простите, долго не мог сообразить, как понятнее написать. Жаль, что не поддерживает. И в 2.2 не ожидается?

                                Идея с правилом обнаружения хорошая, вот только с фильтрацией по ifOperStatus очень уж печально тогда. Ладно, спасибо. Будем думать.
                                  0
                                  В 2.2 не ожидается.
                          0
                          Т.к. ifAlias = TO CISCO2, я надеялся увидеть нечто вроде if.10146 (TO CISCO2) is down on CISCO1.

                      Only users with full accounts can post comments. Log in, please.