Алгоритм действий состоит из следующих шагов:
1.Запуск Kafka-экспортера для сбора метрик с Kafka и отдачи их Prometheus-у
2.Запуск JMX-экспортера для сбора метрик с Java virtual machine-based(JVM)приложений и отдачи их Prometheus-у
3.Настройка Prometheus-а для сбора метрик с Kafka и JMX-экспортеров
4.Импортирование/настройка dashboard-ов Grafana для визуализации метрик для Kafka и JMX
5.Настрйка правил Prometheus для мониторинга Kafka и JMX показателей
1.Запуск Kafka-экспортера для сбора метрик с Kafka и отдачи их Prometheus-у
https://github.com/danielqsj/kafka_exporter
Kafka-экспортер всегда запускаем в Docker-контейнере(независимо от того, запущена Kafka в контейнера или запущена Kafka непосредственно на хосте)
Если Kafka запущена в Docker-контейнере, тогда
Kafka-экспортер запускаем в той же docker-сети, в которой и запущен kafka-контейнер,чтобы средствами докера экспортер смог разименовать имя kafka-контейнера в его IP-адрес и подключиться по этому IP-адресу для снятия с него метрик
Параметр —kafka.server определяет адрес kafka-сервера, с которого необходимо собирать метрики( по умолчанию kafka:9092 )
В данном случае kafka-контейнер имеет имя mq, поэтому значение параметра
1 |
--kafka.server равно mq:9092 |
Если Kafka запущена не в Docker-контейнере, а непостредственно на хосте, тогда для сбора метрик с Kafka можно подключаться, например, к внутреннему интерфейсу хоста, на который нужно настроить прослушивание запросов kafka
1 |
# nano path_to_kafka/config/server.properties |
1 |
listeners=PLAINTEXT://192.168.100.37:9092 |
В таком случае значение параметр —kafka.server может иметь вид
1 |
--kafka.server=192.168.100.37:9092 |
Больше информации о возможных параметрах доступно здесь
https://github.com/danielqsj/kafka_exporter
Также здесь пробрасывается порт,на котором слушает запросы kafka-exporter наружу на, например, туннельный IP-адрес(10.10.110.117) и на порт, например,9308, чтобы Prometheus смог подключиться к kafka-экспортеру для сбора метрик с него.
env-файл для docker-compose имеет вид
1 |
# cat .env |
1 |
OPENVPN_TUNNEL_MONITORING_IP=10.10.110.117 |
Если не используется docker-compose
1 |
# docker run -d --name kafka-exporter -p 10.10.110.117:9308:9308 --network services danielqsj/kafka-exporter --kafka.server=mq:9092 |
Если используется docker-compose
1 |
# nano docker-compose.yml |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
### Kafka Exporter ######################################### kafka-exporter: container_name: kafka-exporter image: danielqsj/kafka-exporter restart: unless-stopped command: ["--kafka.server=mq:9092"] #command: ["--kafka.server=192.168.100.37:9092"] ports: - "${OPENVPN_TUNNEL_MONITORING_IP}:9308:9308" networks: - services #mem_limit: 128m #mem_reservation: 64m logging: driver: "json-file" options: max-size: "5m" |
Проверка синтаксиса docker-compose-файла
1 |
# docker-compose config |
Создание и запуск kafka-exporter контейнера
1 |
# docker-compose up -d kafka-exporter |
Проверяем наличие запущенного kafka-exporter контейнера, который будет собирать метрики с redis-контейнера
1 |
# docker ps | grep redis-exporter |
1 |
3afec4e558a1 danielqsj/kafka-exporter "/bin/kafka_exporter…" 35 seconds ago Up 34 seconds 10.10.110.117:9308->9308/tcp |
1 |
# netstat -nlptu | grep 9308 |
1 |
tcp 0 0 10.10.110.117:9308 0.0.0.0:* LISTEN 39843/docker-proxy |
С хоста, на котором запущен kafka-контейнер проверяем доступность метрик с kafka-экспортера
Список показателей достаточно длинный, поэтому просто вывел их количество
1 2 |
# curl -s 10.10.110.117:9308/metrics | grep -E "^kafka" | wc -l 26 |
С мониторинг хоста получаем такой же успешный ответ
1 2 |
# curl -s 10.10.110.117:9308/metrics | grep -E "^kafka" | wc -l 26 |
2.Запуск JMX-экспортера для сбора метрик с Java virtual machine-based(JVM) и отдачи их Prometheus-у
https://github.com/prometheus/jmx_exporter
Для загрузки jmx-экспортера и его конфигурационного файла выполним скрипт
1 |
# cat jmx-kafka-exporter.sh |
1 2 3 4 5 6 7 8 9 10 11 12 13 |
#!/bin/bash DEST_DIR="/opt/kafka/prometheus" SYSTEM_USER="mysystemuser" JMX_EXPORTER_JAVAAGENT_VERSION=0.12.0 JMX_EXPORTER_KAFKA_CONFIG_VERSION=2_0_0 mkdir -p ${DEST_DIR} && \ wget -q -O ${DEST_DIR}/jmx_prometheus_javaagent-${JMX_EXPORTER_JAVAAGENT_VERSION}.jar https://repo1.maven.org/maven2/io/prometheus/jmx/jmx_prometheus_javaagent/${JMX_EXPORTER_JAVAAGENT_VERSION}/jmx_prometheus_javaagent-${JMX_EXPORTER_JAVAAGENT_VERSION}.jar && \ wget -q -O ${DEST_DIR}/kafka-${JMX_EXPORTER_KAFKA_CONFIG_VERSION}.yml https://raw.githubusercontent.com/prometheus/jmx_exporter/master/example_configs/kafka-${JMX_EXPORTER_KAFKA_CONFIG_VERSION}.yml chown -R ${SYSTEM_USER}:${SYSTEM_USER} /opt/kafka |
Если Kafka-запускается в Docker, тогда встараиваем JMX-экспортера путем передачи опции KAFKA_OPTS в виде переменной, в которой указываем jmx-экспортер
Например:
1 |
# nano docker-compose.yml |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
mq: build: context: ./mq args: - JMX_EXPORTER_JAVAAGENT_VERSION=${JMX_EXPORTER_JAVAAGENT_VERSION} - JMX_EXPORTER_KAFKA_CONFIG_VERSION=${JMX_EXPORTER_KAFKA_CONFIG_VERSION} depends_on: - zookeeper environment: KAFKA_ADVERTISED_HOST_NAME: mq KAFKA_ADVERTISED_PORT: 9092 KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181 KAFKA_OPTS: "-javaagent:/opt/kafka/prometheus/jmx_prometheus_javaagent-${JMX_EXPORTER_JAVAAGENT_VERSION}.jar=9141:/opt/kafka/prometheus/kafka-${JMX_EXPORTER_KAFKA_CONFIG_VERSION}.yml" volumes: - /var/run/docker.sock:/var/run/docker.sock networks: - services ports: - "${OPENVPN_TUNNEL_MONITORING_IP}:9141:9141" |
env-файл для docker-compose имеет вид
1 |
# cat .env |
1 2 3 |
OPENVPN_TUNNEL_MONITORING_IP=10.10.110.117 JMX_EXPORTER_JAVAAGENT_VERSION=0.12.0 JMX_EXPORTER_KAFKA_CONFIG_VERSION=2_0_0 |
Если Kafka-запускается запускается не в Docker, а через запуск бинарника непоредственно на хосте:
https://github.com/apache/kafka, тогда добавляем jmx-экспортер в bash-скрипт
1 |
# less /path_to_kafka/bin/kafka-server-start.sh |
1 2 |
#EXTRA_ARGS=${EXTRA_ARGS-'-name kafkaServer -loggc'} EXTRA_ARGS=${EXTRA_ARGS-'-name kafkaServer -loggc -javaagent:/opt/kafka/prometheus/jmx_prometheus_javaagent-0.12.0.jar=10.10.110.117:9141:/opt/kafka/prometheus/kafka-2_0_0.yml'} |
Проверяем доступность порта jmx-экспортера и получение с него метрик
1 |
# netstat -nlptu | grep 9141 |
1 |
tcp 0 0 10.10.110.117:9141 0.0.0.0:* LISTEN 38456/java |
1 |
# curl -s 10.10.110.117:9141/metrics | grep -E 'jvm' | wc -l |
1 |
96 |
3.Настройка Prometheus-а для сбора метрик с Kafka и JMX-экспортеров
Добавляем kafka-экпортер в service discovery файл
1 |
# nano prometheus/sd/targets-kafka-exporter.yml |
1 2 3 4 5 |
- targets: - kafkaserver:9308 labels: env: staging job: kafka-exporter |
Добавляем jmx-экcпортер в service discovery файл
1 |
# nano prometheus/sd/targets-jmx-kafka-exporter.yml |
1 2 3 4 5 |
- targets: - kafkaserver:9141 labels: env: staging job: jmx-kafka-exporter |
Подключаем эти service discovery файлы в Prometheus
1 |
# nano prometheus/prometheus.yml |
1 2 3 4 5 6 7 8 9 |
- job_name: 'kafka-exporter' file_sd_configs: - files: - sd/targets-kafka-exporter.yml - job_name: 'jmx-kafka-exporter' file_sd_configs: - files: - sd/targets-jmx-kafka-exporter.yml |
Проверка синтаксиса конфиг.файла Prometheus и файлов с правилами
1 |
# (cd /home/myusername/monstack && ../prometheus-2.10.0.linux-amd64/promtool check config ./prometheus/prometheus.yml && echo OK || echo FAIL) |
Перечитываем конф.файл Prometheus
1 |
# curl -X POST https://adminuser:adminpassword@prometheus.mydomain.com /-/reload |
После чего проверяем в Prometheus наличие новой цели для мониторинга
1 |
Prometheus->Status->Target |
4.Импортирование/настройка dashboard Grafana для визуализации метрик
Импортируем дашбоард отсюда
для Kafka-exporter(https://github.com/danielqsj/kafka_exporter)
https://grafana.com/grafana/dashboards/7589
Я изменил его под свои задачи
kafka_dashboard.config
Также создал kafka-jmx-dashboard на основе jmx-экспортера (https://github.com/prometheus/jmx_exporter)
kafka_jmx_dashboard.config
5.Настройка правил Prometheus для мониторинга Kafka и JMX -показателей
В качестве источника для создания правил была выбраны статьи:
https://blog.serverdensity.com/how-to-monitor-kafka
https://www.datadoghq.com/blog/monitoring-kafka-performance-metrics
Добавляем несколько правил для мониторинга Kafka и JMX -показателей
1.Количество kafka-брокеров (kafka_number_broker)
2.Количество ордеров orders1 в топике topicname1 (kafka_number_orders1)
3.Количество ордеров orders2 в топике topicname2 (kafka_number_orders2)
4.Количество under-replicated partitions(kafka_topic_partition_under_replicated_partition)
5.Количество partition-ов без активного лидира (такие partition недоступны как на чтение, так и на запись)(kafka_offline_partitions_count)
6.Количество активных broker-контроллеров(kafka_active_controller_count)
7.LeaderElectionRateAndTimeMs reports the rate of leader elections (per second) and the total time the cluster went without a leader (in milliseconds).(kafka_leader_election_rate_and_timems)
8.Количество partitions в системе( kafka_partitions_count)
9.When a broker goes down, ISR will shrink for some of the partitions. When that broker is up again, ISR will be expanded once the replicas have fully caught up. (kafka_isrshrinks_isrexpands_rate)
10.The average fraction of time the network processors are idle. (kafka_network_processor_avg_idle_percent)
11.Использование оперативной памяти(kafka_memory_usage)
1 |
# nano prometheus/services_rules.yml |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
########## Kafka ########## - name: kafka rules: - alert: kafka_number_broker expr: kafka_brokers{job="kafka-exporter"} == 0 for: 60s labels: severity: critical annotations: summary: "Critical: Kafka number available broker too many(=0) on the instance {{ $labels.instance }} for more than 1 minutes" description: "Kafka number brokers are {{ $value }}" - alert: kafka_number_orders1 expr: rate(kafka_topic_partition_current_offset{job="kafka-exporter",topic="topicname1"}[1m]) == 0 for: 60s labels: severity: critical annotations: summary: "Critical: Kafka number orders1 too small(=0) on the instance {{ $labels.instance }} for more than 1 minutes" description: "Kafka number orders1 are {{ $value }}" - alert: kafka_number_orders2 expr: rate(kafka_topic_partition_current_offset{job="kafka-exporter",topic="topicname2"}[1m]) == 0 for: 60s labels: severity: critical annotations: summary: "Critical: Kafka number orders2 too small(=0) on the instance {{ $labels.instance }} for more than 1 minutes" description: "Kafka number orders2 are {{ $value }}" - alert: kafka_topic_partition_under_replicated_partition expr: kafka_topic_partition_under_replicated_partition{job="kafka-exporter"} > 0 for: 60s labels: severity: critical annotations: summary: "Critical: Kafka topic partition under replicated partition(>0) on the instance {{ $labels.instance }} for more than 1 minutes" description: "Kafka topic partition under replicated partition are {{ $value }}" - alert: kafka_offline_partitions_count expr: kafka_controller_kafkacontroller_offlinepartitionscount{job="jmx-kafka-exporter"} > 0 for: 60s labels: severity: critical annotations: summary: "Critical: Kafka offline partitions count(>0) on the instance {{ $labels.instance }} for more than 1 minutes" description: "Kafka offline partitions count are {{ $value }}" - alert: kafka_active_controller_count expr: kafka_controller_kafkacontroller_activecontrollercount{job="jmx-kafka-exporter"} !=1 for: 60s labels: severity: critical annotations: summary: "Critical: Kafka active controller count(!=1) on the instance {{ $labels.instance }} for more than 1 minutes" description: "Kafka active controller count are {{ $value }}" - alert: kafka_leader_election_rate_and_timems expr: kafka_controller_controllerstats_leaderelectionrateandtimems{job="jmx-kafka-exporter",quantile="0.999"} !=0 for: 60s labels: severity: critical annotations: summary: "Critical: Kafka number of disputed leader elections rate(!=0) on the instance {{ $labels.instance }} for more than 1 minutes" description: "Kafka number of disputed leader elections rate are {{ $value }}" - alert: kafka_partitions_count expr: kafka_server_replicamanager_partitioncount{job="jmx-kafka-exporter"} !=3 for: 60s labels: severity: critical annotations: summary: "Critical: Kafka number of partitions (!=3) on the instance {{ $labels.instance }} for more than 1 minutes" description: "Kafka number of partitions are {{ $value }}" - alert: kafka_isrshrinks_isrexpands_rate expr: irate(kafka_server_replicamanager_isrshrinks_total{job="jmx-kafka-exporter"}[1m]) !=0 OR irate(kafka_server_replicamanager_isrexpands_total{job="jmx-kafka-exporter"}[1m]) !=0 for: 60s labels: severity: critical annotations: summary: "Critical: Kafka number of isrshrinks or isrexpands (!=0) on the instance {{ $labels.instance }} for more than 1 minutes" description: "Kafka number of isrshrinks or isrexpands are {{ $value }}" - alert: kafka_network_processor_avg_idle_percent expr: (kafka_network_socketserver_networkprocessoravgidlepercent) * 100 < 30 for: 60s labels: severity: critical annotations: summary: "Critical: Kafka network processor avg idle percent (<30%) on the instance {{ $labels.instance }} for more than 1 minutes" description: "Kafka network processor avg idle percent are {{ $value }}%" - alert: kafka_memory_usage expr: ((sum without(area)(jvm_memory_bytes_used{job='jmx-kafka-exporter'}) / 1024 / 1024) / (sum without(area)(jvm_memory_bytes_max{job='jmx-kafka-exporter'}) / 1024 / 1024)) * 100 > 70 for: 60s labels: severity: critical annotations: summary: "Critical: Kafka high memory usage (>70%) on the instance {{ $labels.instance }} for more than 1 minutes" description: "Kafka memory usage is {{ $value }}%" |
Проверка синтаксиса конфиг.файла Prometheus и файлов с правилами
1 |
# (cd /home/myusername/monstack && ../prometheus-2.10.0.linux-amd64/promtool check config ./prometheus/prometheus.yml && echo OK || echo FAIL) |
Перечитываем конф.файл Prometheus
1 |
# curl -X POST https://adminuser:adminpassword@prometheus.mydomain.com/-/reload |
После чего в Prometheus→Alerts появляются добавленные правила
Источник:
https://github.com/danielqsj/kafka_exporter
https://github.com/prometheus/jmx_exporter
https://blog.serverdensity.com/how-to-monitor-kafka
https://www.datadoghq.com/blog/monitoring-kafka-performance-metrics
https://grafana.com/grafana/dashboards/7589