Zabbix 3.4: Массовый сбор данных на примерах счетчика Меркурий и smartmontools

  • Tutorial


Всем привет, ранее мы уже упоминали о возможностях по массовому сбору данных в новой версии опенсорс системы мониторинга Zabbix 3.4. Теперь остановимся на этом функционале поподробнее, и чтобы было нагляднее, расскажем о нем на двух примерах:

  • сбор всех данных за раз, полученных в JSON от консольной утилиты счетчика электроэнергии Меркурий 236
  • сбор показателей S.M.A.R.T. жестких дисков и SSD, полученных в табличном виде от smartmontools.

А в чем была собственно проблема?


Собирать данные через консольные утилиты или вызовы API данные можно было и ранее, но существовали сложности:

  • медленные запуски утилит каждый раз, на каждый нужный элемент данных
  • обращение к ресурсу (диск, порт, счетчик, API приложения) на каждый элемент данных
  • парсинг результата нужно было делать внешними скриптами/утилитами
  • а если потом нужно было поправить парсинг – приходилось опять обновлять UserParameters или скрипты
  • кроме всего прочего, одновременные запросы от нескольких Zabbix pollers приводили к ошибке при обращении, например, к последовательному порту.

В общем, дело было так:



А с появлением зависимых элементов данных, стало возможно так:



Как это работает?

  • В Zabbix 3.4 источником данных может выступать другой элемент данных, который называется родительским или мастер-элементом. Такой элемент может, например, содержать массив данных в формате JSON, XML или произвольном текстовом формате.
  • В момент поступления новых данных в родительский элемент, остальные элементы данных, которые называются зависимыми, обращаются к родительскому элементу и при помощи таких функций препроцессинга как JSON path, XPath или Regex выделяют из текста нужную метрику.

Кстати, препроцессинг – тоже нововведение 3.4, он реализован добавлением новых процессов preprocessing_manager и preprocessing_worker на Zabbix-сервере. Поэтому, если вы обновляетесь с 3.2 – не забудьте обновить шаблон для сервера, чтобы мониторить их работу.

Переходим к примерам.


Меркурий 236



Представим, что на нашем проекте, кроме контейнеров, виртуальных машин, приложений, сетевых устройств, баз данных, бизнес показателей и всего прочего требующего контроля, присутствует необходимость мониторить показатели электросети и другой «инженерки», как, например, климатическое оборудование. Используются стандартные для нашей средней полосы устройства: трехфазный счетчик электроэнергии Меркурий 236 АRT-01 PQRS с интерфейсом RS-485, поверх которого общение происходит через проприетарный протокол производителя.

Задача ответственная – сразу собирать показатели напряжения, мощности, тока, потребления, частоты. Подключить такой прибор к серверу с Zabbix агентом – задача посильная – достаточно будет серийного порта с RS-485, например, в форме USB адаптера. Но как прочитать данные? Если бы не github и добрые люди, поделившиеся своим решением для умного дома, писать бы нам модуль к Zabbix, который бы мы учили разговаривать на протоколе счетчика и опрашивать показатели.

Утилита простая и удобная (за что автору большое человеческое спасибо) подключается к счетчику на указанный порт, считывает данные и отдает нам в виде текста, CSV или JSON.

Давайте попробуем установить и запустить:

git clone https://github.com/Shden/mercury236.git
cd mercury236
make
./mercury236 /dev/ttyS0 --help
Usage: mercury236 RS485 [OPTIONS] ...
RS485 address of RS485 dongle (e.g. /dev/ttyUSB0), required
--debug to print extra debug info
--testRun dry run to see output sample, no hardware required
Output formatting:
....
--help prints this screen

Запускается! Отлично, подключаем счетчик, опрашиваем, получаем JSON:

./mercury236 /dev/ttyS0 --json
{
                "U": {
                               "p1": 0.35,
                               "p2": 0.35,
                               "p3": 226.86
                },
                "I": {
                               "p1": 0.00,
                               "p2": 0.00,
                               "p3": 0.39
                },
                "CosF": {
                               "p1": 0.00,
                               "p2": 0.00,
                               "p3": 0.60,
                               "sum": 0.60
                },
                "F": 50.00,
                "A": {
                               "p1": 41943.03,
                               "p2": 41943.03,
                               "p3": 41943.03
                },
                "P": {
                               "p1": 0.00,
                               "p2": 0.00,
                               "p3": 53.45,
                               "sum": 53.45
                },
                "S": {
                               "p1": 0.00,
                               "p2": 0.00,
                               "p3": 89.83,
                               "sum": 89.83
                },
                "PR": {
                               "ap": 120.51
                },
                "PR-day": {
                               "ap": 86.00
                },
                "PR-night": {
                               "ap": 34.51
                },
                "PY": {
                               "ap": 0.00
                },
                "PT": {
                               "ap": 0.04
                }
}

В итоге утилита уже сделала всю сложную работу за нас, реализовав протокол общения с счетчиком, вытащив данные, да еще и предложила нам это в виде удобного JSON объекта. Вот только раньше просто так мы ей не смогли бы воспользоваться — пришлось бы писать обвязку в виде скриптов, а самое главное – реализовывать механизм контроля доступа к среде последовательного порта. Ведь если два поллера Zabbix одновременно обратятся к нему – один за током третьей фазы 3, а другой — за током фазы 2, у нас не вернулось бы ничего.

В 3.4 все становится гораздо проще, и мы теперь быстро и легко можем передавать данные сторонних консольных утилит в Zabbix, не прибегая к оберточным скриптам, и не запуская по 10 раз одно и тоже на каждый элемент данных отдельно. Итак,

Настроим запуск утилиты mercury236 из Zabbix


sudo cp mercury236 /etc/zabbix/scripts
cd /etc/zabbix/scripts
chmod +x mercury236
sudo usermod -G dialout zabbix

Для запуска скрипта, создадим в конфиге Zabbix-агента новый UserParameter:

UserParameter=mercury236[*],/etc/zabbix/scripts/mercury236 $1 $2

Сохраняем файл, не забываем перезапустить наш Zabbix-агент.

Теперь создадим в новом шаблоне родительский элемент данных:



Как видите, в родительском элементе данных нет ничего особенного – просто проверка через UserParameter Zabbix-агента. А это значит, что и нет никаких ограничений на то, какой тип проверки может выступать в роли родительского элемента – здесь могут быть и данные полученные через Zabbix trapper или через Внешние проверки. Единственное, мы выбрали Тип информации – Text и срок хранения истории в 1 день – хранить дольше мы собираемся метрики отдельно в зависимых элементах (можно не хранить данные вообще в родительском элементе, выставив срок хранения 0). Обратите внимание, что препроцессинг в этом элементе данных мы не трогаем.

Настроим получение наших метрик счетчика


Для того чтобы начать создавать зависимые элементы данных, можно воспользоваться новым помощником. Ну или просто нажать «Создать элемент данных»:



Создадим элемент данных для напряжения первой фазы, выберем:

  • Тип: Зависимый элемент данных
  • Основной элемент данных: mercury-get



Затем во вкладке «Предобработка» добавим наше выражение JSON Path:

Путь JSON: $.U.p1



Кстати, маленький совет. Чтобы не тратить много времени на отладку и ловлю ошибок, перед тем как заполнять JSON Path можно быстро проверить правильность выражения онлайн, например здесь: jsonpath.com, скопировав туда JSON, полученный от утилиты.

Аналогичным образом создаем другие интересующие нас метрики. В том числе — для накопленной энергии по дневному тарифу.

Для этого создадим новый элемент данных и выберем:

  • Тип: Зависимый элемент данных
  • Основной элемент данных: mercury-get

А вот во вкладке «Предобработка» обратите внимания на два нюанса:

  • будем использовать нотацию с квадратными скобками, так как в пути JSON есть дефис
  • препроцессинг может быть многошаговым, например здесь результата первого шага умножим на 1000, чтобы получить Вт*ч из кВт*ч



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



Доведем наш шаблон до ума


Чтобы шаблон был законченным, добавим триггеры, используя макросы, делая его максимально гибким. Не забываем про зависимости триггеров.



Что получилось


Шаблон готов, данные побежали, посмотрим, что у нас получилось:



Все последние данные, собранные за одно обращение:



Обратите внимание, что время сбора всех метрик абсолютно идентично.

Итоговый шаблон для счетчика доступен на репозитории решений на share.zabbix.com здесь.

Подведем итоги:

  • переиспользовали хорошую программку и не тратили время на написание своей реализации сбора данных по протоколу Меркурий
  • UserParameter остался, но схлопнулся до простого вызова. По сути можно даже system.run[] использовать
  • cкрипты-обертки тоже не писали. Всё распарсили через JSON path в шаблоне
  • cчетчик не мучали сильно, один запрос – все нужные нам данные разом.

Smartctl и smartmontools




Давно мы уже писали на хабре, как можно контролировать S.M.A.R.T. жестких дисков, чтобы успеть их вовремя поменять, через использование UserParameters. Такой подход работает, но он не был лишен недостатков:

  • избыточные запуски утилиты smartctl, а она в свою очередь каждый раз обращалась к контроллеру жесткого диска
  • пришлось делать отдельный парсинг для Linux и Windows. Особенно больно с этим сейчас работать в Win: (for /F… так… экранируем двойные кавычки еще кавычками…. Аааа!!!!)

Постараемся в 3.4 от всего этого избавится.

Случай с smartmontools имеет два отличия от примера со счетчиком выше:

  • smartctl нам JSON не возвращает
  • дисков в сервере может быть различное количество, поэтому нам нужно использовать низкоуровневое обнаружение(LLD).

Но ничего страшного! Во-первых, зависимые элементы данных работают и для LLD, а во-вторых у нас среди preprocessing-фильтров есть и PCRE regex. Воспользуемся им, чтобы вытащить нужные показатели из не супер сильно структурированного ответа утилиты. Примерно такого:



Приступим.

Упрощаем UserParameters


Было:

UserParameter=uHDD[*], sudo smartctl -A $1| grep -i "$2"| tail -1| cut -c 88-|cut -f1 -d' '
UserParameter=uHDD.model.[*],sudo smartctl -i $1 |grep -i "Device Model"| cut -f2 -d: |tr -d " "
UserParameter=uHDD.sn.[*],sudo smartctl -i $1 |grep -i "Serial Number"| cut -f2 -d: |tr -d " "
UserParameter=uHDD.health.[*],sudo smartctl -H $1 |grep -i "test"| cut -f2 -d: |tr -d " "
UserParameter=uHDD.errorlog.[*],sudo smartctl -l error $1 |grep -i "ATA Error Count"| cut -f2 -d: |tr -d " "
UserParameter=uHDD.discovery,sudo /etc/zabbix/scripts/smartctl-disks-discovery.pl

Стало:

UserParameter=uHDD.A[*],sudo smartctl -A $1
UserParameter=uHDD.i[*],sudo smartctl -i $1
UserParameter=uHDD.health[*],sudo smartctl -H $1
UserParameter=uHDD.discovery,sudo /etc/zabbix/scripts/smartctl-disks-discovery.pl

Аналогично делаем и для Windows, попутно избавляясь от CMD магии с использование for /F и find. Посмотреть можно тут.

Создаем новые родительские элементы данных


Для сбора всех атрибутов S.M.A.R.T. создадим прототип мастер-элемента данных:



Как и в предыдущем примере, ничего особенного настраивать не надо. Только Тип информации – Text, а Период хранения — 1 день.

Для сбора результатов тестов и инвентарных данных нам потребуется запускать smartctl с другими ключами. Поэтому аналогично создадим еще два элемента данных:

  • uHDD.i["{#DISKNAME}"]
  • uHDD.health["{#DISKNAME}"]

Настроим получение наших атрибутов S.M.A.R.T. диска


Создадим зависимый элемент данных для атрибута 5, Reallocated:



И во вкладке «Предобработка» используем регулярное выражение:



И так же как и с JSON Path, чтобы не тратить много времени на отладку и ловлю ошибок, перед тем как заполнять regex, удобно быстро проверить правильность выражения онлайн, например здесь: regex101.com скопировав туда наш вывод smartctl.

В итоге получим такой вот список прототипов:



Тестируем, смотрим что получилось


Для двух HDD:



Для SSD под Windows:



Подведем итоги примера с smartmontools:

  • мы убрали весь парсинг из UserParameters
  • нет внешних скриптов (кроме LLD), нет внешних зависимостей, весь парсинг происходит на Zabbix-сервере, там его легко посмотреть и подправить, если нужно
  • когда утилита или API не возвращает XML/JSON – не беда, всегда можно попробовать использовать регулярные выражения
  • жесткие диски больше не мучаем – сначала достаем весь список параметров S.M.A.R.T., а затем уже на Zabbix-сервере раскладываем его по метрикам.

Обновленный шаблон (заодно обновили триггеры, добавили элементы данных для SSD) доступен на репозитории решений на share.zabbix.com здесь.

В завершении


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

P.S. Статья также доступна на английском в нашем блоге.
Zabbix
51,00
Компания
Поделиться публикацией

Похожие публикации

Комментарии 21

    0
    Спасибо за Zabbix! С нетерпением ждем внешнее хранилище для метрик.
      0
      Как правильнее собирать данные о дисках, если среди наблюдаемых машин есть как с обычными SATA-контроллерами, так и со сложными RAID-контроллерами от разных производителей. Все в одном шаблоне, или под каждый контроллер — свой шаблон?
        0
        За аппаратными RAID как правило можно наблюдать, используя утилиты от самих производителей. Но некоторые видит и smartmontools.
        www.smartmontools.org/wiki/Supported_RAID-Controllers
          0
          Через утилиты производителей — не получится централизованно. Хотелось-бы через Zabbix.
          Ко всем поддерживаемым RAID нужно обращаться по-разному. Потому и возник вопрос, как правильнее поступать с шаблонами.
            +1
            Можно завернуть все в один шаблон через LLD. Да, много возни, но все в одном месте.
              0
              +1 LLD лучший выход.
              0

              Мы в свое время писали Einarc для этого.

            0
            Вариант 1:
            Модифицировать юзерпараметр 'sudo smartctl *' для каждой машины с контроллером согласно приведённой выше ссылке.
            Вариант 2:
            Написать обёртку используя вывод утилиты производителя для имитации вывода smartctl, так же заменить юзерпараметр.

            В этих случаях получится использовать данный шаблон как с контроллерами так и без.
            +2
            > фривольный текстовый параметр
            OMG www.lmgtfy.com/?q=фривольный+значение
              –1
              Когда появится HA для zabbix-server?
                +1
                Есть ли возможность использовать массовый сбор метрик, используя агенты версий 3.0.x и более ранние версии?
                  +1

                  Конечно! Это серверная функциональность, которая не затрагивает агентов.

                  0
                  А что с потреблением диска у этой фичи? Если пилить весь вывод smartctl в varchar в innodb каждую минуту — места уходить будет весьма много.
                    +1

                    Устанавливаем "Период хранения истории" в 0. В этом случае Zabbix не будет хранить историю для конкретной метрики.

                    0
                    Как посмотреть потребленную энергию за день/месяц/год?
                      0
                      А на других счётчиках Меркурий кто-нибудь пробовал такое же? Меркурий 230, например, или какие-либо однофазные
                        0
                        Меркурий 230 — вроде точно такой же протокол. Утилита должна работать по идее. Не знаю, правда, как она отреагирует если будет три тарифа, а не два, например. Но наверняка адаптировать утилиту посильная задача.
                        0
                        Из-за того, что шаблон по дискам составлялся как универсальный (и для HDD, и для SSD), то некоторые элементы данных оказываются со статусом «Не поддерживаемый».
                        Есть ли возможность этого избежать?
                          0
                          да, есть. Но нужно использовать отдельные правила обнаружения для SSD и HDD. Планирую сделать такой шаблон в дальнейшем. Однако, уже сейчас LLD отдает метку в макросе DISKTYPE = SSD / HDD по которой можно создать такой шаблон самостоятельно.
                          +1
                          Осмелюсь предложить свой вариант реализации мониторинга UPS, работающих по протоколу Megatec (тоже JSON+Zabbix). Информацию собирал для себя, в основном столкнувшись с необходимостью контроля за UPS Энергия ПН-500 (и других этого производителя). Был взят исходник из статьи, допилен коллегой по моей просьбе, протестирован и опубликован в виде пакета для сборки в OpenWrt на GitHub. Получившийся бинарник (~5kB) легко закидывается в любое OpenWrt устройство с Zabbix агентом, без необходимости пересборки системы. Как по мне, то NUT немного «жирноват» для Embedded устройств с такими целями как получение данных с UPS с последующей передачей их в Zabbix.
                            0
                            Осмелюсь предложить свою самоделку для Меркурий 206 под OpenWrt (JSON для Zabbix умеет) — GitHub
                            Подборка некоторых ссылок и недописанные мои заметки здесь — ZFT Lab.
                            Фидбек, тесты и правки приветствуются. Спасибо!

                            Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                            Самое читаемое