Мониторинг RabbitMQ в  Zabbix и скрытые возможности Zabbix key

Вступление


    Столкнувшись с задачей замониторить большое кол-во метрик в RabbitMQ кластере, появилось желание создать универсальный парсер для JSON данных. Задача усложнялась тем, что появляются и пропадают метрики динамически во время работы кластера, плюс к этому разработчики постоянно хотят собрать/посчитать что-то новое. К сожалению, в Zabbix нет возможности собирать данные в таком виде из коробки. Но есть такая удобная фича как zabbix_trapper, позволяющая делать гибкую кастомизацию. В статье пойдет речь о не сосвем стандартном способе использовании айтемов zabbix_trapper. Мне не хотелось каждый раз, когда разработчики попросят добавить новых метрик, изменять скрипт, который собирает данные и засылает в заббикс. Отсюда появилась идея использовать собственно сам zabbix key как инструкцию по сбору новой метрики. Суть в следующем, мы используем zabbix key как команду, с заранее заданным синтакисом. То есть zabbix key в этом случае будет служить инструкцией, подобной ключам типа zabbix_agent.

    Согласно официальной документации Zabbix, item key имеет некоторые ограничения на допустимые символы. Немного поиграв с созданием ключей типа zabbix trapper нашел, что к примеру ключ вида:

some.thing.here[one:two:three][foo=x,bar=y]

создаются в заббиксе без ошибок. То есть ограничения работают только на то, что вне [ ] скобок, также обязательно должен быть хотя бы один символ [a-z][A-Z] перед скобками. Имея возможность создавать такие ключи мы можем придумать свой синтаксис ключей и запрограммировать в нем довольно гибкую логику. Далее остается только написать обработчик придуманного синтаксиса который будет делать всю основную работу. И наконец, написав доку по этому обработчику и выложив код в паблик, у всего Zabbix community появится возможность обмениваться такими «как бы» плагинами.

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

    Ссылки на код приведены в конце статьи.

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


    Сначала создаем в Zabbix фронт-енде айтемы типа zabbix_trapper согласно разработанному синтаксису(синтксис будет описан ниже). Далее запускаем обработчик (rmq_data_collect.pl — далее коллектор) в кроне с частотой сбора информации, скажем 1 минута. Теперь коллектор взаимодействует с Zabbix сервером и с сервером RabbitMQ как указано на схеме:

Т.е. скрипт делает 3 основных шага:

1) Запрашивает список айтемов с Zabbix сервера, которые должны быть собраны.
2) Забирает все необходимые данные с RabbitMQ согласно списку айтемов выше.
3) Отправляет все собранные данные на Zabbix сервер/прокси на соотв-ие айтемы.

    При первом обащении обработчик может взаимодействовать как через Zabbix API так и напрямую с базой. В моей реалзации взаимодействие происходит с базой Zabbix прокси. Этот подход удобней при использовании распределенного мониторинга с некоторым кол-вом Zabbix прокси серверов. В этом случае скрипт должен быть установлен на zabbix прокси сервере, а в конфигурации скрипта должны быть прописаны данные для коннекта к базе этой же прокси.

    Кроме обработчика будет также рассмотрен еще дискаверер, который используется для low level discovery. Далее пойдет речь о текущей реализации мониторинга для RabbitMQ, теория и примеры настройки.

Что реализовано


    В документации по RabbitMQ API описано 9 API url’ов + есть еще federation-links, который ставится отдельным плагином на реббит. Возможно есть и еще что-то. В текущей реализации моих скриптов возможен мониторинг следующих API path:

-nodes
-connections
-queues
-bindings
-federation-links

Для моих задач этого хватило, в случае если нужны еще какие-то API path то нужно дописать их в ф-ю map_rmq_elements (см. комментарии к коду).

Установка и настройка скриптов


    Для мониторинга RabbitMQ понадобится установить и настроить 2 скрипта (Collector и Discoverer) + ZabbixProxyDB.pm. Скрипты могут быть установлены как на Zabbix сервере так и на прокси, зависит от вашей конфигурации Zabbix.

Collector

rmq_data_collect.pl — Используется для обработки заббикс ключей и сбора данных с rabbitmq.

Использование

Имеет один входной параметр

$1 — полное имя RabbitMQ хоста в Zabbix, если RabbitMQ не запущен как кластер. В случае если реббит работает как кластер, $1 — это общая часть имени хостов в кластере, т.е. имена хостов в класере должны быть заданы по определенному правилу. Например имена хостов в кластере:
— rmq-host1
— rmq-host2
— rmq-host3
    В этом случае $1 должен быть “rmq-host". Скрипт запросит у Zabbix сервера/прокси список все хостов с именами, содержащими «rmq-host”, после чего пойдет по этому списку, запрашивая необходимые данные к RabbitMQ API. После первого успешного ответа от любого из хостов данные будут собраны и записаны в файл для отправки zabbix_sender’ом. На момент написания статьи имеется недоработка в коде, в случае если не один хост из кластера RabbitMQ не ответит то ничего не произойдет. В текущей реализации требования к именам хостов связаны с SQL запросом в базу, пока только так.
    Коллектор должен быть прописан в crontab с частотой равной частоте сбора данных с реббита. Список необходимых модулей можно посмотреть в самом скрипте.

Discoverer

rmq_data_discover.pl — Используется для низкоуровневого обнаружения в Zabbix (low level discovery или LLD).

Использование
Имеет 3 обязательных входных параметра:

$1 — полное имя RabbitMQ хоста в Zabbix, если RabbitMQ не запущен как кластер. Для кластера принцип тот же что у коллектора. После первого успешного ответа прохождение по списку остановится и начнется компиляция сообщения для низкоуровневого обнаружения (low level discovery).

$2 — regexp по которому произойдет отбор метрик в момент работы скрипта. Не путать с regexp фильтром на стороне Заббикс в настройках LLD. Такое разделение удобно в некоторых случаях.

$3 — RabbitMQ API path, любой из списка поддерживаемых (см. п. Что реализовано).

    Скрипт должен быть установлен в папку externalscripts, прописанную в конфигурации Zabbix прокси/сервера. Примеры настройки правил LLD приведены в конце статьи.

Пример конфигурации хостов в Zabbix

    Есть кластер rabbitmq состоящий из трех хостов. Сами хосты по отдельности мониторятся заббикс агентами, темплейт Template_Linux, где собраны стандартные метрики по CPU, memory и т.д. Для метрик кластера создан отдельный хост ”rmq-host». Имя хоста для всего кластера — общая часть имен хостов в кластере. Это обязательное условие в текущей реализации, иначе выборка из базы будет работать не корректно.


Синтаксис ключей


Теперь поговорим о разработанном мной синтаксисе для реббита. Как уже было сказано выше, в Zabbix айтемы должны иметь тип zabbix trapper.

Для мониторинга реббита Есть два типа item'ов, simple и aggregated, их синтаксис незначительно отличается. Simple айтемы используются для выборки значений отдельных параметров. Aggregated айтемы используются для выборки массива значений по заданному условию и их аггрегации. В обоих случаях условия может быть не указано(опционально).

Значения Simple

Синтаксис: <path.to.value.inside.json>[$type:$api_path:$element_name]

<path.to.value.inside.json> — Путь к значению внутри каждого элемента массива.

$type — может быть название VHOST или “general”, в случае VHOST поиск значений будет вестись по указанному VHOST, «general” — является ключевым словом, необходимым для значений, которые не относятся к конкретным VHOST’ам.

$api_path — RabbitMQ API path, любой из поддерживаемых (см. п. Что реализовано).

$element_name — это уникальный идентификатор элемента массива в указанном $api_path, для federation-links это exchange, для bindings это destination, для остальных name.

Значения Aggregated

Общий синтаксис: <path.to.value.inside.json|rmq>[aggregated:$api_path:$func][$conditions]

aggregated — является ключевым словом, после которого коллектор(rmq_data_collect.pl) понимает что синтаксис ключа должен быть разобран как для значения типа aggregated.

$api_path — путь к API, любой из поддерживаемых (см. п. Что реализовано).

$func — реализованы 2 функции, sum и count.

$conditions — опциональный параметр, если задан, то при аггрегации будут учитываться только те элементы в массиве данных, которые подходят под условие. Синтаксис условий следующий: [condition1=“cond1”,condition2=“cond2”,condition3=“cond3”,etc]. Кавычки обязательны. Само условие является Perl регекспом.

Функция sum
Синтаксис: <path.to.value.inside.json>[aggregated:$api_path:sum][$conditions]

Функция sum суммирует значения находящиеся по указанному пути <path.to.value.inside.json> внутри каждого элемента массива, полученного по $api_path, и подходящего под условие $conditions.

<path.to.value.inside.json> — Путь к значению внутри каждого элемента массива полученного по RabbitMQ API path.

Функция count

Синтаксис: rmq[aggregated:$api_path:count][$conditions]

Функция count считает кол-во элементов в массиве, полученном по $api_path, подходящих под условие .

rmq — является обязательным словом, но никак не используется(тут может быть абсолютно любой набор букв). Это связано с ограничениями Zabbix на ключ айтема типа “zabbix_trapper” — айтем не может начинаться с квадратной скобки.

Примеры


Агрегированые значения

1) Считает сумму элементов running в массиве nodes. Прим: В случае если rabbitmq нода работает, running возвращает 1, соот-но на выходе получаем кол-во работающих нод.

2) Считает кол-во элементов в массиве queues, где name = ^system-queue1$. Т.к. значение условия всегда рассматривается как regexp необходимо задавать начало и конец строки (^ $) чтобы избежать ошибки в случае, если под regexp попадет что-то еще. На выходе получаем кол-во очередей с именем system-queues1

3) Считает общее кол-во элементов в массиве nodes. Т.е. кол-во настроенных нод в класетере.

4) Считает общее кол-во элементов в массиве connections. Т.е. кол-во соединений к кластеру в данный момент.

5) Считает кол-во элементов в массиве connections, у которых type=“^direct$” и protocol=»^Direct\s0-9-1$”.

Примеры для значений simple есть дальше в LLD. Т.к. задавать их статически не удобно, большинство очередей постоянно появляются и исчезают.

Low level discovery


В слуачае большой конфигурации rabbitmq кластера разумно будет использовать низкоуровневое обнаружение Zabbix. Использование rmq_data_discover.pl описано выше. Здесь я приведу примеры и значения возвращаемые скриптом.

Значение, возвращаемые скриптом и которые можно использовать в LLD:

Connections

"{#VHOST}" => $vhost,
"{#NAME}" => $name,
"{#NODE}" => $node,

Nodes

"{#NODENAME}" => $name,

Bindings

"{#SOURCE}" => $queueSource,
"{#VHOST}" => $vhost,
"{#DESTINATION}" => $queueDest,
"{#THRESHOLD}" => $threshold,

Замечание: все элементы с пустым source игнорируются.

Queues

"{#VHOST}" => $vhost,
"{#QUEUE}" => $queueName,

Federations

“{#VHOST”} => $vhost,
“{#EXCHANGE} => $name

Примеры LLD


Примеры запуска правил для каждого API path:



Примеры айтем прототипов

В API path queues мы можем собирать статистику по обработанным сообщениям, не заботясь о кол-ве очередей.



1) Значение поля idle_since. Единственное поле которое имеет обработку внутри rmq_data_collector.pl. Как результат получаем timestamp, с момента которого очередь неактивна.

2) Значение ack внутри элемента message_stats.

3) Оставшиеся значения работают с message_stats также как п.2

Пример для connections



Айтем подсчитывает кол-во элементов в массиве connections с заданными type,protocol для каждого {#VHOST}.

Пример для nodes



1) Считает кол-во соединений к каждой ноде.
2) Возвращает значение поля running для каждого элемента массива nodes. На выходе получаем health статус каждой ноды.

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


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

    Преимущество описанного подхода в создании кастомных ключей, специализированных для какого то конкретного софта, очевидно. Нет необходимости в изменении кода самого Zabbix. Уже сейчас мы можем создавать такие плагины, писать по ним документацию и обмениваться готовыми решениями в интернете. Если развивать идею создания кастомизированных ключей в Zabbix дальше, то в идеале хотелось бы видеть это, возможно, в виде новой фичи. Имея подобный плагин теперь, когда нужно добавить какуюто новую метрику по RabbitMQ, нужно просто создать соотв-ий айтем, как это делается для zabbix_agent.

    Код скриптов тут: github.com/mfocuz/zabbix_plugins
  • +17
  • 14,1k
  • 7
Поделиться публикацией
Похожие публикации
Ой, у вас баннер убежал!

Ну. И что?
Реклама
Комментарии 7
  • +1
    Прошу простить мои слова. Но я проникся сочувствием и соболезнованием.
    У меня было:
    — порядка 100-150 метрик с сервера (с разными интервалами опроса), всего 16 серверов
    — потребность делать, часто, кастомные графики и дашборды, в том числе более менее рилтайм графики
    — возможность делать графики программерам.

    Получилось(при заведении ~70% метрик):
    — перегруженный постгрес, в основном на запись, а сервачек простите с 15к sas дисками был. (думаю можно было бы заоптимизировать, но напурква на это тратить время)
    — с графиками жопа, в основном, конечно, удобство построения. Отдать этот инструмент не админам в команде — нельзя
    — за 2 недели база выросла до 6 гигов

    В результате перешел на связку sensu+graphite, сейчас порядка 40 серверов, в среднем около 200 метрик на сервер. Мониторинг крутится на относительно старом серваке с 10к SCSI дисками (что-то вроде dl120 g3-g4).

    PS В моем случае, одно из самых объемных, в плане данных, и в плане рилтаймовости, был как раз мониторинг самого rabbitmq :)
    PPS Меня не спасли ни прокси, ни передача данных через rabbitmq, только я на пиотоне обвязку делал.
    • 0
      перегруженный постгрес, в основном на запись
      Это с включенным Housekeeper или с выключенным?
      • 0
        Выключенным. Система поднималась для сравнения с другими вариантами. Через неделю стало понятно, что слищком много вопросов, а через три недели отказались, так как нагрузки не выдержит, а покупать железо и тратить время на оптимизацию было не интересно.

        К тому же количество метрик у нас росло. Сейчас порядка 220 на сервер (это только метрики, без чеков).
        • 0
          Зависит от частоты опроса, но со сбором 8000 (40*200) метрик раз в 30-60 секунд Заббикс справится даже на Raspberry Pi. Да, хранение истории требует дисков и более мощного железа, но тут мы сами выбираем: либо нам нужны гигабайты истории либо нет. Это справедливо и для альтернативных систем мониторинга.
          • 0
            да безусловно. Хотя у меня, метрики делятся на два типа: с опросом: от 0,05s до 120s, по большей части 1-5s, и метрики приложение кидает само (например через statsd), тут бывает 150-200 значений в секнуду на ~50 метрик.
            Я уже где-то писал тут. Zabbix нельзя тольком масштабировать горизонтально. В любом случае БД будет бутылочным горлышком. Для меня решения вроде sensu+graphite проще, нагляднее, а главное масштабировать не сложно и нет явного бутылочного горлышка.
            • 0
              Вообще статья была о некотором хаке в функциональность Zabbix и не затрагивала вопросы производительности… Это на случай если вы прочитали только заголовок а дальше воспользовались полосой прокрутки.
    • 0
      Путь к исходникам немного изменился, теперь здесь: github.com/mfocuz/zabbix_plugins/tree/master/rabbitmq

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

      Самое читаемое
      Интересные публикации