Мониторинг Apache ZooKeeper с помощью Proto Observability

Сбор метрик и логов Apache ZooKeeper: znode’ы, watch’и, соединения, latency, throttling и состояние ансамбля.

На этой странице:

Сбор метрик 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 и т.д.);
  • statzookeeper_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.

Конфигурация 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 агента

Если агент запускается в виде службы на хосте

  1. Создайте файл /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
    
  2. Перезапустите агента: 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 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: truestandalone, leader, follower, observer
portна сервис-проверках zookeeper_ruok / zookeeper_mode2181
hostна сервис-проверках — адрес опрашиваемого ZooKeeper172.19.0.3

Метрики уровня сервера

Имя метрикиЕдиницаОписание
zookeeper_nodesnodeКоличество znode’ов в пространстве имён (из stat)
zookeeper_znode_countnodeКоличество znode’ов (из mntr)
zookeeper_ephemerals_countnodeКоличество эфемерных znode’ов
zookeeper_approximate_data_sizebyteПримерный объём данных в дереве znode’ов
zookeeper_watch_countwatchКоличество зарегистрированных watch’ей
zookeeper_outstanding_requestsrequestКоличество запросов в очереди (растёт, когда сервер не успевает обрабатывать поток)
zookeeper_uptimemsВремя работы сервера (ZooKeeper 3.6+)
zookeeper_open_file_descriptor_countdescriptorКоличество открытых файловых дескрипторов процесса
zookeeper_max_file_descriptor_countdescriptorЛимит файловых дескрипторов процесса
zookeeper_zxid_countСчётчик последнего обработанного zxid
zookeeper_zxid_epochЭпоха последнего zxid (меняется при выборах лидера)
zookeeper_outstanding_changes_queuedИзменения, поставленные в очередь на применение к дереву
zookeeper_outstanding_changes_removedИзменения, снятые с очереди (применённые)
zookeeper_unrecoverable_error_counterrorКоличество невосстановимых ошибок (ZooKeeper 3.6+)
zookeeper_instances1 — индикатор того, что инстанс отвечает
zookeeper_instances_standalone
(_leader / _follower / _observer)
1 для текущего режима узла (при report_instance_mode: true)

Метрики соединений и сессий

Имя метрикиЕдиницаОписание
zookeeper_connectionsconnectionКоличество клиентских соединений (из stat)
zookeeper_num_alive_connectionsconnectionКоличество живых клиентских соединений (из 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_sessionssessionКоличество глобальных сессий (3.6+)
zookeeper_local_sessionssessionКоличество локальных сессий (3.6+)
zookeeper_sessionless_connections_expiredНакопленное число истёкших соединений без сессии (3.6+)
zookeeper_stale_sessions_expiredНакопленное число истёкших устаревших сессий (3.6+)
zookeeper_bytes_received_countbyteНакопленный объём принятых байт (3.6+)
zookeeper_bytes_received / zookeeper_bytes_sentbyteОбъём принятых / отправленных байт
zookeeper_last_client_response_size
zookeeper_max_client_response_size
zookeeper_min_client_response_size
byteРазмер последнего / максимального / минимального ответа клиенту (3.6+)
zookeeper_outstanding_tls_handshakeНезавершённые TLS-рукопожатия (3.6+)

Метрики watch’ей

ZooKeeper 3.6+: при срабатывании watch’ей публикуется гистограмма *_watch_count (число watch’ей, затронутых событием) с обычным набором агрегатов (avg_, min_, max_, cnt_, sum_):

Имя метрики (с префиксами агрегатов)Описание
zookeeper_*_node_created_watch_countWatch’ей сработало на событие «znode создан»
zookeeper_*_node_deleted_watch_countWatch’ей сработало на событие «znode удалён»
zookeeper_*_node_changed_watch_countWatch’ей сработало на событие «данные znode изменены»
zookeeper_*_node_children_watch_countWatch’ей сработало на событие «изменился список детей»
zookeeper_dead_watchers_queuedWatch’ей поставлено в очередь на очистку (3.6+)
zookeeper_dead_watchers_clearedWatch’ей очищено (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_hits
zookeeper_response_packet_cache_misses
Попадания / промахи кэша пакетов ответов
zookeeper_response_packet_get_children_cache_hits
zookeeper_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_avgmsСреднее время ответа на клиентский запрос (stat)
zookeeper_latency_min / zookeeper_latency_maxmsМинимальное / максимальное время ответа (stat)
zookeeper_avg_latency
zookeeper_min_latency
zookeeper_max_latency
msТо же из mntr
zookeeper_*_readlatencymsГистограмма latency запросов на чтение (3.6+)
zookeeper_*_updatelatencymsГистограмма latency запросов на изменение (3.6+)
zookeeper_*_propagation_latencymsСквозная latency обновления: от предложения на лидере до записи в дерево (3.6+)
zookeeper_*_commit_propagation_latencymsLatency распространения коммита (3.6+)
zookeeper_*_dbinittimemsГистограмма времени перезагрузки БД при старте (3.6+)
zookeeper_*_snapshottimemsГистограмма времени записи снапшота (3.6+)
zookeeper_*_fsynctimemsГистограмма времени 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_count
zookeeper_learner_commit_received_count
Получено предложений / коммитов фолловером
zookeeper_looking_countНакопленное число переходов в состояние LOOKING (перевыборы)
zookeeper_election_time / zookeeper_*_election_timeВремя между входом и выходом из выборов лидера
zookeeper_quit_leading_due_to_disloyal_voterНакопленное число отказов от лидерства из-за нелояльного избирателя
zookeeper_ensemble_auth_success
zookeeper_ensemble_auth_fail
zookeeper_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}"}]}]'

Проверка

В выводе 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.)