Мониторинг Apache ZooKeeper с помощью Proto Observability
На этой странице:
- Сбор метрик ZooKeeper
- Сбор логов ZooKeeper
Сбор метрик ZooKeeper
Интеграция zk собирает метрики Apache ZooKeeper по протоколу
four-letter-words на клиентском порту (по умолчанию 2181) — без JMX и без
HTTP. Проверка опрашивает:
mntr— основной источник метрик (zookeeper_znode_count,zookeeper_watch_count,zookeeper_num_alive_connections,zookeeper_outstanding_requests, гистограммы latency и т.д.);stat—zookeeper_connections,zookeeper_latency_avg/zookeeper_latency_min/zookeeper_latency_max,zookeeper_nodes,zookeeper_zxid_count/zookeeper_zxid_epoch;ruok— сервис-проверкаzookeeper_ruok(жив ли сервер) и определение режима узла для сервис-проверкиzookeeper_mode.
Покрываются автономный сервер (standalone) и узлы ансамбля (leader / follower / observer). Часть метрик доступна только начиная с ZooKeeper 3.6.
four-letter-words whitelist
Начиная с ZooKeeper 3.5 four-letter-words отключены по умолчанию, кромеsrvr.
Чтобы интеграция могла собрать метрики, добавьте как минимум mntr (а
заодно ruok и stat — на них строятся сервис-проверка zookeeper_ruok и часть
метрик) в 4lw.commands.whitelist (см. ниже). Без этого проверка запустится, но
бо́льшая часть метрик будет отсутствовать.Конфигурация ZooKeeper
Разрешите нужные four-letter-words и убедитесь, что клиентский порт доступен с хоста, на котором работает агент.
В conf/zoo.cfg добавьте (или дополните) строку:
4lw.commands.whitelist=srvr,mntr,ruok,stat,cons,wchs
Можно указать 4lw.commands.whitelist=*, чтобы разрешить все — но в проде
ограничьтесь нужным набором. Клиентский порт задаётся clientPort=2181.
После правок перезапустите ZooKeeper.
Официальный образ zookeeper пробрасывает whitelist через переменную
ZOO_4LW_COMMANDS_WHITELIST:
services:
zookeeper:
image: zookeeper:3.9
environment:
ZOO_4LW_COMMANDS_WHITELIST: "srvr,mntr,ruok,stat,cons,wchs"
ports:
- "2181:2181" # клиентский порт
- "8080:8080" # AdminServer (встроенный Jetty) — опционально
Встроенный AdminServer (Jetty на 8080) включён по умолчанию и даёт те же
команды по HTTP (/commands/mntr, /commands/srvr, …) — для интеграции zk
он не используется, но удобен для отладки.
Конфигурация ProtoOBP агента
Если агент запускается в виде службы на хосте
Создайте файл
/etc/protoobp-agent/conf.d/zk.d/conf.yaml:init_config: instances: - host: localhost port: 2181 # timeout: 3 # таймаут чтения 4lw-ответа, сек (по умолчанию 3) # сообщать режим узла отдельной метрикой (zookeeper_instances_<mode> = 1) # и добавлять тег mode:<leader|follower|observer|standalone> на все метрики report_instance_mode: true # сервис-проверка zookeeper_mode = OK, если режим совпадает с ожидаемым expected_mode: standalone # leader / follower / observer / standalone # tags: # - "cluster:zk-prod" # use_tls: false # включите, если клиентский порт под TLS # tls_ca_cert: /path/to/ca.pem # tls_cert: /path/to/client.pem # tls_private_key: /path/to/client.keyПерезапустите агента:
systemctl restart protoobp-agent.
Если агент запускается в виде Docker контейнера
Добавьте autodiscovery-лейблы к контейнеру ZooKeeper. В docker-compose.yaml:
services:
zookeeper:
labels:
com.protoobp.ad.check_names: '["zk"]'
com.protoobp.ad.init_configs: '[{}]'
com.protoobp.ad.instances: '[{"host": "%%host%%", "port": 2181, "report_instance_mode": true, "expected_mode": "standalone"}]'
Контейнер агента
Контейнер агента должен находиться в той же docker network, что и ZooKeeper. Также агенту нужен смонтированный/var/run/docker.sock:/var/run/docker.sock:ro
для autodiscovery контейнеров. Суффикс -jmx у образа агента не нужен —
zk работает по four-letter-words, не по JMX.Проверка
Убедитесь, что проверка запустилась и собирает метрики:
docker exec protoobp-agent agent status | grep -A 11 '^ zk ('
Ожидаемый вывод — instance в состоянии [OK] и ненулевой Metric Samples:
zk (4.2.0)
----------
Instance ID: zk:a064338738fe3ed5 [OK]
Configuration Source: container:docker://de71e775fef2acc5723d04e9c2037118fab5d714683addeeb22b8b81c1ddb8bb
Total Runs: 12
Metric Samples: Last Run: 738, Total: 6,651
Events: Last Run: 0, Total: 0
Service Checks: Last Run: 2, Total: 23
Average Execution Time : 24ms
metadata:
version.major: 3
version.minor: 9
version.patch: 5
Список метрик и сервис-проверок, которые отдаёт проверка прямо сейчас:
docker exec protoobp-agent agent check zk
На ZooKeeper 3.9 в standalone-режиме за прогон собирается порядка 700–760 серий,
плюс сервис-проверки zookeeper_ruok и zookeeper_mode в состоянии OK.
Собираемые метрики
Все метрики собираются по протоколу four-letter-words и имеют тип gauge —
содержат мгновенное значение на момент сбора. Многие значения, отдаваемые
ZooKeeper как монотонные счётчики (*_count, connection_drop_count,
outstanding_changes_* и т.п.), интеграция не конвертирует в rate —
дельту нужно считать на стороне дашборда/алерта. Для каждой гистограммы из
mntr (ZooKeeper 3.6+: *latency, *_watch_count, …) интеграция публикует
семейство метрик с префиксами avg_, min_, max_, cnt_, sum_, p50_,
p95_, p99_, p999_ (например zookeeper_avg_updatelatency,
zookeeper_p99_propagation_latency).
В ProtoOBP backend имена метрик хранятся в Prometheus-стиле — точки заменены
на подчёркивания (zookeeper_outstanding_requests, zookeeper_latency_avg,
zookeeper_zxid_count и т.д.). Именно в таком виде они приведены ниже и под
ними их видно на дашбордах и в алертах.
Ниже — ключевые метрики; полный набор зависит от версии ZooKeeper (на 3.9 интеграция отдаёт ~700–760 серий за прогон).
Лейблы
Общие (на всех метриках)
Добавляются агентом и ProtoOBP backend’ом:
| Лейбл | Значение |
|---|---|
host | Хост, на котором работает агент |
service | Тег service (через com.protoobp.tags.service или POBP_TAGS) |
env | Тег env |
docker_image | Полный ref образа контейнера (например, zookeeper:3.9) |
image_name | Имя образа без тега |
image_tag | Тег образа |
short_image | Короткое имя образа |
Специфичные для ZooKeeper
| Лейбл | Где появляется | Пример |
|---|---|---|
mode | на всех метриках, если задано report_instance_mode: true | standalone, leader, follower, observer |
port | на сервис-проверках zookeeper_ruok / zookeeper_mode | 2181 |
host | на сервис-проверках — адрес опрашиваемого ZooKeeper | 172.19.0.3 |
Метрики уровня сервера
| Имя метрики | Единица | Описание |
|---|---|---|
zookeeper_nodes | node | Количество znode’ов в пространстве имён (из stat) |
zookeeper_znode_count | node | Количество znode’ов (из mntr) |
zookeeper_ephemerals_count | node | Количество эфемерных znode’ов |
zookeeper_approximate_data_size | byte | Примерный объём данных в дереве znode’ов |
zookeeper_watch_count | watch | Количество зарегистрированных watch’ей |
zookeeper_outstanding_requests | request | Количество запросов в очереди (растёт, когда сервер не успевает обрабатывать поток) |
zookeeper_uptime | ms | Время работы сервера (ZooKeeper 3.6+) |
zookeeper_open_file_descriptor_count | descriptor | Количество открытых файловых дескрипторов процесса |
zookeeper_max_file_descriptor_count | descriptor | Лимит файловых дескрипторов процесса |
zookeeper_zxid_count | — | Счётчик последнего обработанного zxid |
zookeeper_zxid_epoch | — | Эпоха последнего zxid (меняется при выборах лидера) |
zookeeper_outstanding_changes_queued | — | Изменения, поставленные в очередь на применение к дереву |
zookeeper_outstanding_changes_removed | — | Изменения, снятые с очереди (применённые) |
zookeeper_unrecoverable_error_count | error | Количество невосстановимых ошибок (ZooKeeper 3.6+) |
zookeeper_instances | — | 1 — индикатор того, что инстанс отвечает |
zookeeper_instances_standalone( _leader / _follower / _observer) | — | 1 для текущего режима узла (при report_instance_mode: true) |
Метрики соединений и сессий
| Имя метрики | Единица | Описание |
|---|---|---|
zookeeper_connections | connection | Количество клиентских соединений (из stat) |
zookeeper_num_alive_connections | connection | Количество живых клиентских соединений (из mntr) |
zookeeper_connection_request_count | — | Накопленное число входящих запросов на установку соединения (3.6+) |
zookeeper_connection_drop_count | — | Накопленное число оборванных соединений (3.6+) |
zookeeper_connection_drop_probability | — | Текущая вероятность сброса нового соединения (защита от перегруза) |
zookeeper_connection_rejected | — | Накопленное число отклонённых соединений (3.6+) |
zookeeper_connection_revalidate_count | — | Накопленное число ревалидаций соединений (3.6+) |
zookeeper_revalidate_count | — | Накопленное число ревалидаций сессий (3.6+) |
zookeeper_global_sessions | session | Количество глобальных сессий (3.6+) |
zookeeper_local_sessions | session | Количество локальных сессий (3.6+) |
zookeeper_sessionless_connections_expired | — | Накопленное число истёкших соединений без сессии (3.6+) |
zookeeper_stale_sessions_expired | — | Накопленное число истёкших устаревших сессий (3.6+) |
zookeeper_bytes_received_count | byte | Накопленный объём принятых байт (3.6+) |
zookeeper_bytes_received / zookeeper_bytes_sent | byte | Объём принятых / отправленных байт |
zookeeper_last_client_response_sizezookeeper_max_client_response_sizezookeeper_min_client_response_size | byte | Размер последнего / максимального / минимального ответа клиенту (3.6+) |
zookeeper_outstanding_tls_handshake | — | Незавершённые TLS-рукопожатия (3.6+) |
Счётчики пакетов
mntr отдаёт packets_received / packets_sent, но интеграция zk версии
4.x их не публикует по 4lw-пути — для объёма трафика ориентируйтесь на
zookeeper_bytes_received / zookeeper_bytes_sent либо на /commands/mntr
встроенного AdminServer.Метрики watch’ей
ZooKeeper 3.6+: при срабатывании watch’ей публикуется гистограмма
*_watch_count (число watch’ей, затронутых событием) с обычным набором
агрегатов (avg_, min_, max_, cnt_, sum_):
| Имя метрики (с префиксами агрегатов) | Описание |
|---|---|
zookeeper_*_node_created_watch_count | Watch’ей сработало на событие «znode создан» |
zookeeper_*_node_deleted_watch_count | Watch’ей сработало на событие «znode удалён» |
zookeeper_*_node_changed_watch_count | Watch’ей сработало на событие «данные znode изменены» |
zookeeper_*_node_children_watch_count | Watch’ей сработало на событие «изменился список детей» |
zookeeper_dead_watchers_queued | Watch’ей поставлено в очередь на очистку (3.6+) |
zookeeper_dead_watchers_cleared | Watch’ей очищено (3.6+) |
zookeeper_add_dead_watcher_stall_time | Время блокировки при добавлении dead-watcher’а, мс (3.6+) |
zookeeper_*_dead_watchers_cleaner_latency | Гистограмма latency очистителя dead-watcher’ов (3.6+) |
Метрики throttling и кэша ответов
ZooKeeper 3.6+:
| Имя метрики | Описание |
|---|---|
zookeeper_*_connection_token_deficit | Гистограмма дефицита токенов rate-limiter’а соединений |
zookeeper_large_requests_rejected | Накопленное число отклонённых «больших» запросов |
zookeeper_request_throttle_wait_count | Накопленное число запросов, ждавших в throttle |
zookeeper_stale_requests | Накопленное число устаревших запросов |
zookeeper_stale_requests_dropped | Накопленное число отброшенных устаревших запросов |
zookeeper_stale_replies | Накопленное число устаревших ответов |
zookeeper_response_packet_cache_hitszookeeper_response_packet_cache_misses | Попадания / промахи кэша пакетов ответов |
zookeeper_response_packet_get_children_cache_hitszookeeper_response_packet_get_children_cache_misses | Попадания / промахи кэша ответов getChildren |
zookeeper_digest_mismatches_count | Накопленное число расхождений digest’ов дерева (порча данных) |
Метрики latency
zookeeper_latency_avg / zookeeper_latency_min / zookeeper_latency_max —
из stat, в миллисекундах: время ответа сервера на клиентский запрос.
ZooKeeper 3.6+ дополнительно отдаёт гистограммы из mntr (с агрегатами
avg_/min_/max_/cnt_/sum_/p50_/p95_/p99_/p999_):
| Имя метрики | Единица | Описание |
|---|---|---|
zookeeper_latency_avg | ms | Среднее время ответа на клиентский запрос (stat) |
zookeeper_latency_min / zookeeper_latency_max | ms | Минимальное / максимальное время ответа (stat) |
zookeeper_avg_latencyzookeeper_min_latencyzookeeper_max_latency | ms | То же из mntr |
zookeeper_*_readlatency | ms | Гистограмма latency запросов на чтение (3.6+) |
zookeeper_*_updatelatency | ms | Гистограмма latency запросов на изменение (3.6+) |
zookeeper_*_propagation_latency | ms | Сквозная latency обновления: от предложения на лидере до записи в дерево (3.6+) |
zookeeper_*_commit_propagation_latency | ms | Latency распространения коммита (3.6+) |
zookeeper_*_dbinittime | ms | Гистограмма времени перезагрузки БД при старте (3.6+) |
zookeeper_*_snapshottime | ms | Гистограмма времени записи снапшота (3.6+) |
zookeeper_*_fsynctime | ms | Гистограмма времени fsync журнала транзакций (3.6+) |
Метрики уровня ансамбля и quorum
Имеют смысл в кластере; на standalone обычно нули. Часть метрик публикуется только на лидере. ZooKeeper 3.6+:
| Имя метрики | Описание |
|---|---|
zookeeper_*_quorum_ack_latency | Гистограмма latency сбора ACK quorum’а на предложение |
zookeeper_*_proposal_latency | Гистограмма latency обработки предложений лидером |
zookeeper_*_proposal_ack_creation_latency | Гистограмма latency создания ACK на предложение |
zookeeper_proposal_count | Накопленное число предложений |
zookeeper_commit_count | Накопленное число коммитов на лидере |
zookeeper_diff_count / zookeeper_snap_count | Накопленное число diff- / snap-синхронизаций фолловеров |
zookeeper_learner_proposal_received_countzookeeper_learner_commit_received_count | Получено предложений / коммитов фолловером |
zookeeper_looking_count | Накопленное число переходов в состояние LOOKING (перевыборы) |
zookeeper_election_time / zookeeper_*_election_time | Время между входом и выходом из выборов лидера |
zookeeper_quit_leading_due_to_disloyal_voter | Накопленное число отказов от лидерства из-за нелояльного избирателя |
zookeeper_ensemble_auth_successzookeeper_ensemble_auth_failzookeeper_ensemble_auth_skip | Результаты аутентификации в ансамбле |
Метрики per-namespace
При включённом в ZooKeeper учёте по пространствам имён mntr отдаёт счётчики
запросов на чтение/запись с разбивкой по корневому znode (namespace) — для
каждого namespace <ns> интеграция публикует семейство
zookeeper_{avg,min,max,cnt,sum}_<ns>_read_per_namespace и
zookeeper_..._<ns>_write_per_namespace. На больших деревьях это даёт много
серий — при необходимости ограничьте их через metric_patterns в конфиге
проверки.
Сервис-проверки
| Сервис-проверка | Когда OK |
|---|---|
zookeeper_ruok | Сервер ответил imok на four-letter-word ruok (доступен и не «болен») |
zookeeper_mode | Режим узла совпал с expected_mode (если он задан в конфиге) |
Несут лейблы host (адрес опрашиваемого ZooKeeper) и port.
Ключевые метрики для дашбордов и алертов
Доступность
- Сервис-проверка
zookeeper_ruok != OKили отсутствие свежих метрик по инстансу — алерт: сервер недоступен, four-letter-words запрещены или сервер «болен». zookeeper_mode != OK(при заданномexpected_mode) — узел в неожиданной роли (например, ожидалсяleader, а узел сталfollowerпосле перевыборов).- В кластере: рост
zookeeper_looking_count/ ненулевойzookeeper_*_election_time— идут перевыборы лидера;zookeeper_zxid_epochсменился — лидер сменился.
Насыщение и backlog
zookeeper_outstanding_requestsстабильно > 0 (и растёт) — сервер не успевает обрабатывать поток запросов; основной SLI перегрузки.zookeeper_outstanding_changes_queuedрастёт без снижения — pipeline записи отстаёт.zookeeper_connection_drop_probability > 0или ростzookeeper_connection_drop_count/zookeeper_connection_rejected— сработала защита от перегрузки соединениями.zookeeper_request_throttle_wait_count/zookeeper_large_requests_rejectedрастут — клиенты упираются в request throttler.
Размер дерева и watch’и
zookeeper_znode_count(илиzookeeper_nodes) иzookeeper_approximate_data_size— рост к лимитам (jute.maxbuffer, объём heap) → деградация и риск OOM.zookeeper_watch_countнеконтролируемо растёт — утечка watch’ей у клиента (не переустанавливают/не отписываются).zookeeper_ephemerals_countне падает после отключения клиентов — «висящие» эфемерные ноды (сессии не истекли).
Latency
zookeeper_latency_avg/zookeeper_p99_updatelatency/zookeeper_p99_propagation_latency— рост = деградация ответа сервера; коррелируйте сzookeeper_outstanding_requests.zookeeper_max_fsynctime/zookeeper_max_snapshottime(и ихp99_) — медленный диск под журналом транзакций / снапшотами тормозит запись.- В кластере:
zookeeper_p99_quorum_ack_latency/zookeeper_p99_proposal_latency— медленный сбор ACK quorum’а (сетевые проблемы между узлами или медленный фолловер).
Ресурсы и целостность
zookeeper_open_file_descriptor_countблизко кzookeeper_max_file_descriptor_count— утечка дескрипторов (незакрытые соединения).zookeeper_unrecoverable_error_count > 0илиzookeeper_digest_mismatches_count > 0— серьёзная проблема: невосстановимая ошибка или расхождение digest’ов дерева (порча данных) — немедленный алерт.zookeeper_stale_requests_dropped/zookeeper_stale_repliesрастут — сервер отбрасывает устаревшие запросы (был перегружен или «залипал»).
Сбор логов ZooKeeper
Логи ZooKeeper собираются ProtoOBP агентом и отправляются в бэкенд ProtoOBP.
Здесь — только специфичные для ZooKeeper настройки. Включение логов на стороне
агента (logs_enabled, logs_pobp_url) описано в
Получение данных логов.
Конфигурация ProtoOBP агента
Если агент запускается в виде службы на хосте
Дополните уже существующий /etc/protoobp-agent/conf.d/zk.d/conf.yaml
(тот же файл, в котором лежит instances: для метрик) блоком logs::
logs:
- type: file
path: <ZOO_LOG_DIR>/zookeeper-*.out
source: zookeeper
service: zookeeper
log_processing_rules:
- type: multi_line
name: log_start_with_date
pattern: \d{4}-\d{2}-\d{2}
# Если включён rolling-file appender (по умолчанию в zoo.cfg на хосте):
- type: file
path: <ZOO_LOG_DIR>/zookeeper.log
source: zookeeper
service: zookeeper
log_processing_rules:
- type: multi_line
name: log_start_with_date
pattern: \d{4}-\d{2}-\d{2}
<ZOO_LOG_DIR> — каталог логов ZooKeeper (переменная окружения ZOO_LOG_DIR;
часто <ZK_HOME>/logs или /var/log/zookeeper). zookeeper-*.out — это
перенаправленный stdout/stderr процесса (туда log4j ConsoleAppender печатает
строки лога); zookeeper.log появляется при включённом RollingFileAppender.
Перезапустите агента: systemctl restart protoobp-agent.
Если агент запускается в виде Docker контейнера
Шаг 1 — включите сбор логов в самом агенте через переменные окружения и смонтируйте директорию JSON-логов docker-демона:
services:
protoobp-agent:
environment:
POBP_LOGS_ENABLED: "true"
POBP_LOGS_CONFIG_USE_HTTP: "true"
POBP_LOGS_CONFIG_LOGS_POBP_URL: <protoobp-backend>:<port>
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
# Прямое чтение JSON-лог файлов docker-демона быстрее,
# чем тянуть их через Docker socket API.
- /var/lib/docker/containers:/var/lib/docker/containers:ro
Шаг 2 — добавьте лейбл com.protoobp.ad.logs к контейнеру ZooKeeper. Агент
подхватит stdout/stderr контейнера (официальный образ zookeeper пишет лог
log4j в консоль) и пометит записи указанными source и service:
services:
zookeeper:
labels:
com.protoobp.ad.logs: '[{"source": "zookeeper", "service": "zookeeper", "log_processing_rules": [{"type": "multi_line", "name": "log_start_with_date", "pattern": "\\d{4}-\\d{2}-\\d{2}"}]}]'
Только нужные контейнеры
Если в агенте не задана переменнаяPOBP_LOGS_CONFIG_CONTAINER_COLLECT_ALL=true,
агент собирает логи только тех контейнеров, на которых есть лейбл
com.protoobp.ad.logs.Multi-line
ZooKeeper пишет лог через log4j ConsoleAppender, и каждая запись начинается с метки времени в форматеyyyy-MM-dd HH:mm:ss,SSS, например
2026-05-12 10:00:00,123 [myid:] - INFO [main:…] - …. Поэтому якорь правила
multi_line здесь — \d{4}-\d{2}-\d{2}. Правило склеивает следующие за меткой
времени строки (Java stack traces, multi-line сообщения) в одну логическую
запись; без него каждая строка трейса попадёт в ProtoOBP как отдельная запись.Проверка
В выводе agent status должен быть раздел Logs Agent с источником
zookeeper и ненулевым BytesRead:
docker exec protoobp-agent agent status \
| sed -n '/^==== Logs Agent ====/,/^====/p'
docker
------
- Type: file
Path: /var/lib/docker/containers/<id>/<id>-json.log
Service: zookeeper
Source: zookeeper
Status: OK
BytesRead: 111199
MultiLine matches: 452
(Поле Status у источника типа «JSON-файл docker-контейнера» может
отображаться как Pending даже при активном чтении — ориентируйтесь на
ненулевой BytesRead и на рост LogsProcessed в шапке раздела Logs Agent.)