Zabbix Prometheus: различия между версиями
Sirmax (обсуждение | вклад) |
Sirmax (обсуждение | вклад) |
||
Строка 252: | Строка 252: | ||
Задача - мониторить абстрактное приложение написанное на Java в Zabbix |
Задача - мониторить абстрактное приложение написанное на Java в Zabbix |
||
− | |||
− | =Запуск Java с поддержкой JMX= |
||
− | |||
− | <PRE> |
||
− | Для удобства чтениея разбито на строки, так это одна строка |
||
− | JAVA_OPTIONS=" |
||
− | -Dcom.sun.management.jmxremote=true |
||
− | -Dcom.sun.management.jmxremote.authenticate=false |
||
− | -Dcom.sun.management.jmxremote.ssl=false |
||
− | -Djava.net.preferIPv4Stack=true |
||
− | -Dcom.sun.management.jmxremote.local.only=false |
||
− | -Dcom.sun.management.jmxremote.port=8004 |
||
− | -Dcom.sun.management.jmxremote.rmi.port=8004 |
||
− | -Djava.rmi.server.hostname=ec2-XX-XX-XX-XX.eu-west-1.compute.amazonaws.com" |
||
− | " |
||
− | </PRE> |
||
− | Пример для AWS EC2 |
||
− | <PRE> |
||
− | JVM_OPTS="$JVM_OPTS -Djava.rmi.server.hostname=$(curl http://169.254.169.254/latest/meta-data/public-hostname)" |
||
− | |||
− | </PRE> |
||
− | Для инстансов без публичной сети |
||
− | <PRE> |
||
− | curl http://169.254.169.254/1.0/meta-data/hostname |
||
− | </PRE> |
||
− | или если нужно использовать IP |
||
− | <PRE> |
||
− | getent hosts $(curl http://169.254.169.254/1.0/meta-data/hostname) | awk '{print $1 }' |
||
− | </PRE> |
||
− | |||
− | |||
− | <PRE> |
||
− | WARN com.zabbix.gateway.SocketProcessor - error processing request |
||
− | com.zabbix.gateway.ZabbixException: java.rmi.ConnectException: Connection refused to host: 127.0.0.1; nested exception is: |
||
− | java.net.ConnectException: Connection refused |
||
− | at com.zabbix.gateway.JMXItemChecker.getValues(JMXItemChecker.java:98) ~[zabbix-java-gateway-3.4.13.jar:na] |
||
− | at com.zabbix.gateway.SocketProcessor.run(SocketProcessor.java:63) ~[zabbix-java-gateway-3.4.13.jar:na] |
||
− | at java.util.concurrent.ThreadPoolExecutor.runWorker(java.base@9-internal/ThreadPoolExecutor.java:1158) [na:na] |
||
− | at java.util.concurrent.ThreadPoolExecutor$Worker.run(java.base@9-internal/ThreadPoolExecutor.java:632) [na:na] |
||
− | at java.lang.Thread.run(java.base@9-internal/Thread.java:804) [na:na] |
||
− | Caused by: java.rmi.ConnectException: Connection refused to host: 127.0.0.1; nested exception is: |
||
− | java.net.ConnectException: Connection refused |
||
− | at sun.rmi.transport.tcp.TCPEndpoint.newSocket(java.rmi@9-internal/TCPEndpoint.java:619) ~[na:na] |
||
− | at sun.rmi.transport.tcp.TCPChannel.createConnection(java.rmi@9-internal/TCPChannel.java:214) ~[na:na] |
||
− | at sun.rmi.transport.tcp.TCPChannel.newConnection(java.rmi@9-internal/TCPChannel.java:200) ~[na:na] |
||
− | at sun.rmi.server.UnicastRef.invoke(java.rmi@9-internal/UnicastRef.java:130) ~[na:na] |
||
− | at java.rmi.server.RemoteObjectInvocationHandler.invokeRemoteMethod(java.rmi@9-internal/RemoteObjectInvocationHandler.java:209) ~[na:na] |
||
− | at java.rmi.server.RemoteObjectInvocationHandler.invoke(java.rmi@9-internal/RemoteObjectInvocationHandler.java:161) ~[na:na] |
||
− | at com.sun.proxy.$Proxy2.newClient(Unknown Source) ~[na:na] |
||
− | at javax.management.remote.rmi.RMIConnector.getConnection(java.management@9-internal/RMIConnector.java:2072) ~[na:na] |
||
− | at javax.management.remote.rmi.RMIConnector.connect(java.management@9-internal/RMIConnector.java:300) ~[na:na] |
||
− | at javax.management.remote.JMXConnectorFactory.connect(java.management@9-internal/JMXConnectorFactory.java:268) ~[na:na] |
||
− | at com.zabbix.gateway.ZabbixJMXConnectorFactory$1.run(ZabbixJMXConnectorFactory.java:76) ~[zabbix-java-gateway-3.4.13.jar:na] |
||
− | at java.util.concurrent.Executors$RunnableAdapter.call(java.base@9-internal/Executors.java:514) ~[na:na] |
||
− | at java.util.concurrent.FutureTask.run(java.base@9-internal/FutureTask.java:266) ~[na:na] |
||
− | ... 3 common frames omitted |
||
− | Caused by: java.net.ConnectException: Connection refused |
||
− | at java.net.PlainSocketImpl.socketConnect(java.base@9-internal/Native Method) ~[na:na] |
||
− | at java.net.AbstractPlainSocketImpl.doConnect(java.base@9-internal/AbstractPlainSocketImpl.java:405) ~[na:na] |
||
− | at java.net.AbstractPlainSocketImpl.connectToAddress(java.base@9-internal/AbstractPlainSocketImpl.java:248) ~[na:na] |
||
− | at java.net.AbstractPlainSocketImpl.connect(java.base@9-internal/AbstractPlainSocketImpl.java:230) ~[na:na] |
||
− | at java.net.SocksSocketImpl.connect(java.base@9-internal/SocksSocketImpl.java:402) ~[na:na] |
||
− | at java.net.Socket.connect(java.base@9-internal/Socket.java:591) ~[na:na] |
||
− | at java.net.Socket.connect(java.base@9-internal/Socket.java:540) ~[na:na] |
||
− | at java.net.Socket.<init>(java.base@9-internal/Socket.java:436) ~[na:na] |
||
− | at java.net.Socket.<init>(java.base@9-internal/Socket.java:213) ~[na:na] |
||
− | at sun.rmi.transport.proxy.RMIDirectSocketFactory.createSocket(java.rmi@9-internal/RMIDirectSocketFactory.java:40) ~[na:na] |
||
− | at sun.rmi.transport.proxy.RMIMasterSocketFactory.createSocket(java.rmi@9-internal/RMIMasterSocketFactory.java:144) ~[na:na] |
||
− | at sun.rmi.transport.tcp.TCPEndpoint.newSocket(java.rmi@9-internal/TCPEndpoint.java:613) ~[na:na] |
||
− | ... 15 common frames omitted |
||
− | 2018-09-03 19:54:55.449 [pool-1-thread-3] DEBUG c.z.gateway.BinaryProtocolSpeaker - sending the following data in response: {"response":"failed","error":"java.rmi.ConnectException: Connection refused to host: 127.0.0.1; nested exception is: \n\tjava.net.ConnectException: Connection refused"} |
||
− | </PRE> |
||
− | |||
− | https://www.zabbix.com/documentation/3.4/ru/manual/discovery/low_level_discovery/jmx#поддерживаемые_макросы |
||
− | https://github.com/RiotGamesMinions/zabbix_jmxdiscovery |
||
− | https://zabbix.org/wiki/ConfigureJMX |
||
− | https://jolokia.org/features-nb.html |
||
− | |||
− | |||
− | https://habr.com/company/zabbix/blog/342226/ |
||
− | https://habr.com/post/147008/ |
||
− | http://blog.arhs-group.com/post/111263584024/jmx-over-rmi-through-firewall |
Версия 12:27, 29 апреля 2019
Использование экспортеров Prometheus в Zabbix
Начиная с версии 4.2 Zabbix поддерживает работу с экспортерами Prometheus
Строго говоря это обычные HTTP метрики однако работать с ними стало более-менее удобно.
Эта заметка появилась в связи с недостатком документации
Замечание
Возможно что снимать метрики JMX в условиях интернет можно более эффективно используя нативные средства Zabbix, такие как Zabbix Proxy но этак гипотеза мной не проверялась,
Постановка задачи
- Существует приложение на Java с включенным экспортом JMX-метрик (как включить экспорт см тут: !!!! )
- Требуется снимать метрики JMX в Zabbix
- Метрики динамические (например время чтения из keyspace, имена которых заранее неизвестны), что требует Autodiscovery
- Доступ к интерфейсу JMX приложения осуществляется через интернет (задержки до 100мс)
Вероятно из-за задержек при значительном (~1000) числе метрик часть данных начинала теряться, причем заранее предсказать какая именно метрика будет потеряна нельзя. Все попытки решить проблему настройками Zabbix Java Gateway (увеличение числа потоков/Heap Size/Разные версии Gateway) к успеху не привели
Суть решения в том что вместо того что б делать медленный запрос со 100мс задержкой на каждый объект JMX, локальный экспортер делает те же запросы через localhost c ~0 RTT и отдает в ответ по HTTP все метрик в одном запросе.
Дальнейший разбор метрик происходит уже на стороне Zabbix
Prometheus Exporter
Введение в Prometheus Exporter
Prometheus использует отдельные процессы-экспортеры для сбора данных которые запускаются на хостах, и отдают данные по запросу (pull модель) по протоколу http (подробное описание Prometheus выходит за рамки этой заметки)
Для решения задачи предпологается:
- на каждом хосте с JVM запустить JMX Exporter (https://github.com/prometheus/jmx_exporter)
- Экспортер может работать как standalone HTTP сервер, те опрашивать приложение и отдавать метрики по HTTP
- Может встраиваться как агент (этот вариант я не могу использовать так как встраивание на-лету доступно только с 9-й Java а перезапуск приложений для меня недопустим)
- Со стороны Zabbix настраивается сбор метрик по HTTP
Настройка Prometheus JMX Exporter
Сборка
mvn package
или скачать готовый jar file Для запуска standalone server потребуется (с точностью до версии):
jmx_prometheus_httpserver-0.11.1-SNAPSHOT-jar-with-dependencies.jar
Конфигурация
systemd unit file
Потенциально может быть запущено несколько экземпляров экспортера, потому я подготовил юнит с поддержкой экземпляров:
/etc/systemd/system/prometheus-exporter@.service
[Unit] Description=Prometeus Exporter: %i After=network.target [Service] PIDFile=/var/run/prometheus-exporter.%i.pid Type=simple EnvironmentFile=/etc/prometheus-exporter/prometheus-exporter EnvironmentFile=/etc/prometheus-exporter/%i/env ExecStart=/usr/bin/java \ -jar ${JAR_FILE} \ ${BIND_ADDR}:${BIND_PORT} \ /etc/prometheus-exporter/%i/config.yaml SuccessExitStatus=0 143 [Install] WantedBy=multi-user.target
- /etc/prometheus-exporter/prometheus-exporter Переменные общие для всех экземпляров
- /etc/prometheus-exporter/%i/env Переменные специфичные для экземпляра
- %i - instance name , например в сервисе prometheus-exporter@localhost-cassandra %i будет заменено на localhost-cassandra
- Подробнее о других подстановках: https://www.freedesktop.org/software/systemd/man/systemd.unit.html#Specifiers
Переменные окружения общие для всех инстансов
/etc/prometheus-exporter/prometheus-exporter
JAVA="/usr/bin/java" JAR_FILE="/usr/share/jmx_exporter/jmx_prometheus_httpserver-0.11.1-SNAPSHOT-jar-with-dependencies.jar"
Пояснений не требует
Переменные окружения специфичные для инстанса
Пример для сервиса /cassandra-localhost /etc/prometheus-exporter/cassandra-localhost/env
BIND_ADDR="0.0.0.0" BIND_PORT="65001"
BIND_ADDR / BIND_PORT - адрес и порт на котором запускать HTTP сервер с метриками
Конфигурация JMX Exporter
--- hostPort: localhost:7199 username: password: #lowercaseOutputLabelNames: true #lowercaseOutputName: true whitelistObjectNames: - "java.lang:type=GarbageCollector,*" - "java.lang:type=MemoryPool,*" - "java.lang:type=Memory,*" - "java.lang:type=ClassLoading,*" - "java.lang:type=Compilation,*" - "java.lang:type=MemoryManager,*" - "java.lang:type=OperatingSystem,*" - "java.lang:type=Runtime,*" - "java.lang:type=Threading,*" - "org.apache.cassandra.metrics:type=*,scope=*,*" # ColumnFamily is an alias for Table metrics blacklistObjectNames: - "org.apache.cassandra.metrics:type=ColumnFamily,*" - "org.apache.cassandra.metrics:type=Table,keyspace=system_auth,*" - "org.apache.cassandra.metrics:type=Table,keyspace=system,*" - "org.apache.cassandra.metrics:type=Table,keyspace=*,scope=*,name=BloomFilter,*" rules: - pattern: "java.lang<type=GarbageCollector, name=(.+)><>(.+):" name: java.lang_GC type: UNTYPED labels: "gc_name": "$1" "metric_name": "$2" ... skipped...
Конфигурационный файл более-менее подробно описан на странице prometheus-exporter, повторю кратко
- hostPort: localhost:7199 Адрес и порт приложения с JMX. В общем случае JMX Exporter может быть запущен и на другом хосте, особенно в случае локальной сети или одной zone для клаудов, когда RTT между хостами невелико. В примере указан localhost - мониторится приложение запущенное на том же хосте что и exporter на порту 7199 - Cassandra
- username / password Логин/Пароль если JMX настроен с авторизацией, в примере не используется
- whitelistObjectNames: Белый список объектов
- "java.lang:type=GarbageCollector,*" Пример объекта который нужно мониторить - метрики сборщика мусора JVM
- "org.apache.cassandra.metrics:type=*,scope=*,*" Еще один объект для мониторинга
- blacklistObjectNames: Черный список (перекрывает белый список если нужно добавить исключение)
- "org.apache.cassandra.metrics:type=ColumnFamily,*"
В каком виде отдать метрики задает секция rules
- rules: Начало секции
- pattern: "java.lang<type=GarbageCollector, name=(.+)><>(.+):" Паттерн определяет какие части метрики использовать - в примере первое выражение (.+) определит имя коллектора а второе - имя метрики (или скорее тип) например CollectionCount или CollectionTime
- name: java.lang_GC Имя метрики как она будет видна в http- ответе
- type: UNTYPED Тип метрики (уточнить но скорее всего не важен для zabbix)
- labels: Метки которые будут установлены на метрику
- "gc_name": "$1" $1 соответствует первому (.+)
- "metric_name": "$2" $1 соответствует второму (.+)
Вывод http выглядит так
curl 127.0.0.1:65001 2>/dev/null | grep -v '#' | grep java_lang_GC java_lang_GC{gc_name="G1 Young Generation",metric_name="CollectionCount",} 6091.0 java_lang_GC{gc_name="G1 Young Generation",metric_name="CollectionTime",} 1360730.0 java_lang_GC{gc_name="G1 Young Generation",metric_name="Valid",} 1.0 java_lang_GC{gc_name="G1 Old Generation",metric_name="CollectionCount",} 0.0 java_lang_GC{gc_name="G1 Old Generation",metric_name="CollectionTime",} 0.0 java_lang_GC{gc_name="G1 Old Generation",metric_name="Valid",} 1.0
Полный конфиг приведен в конце статьи
Zabbix
В версии 4.2 появилась работа с Prometheus Exporter
Добавить создание всех объектов через Zabbix API - конфигурирование руками подходит только для небольших установок
Предварительная конфигурация
В текущих версиях нет возможности указать дополнительные интерфейсы вроде JMX и ссылаться на них в темплейте, приходится использовать Host Macros
Для того что бы добавить макросы к хосту
1 - Конфигурация 2 - Раздел Hosts, выбрать нужный хост 3 - Раздел макросы
Макросы которые я использую
{$PROMETEUS_EXPORTER_ADDR_0}
{$PROMETEUS_EXPORTER_PORT_0}
Обратить внимание на формат именования макросов хостов - это "{$ИМЯ_МАКРОСА}" в отличие от {#ИМЯ_МАКРОСА} в правилах автообнаружения.
Индекс _0 добавлен для поддержки будущих экспортеров, если такие будут
Создание шаблона
Все элементы добавляются к шаблону, подробно о шаблонах написано в документации Zabbix
Simple Item
Первый шаг - получить все данные
На этом простом элементе будут базироваться остальные элементы
По сути это обычный элемент данных HTTP
Единственное отличие - то что адрес для подключения читается из макроса хоста
{$PROMETEUS_EXPORTER_ADDR_0}:{$PROMETEUS_EXPORTER_PORT_0}
Остальные настройки (которые не попали на скриншот) оставлены по-умолчанию
Данные при нормальной работе выглядят примерно так (начало, показаны не все метрики)
# HELP jmx_config_reload_success_total Number of times configuration have successfully been reloaded. # TYPE jmx_config_reload_success_total counter jmx_config_reload_success_total 77.0 # HELP cassandra_Table_ReadRepairRequests_count Attribute exposed for management (org.apache.cassandra.metrics<type=Table, keyspace=KEYSPACE_NAME, scope=SCOPE_NAME, name=ReadRepairRequests><>Count) # TYPE cassandra_Table_ReadRepairRequests_count untyped cassandra_Table_ReadRepairRequests_count{Table="TABLE_NAME",keyspace="KEYSPACE_NAME",} 0.0 cassandra_Table_ReadRepairRequests_count{Table="TABLE_NAME",keyspace="KEYSPACE_NAME",} 13.0
Discovery Rule
Item Prototype
Задача - мониторить абстрактное приложение написанное на Java в Zabbix