Мониторинг OpenLDAP с помощью Proto Observability
На этой странице:
- Сбор метрик OpenLDAP
- Сбор логов OpenLDAP
Сбор метрик OpenLDAP
Интеграция openldap собирает рантайм-статистику сервера каталогов
OpenLDAP (slapd): читает поддерево cn=Monitor по протоколу LDAP
(не JMX, не Prometheus). Из него извлекаются метрики соединений, операций
(bind / search / add / modify / delete / …), потоков, ожидающих
воркеров, объёма переданных данных и аптайма. Дополнительно можно описать
произвольные LDAP-поиски в custom_queries — для них собираются длительность
и число найденных записей.
Бэкенд cn=Monitor обязателен
Интеграция читает статистику только из бэкендаcn=Monitor (back_monitor).
В части дистрибутивов он скомпилирован в slapd статически (moduleload
не требуется), в других поставляется отдельным модулем; в любом случае по
умолчанию он не активирован — его нужно добавить как отдельную БД в
конфигурации cn=config и выдать на неё доступ на чтение тому DN, под которым
биндится агент (см. ниже).Конфигурация OpenLDAP
Включите бэкенд cn=Monitor и выдайте доступ на чтение поддерева cn=Monitor
тому DN, под которым будет биндиться агент (здесь — cn=admin,dc=example,dc=org).
В современном slapd (формат конфигурации cn=config, она же slapd.d) это
делается LDIF-файлом:
# enable-monitor.ldif
dn: olcDatabase=monitor,cn=config
objectClass: olcDatabaseConfig
olcDatabase: monitor
olcAccess: to dn.subtree="cn=Monitor" by dn.base="cn=admin,dc=example,dc=org" read by * none
Примените его от имени root-DN сервера через ldapi:///:
ldapadd -Y EXTERNAL -H ldapi:/// -f enable-monitor.ldif
slapd сам присвоит индекс базе данных (например, olcDatabase={2}monitor,cn=config,
после {0}config и {1}mdb/{1}hdb).
objectClass для monitor-БД
Вslapd 2.4 у бэкенда back-monitor нет собственных конфигурационных
атрибутов, поэтому запись olcDatabase=monitor,cn=config несёт только
objectClass: olcDatabaseConfig (как в примере выше). Отдельный
objectClass: olcMonitorConfig появился лишь в slapd 2.5+ — на 2.4 его
указывать не нужно (и нельзя — он не определён в схеме).back_monitor может быть загружаемым модулем
Если ваша сборка slapd поставляет back_monitor отдельным модулем
(back_monitor.so / back_monitor.la) — добавьте его перед созданием БД:
dn: cn=module{0},cn=config
changetype: modify
add: olcModuleLoad
olcModuleLoad: back_monitor
В пакетах Debian/Ubuntu (slapd) back_monitor исторически линкуется
статически — в этом случае шаг с moduleload не нужен.
В Docker-образах с механизмом «bootstrap LDIF» (например, osixia/openldap)
те же LDIF-файлы достаточно положить в каталог, который образ применяет на
первом старте — для osixia/openldap это
/container/service/slapd/assets/config/bootstrap/ldif/custom:
services:
openldap:
image: osixia/openldap:1.5.0
environment:
LDAP_DOMAIN: "example.org" # → base DN dc=example,dc=org
LDAP_ADMIN_PASSWORD: "adminpassword"
LDAP_LOG_LEVEL: "256" # loglevel "stats" — нужен для сбора логов
volumes:
- ./bootstrap/ldif/custom:/container/service/slapd/assets/config/bootstrap/ldif/custom
ports:
- "389:389"
В таком образе back_monitor обычно не статический, поэтому набор LDIF состоит
из двух файлов: сначала moduleload back_monitor (см. предыдущий alert), затем
создание olcDatabase=monitor,cn=config с ACL на cn=Monitor. Учтите, что
стартовый скрипт osixia выбирает ldapadd vs ldapmodify по наличию слова
changetype в файле — не пишите его в комментариях к LDIF, который должен
примениться через ldapadd.
Проверить, что бэкенд работает и читается, можно так:
ldapsearch -x -H ldap://localhost:389 -D "cn=admin,dc=example,dc=org" -w adminpassword \
-b "cn=Monitor" -s base "+"
Команда должна вернуть запись cn=Monitor (а с -s sub — всё поддерево
со счётчиками monitorCounter / monitorOpInitiated / monitoredInfo и т.п.).
Конфигурация ProtoOBP агента
Если агент запускается в виде службы на хосте
Создайте файл
/etc/protoobp-agent/conf.d/openldap.d/conf.yaml:init_config: instances: - url: ldap://localhost:389 # ldaps://localhost:636 для TLS, ldapi:/// для unix-сокета username: cn=admin,dc=example,dc=org password: adminpassword # ssl_verify: true # проверять сертификат сервера (для ldaps://) # ssl_ca_certs: /path/to/ca.pem # CA-сертификат # ssl_cert: /path/to/client.pem # клиентский сертификат (mTLS) # ssl_key: /path/to/client.key # ключ клиентского сертификата # tags: # - ldap_instance:primary # custom_queries: # - name: active_users # search_base: ou=people,dc=example,dc=org # search_filter: "(objectClass=inetOrgPerson)" # search_scope: subtree # base | level | subtree # attributes: [] # [] = только посчитать записи; иначе список атрибутов # # username / password можно переопределить per-queryПерезапустите агента:
systemctl restart protoobp-agent.
url поддерживает схемы ldap:// (открытое соединение), ldaps:// (TLS) и
ldapi:// (unix-сокет). Если на cn=Monitor выдан анонимный доступ на чтение —
username / password можно не указывать; в примере выше доступ ограничен
admin-DN, поэтому они обязательны.
Если агент запускается в виде Docker контейнера
Добавьте autodiscovery-лейблы к контейнеру slapd. В docker-compose.yaml:
labels:
com.protoobp.ad.check_names: '["openldap"]'
com.protoobp.ad.init_configs: '[{}]'
com.protoobp.ad.instances: '[{"url": "ldap://%%host%%:389", "username": "cn=admin,dc=example,dc=org", "password": "adminpassword"}]'
%%host%% агент подставит автоматически — это адрес контейнера в docker network.
Для TLS используйте "url": "ldaps://%%host%%:636" и при необходимости
"ssl_verify": false / "ssl_ca_certs": "<путь>" в том же объекте instance.
Контейнер агента
Контейнер агента должен находиться в той же docker network, что иslapd,
и иметь смонтированный /var/run/docker.sock:/var/run/docker.sock:ro для
autodiscovery контейнеров. Образ с суффиксом -jmx здесь не нужен —
проверка работает по LDAP, а не по JMX.Проверка
Убедитесь, что проверка запустилась и собирает метрики:
docker exec protoobp-agent agent status | grep -A 8 "^ openldap"
Ожидаемый вывод — Instance ID: … [OK] и ненулевые Metric Samples:
openldap (1.10.0)
Instance ID: openldap:bdbe18c6f6daf828 [OK]
Configuration Source: container:docker://…
Total Runs: 8
Metric Samples: Last Run: 40, Total: 320
Service Checks: Last Run: 1, Total: 8
Average Execution Time : 84ms
Полный список собираемых метрик с тегами — agent check openldap (с
--check-rate собираются и кумулятивные count-метрики openldap_operations_*,
openldap_connections_total, openldap_statistics_* — на одном прогоне
дельты ещё нет):
docker exec protoobp-agent agent check openldap --check-rate
За один прогон проверка отдаёт около 40 семплов (18 различных метрик плюс
разбивка по лейблам operation / status).
Собираемые метрики
Метрики приходят из поддерева cn=Monitor. Тип метрики:
gauge— мгновенное значение на момент сбора;count— кумулятивный счётчикslapd; интеграция отправляет его как monotonic count (агент считает дельту между сборами).
В ProtoOBP backend имена метрик хранятся в Prometheus-стиле — точки заменены
на подчёркивания (openldap_connections_current, openldap_operations_initiated
и т.д.). Именно в таком виде они приведены ниже и под ними их видно на
дашбордах и в алертах.
Лейблы
Добавляются агентом и ProtoOBP backend’ом:
| Лейбл | Значение |
|---|---|
host | Хост, на котором работает агент |
url | URL LDAP-сервера из instances: (например, ldap://openldap:389) |
operation | Тип LDAP-операции — только на openldap_operations_initiated / openldap_operations_completed (bind, unbind, search, compare, modify, modrdn, add, delete, abandon, extended) |
status | Состояние пула потоков — только на openldap_threads (open, starting, active, pending, backload, max, max_pending) |
query | Имя запроса из custom_queries — только на openldap_query_* |
service | Тег service (через com.protoobp.tags.service или POBP_TAGS) |
env | Тег env |
docker_image | Полный ref образа контейнера (например, osixia/openldap:1.5.0) |
image_name | Имя образа без тега |
image_tag | Тег образа |
short_image | Короткое имя образа |
Соединения
| Имя метрики | Тип | Единица | Описание |
|---|---|---|---|
openldap_connections_current | gauge | connection | Текущее число активных клиентских соединений |
openldap_connections_total | count | connection | Суммарное число соединений с момента старта сервера |
openldap_connections_max_file_descriptors | gauge | file | Максимальное число файловых дескрипторов, доступное процессу |
Операции
Метрики операций несут лейбл operation:<тип>; есть также агрегаты *_total
без этого лейбла.
| Имя метрики | Тип | Единица | Описание |
|---|---|---|---|
openldap_operations_initiated | count | operation | Число инициированных операций, по типам (лейбл operation) |
openldap_operations_completed | count | operation | Число завершённых операций, по типам (лейбл operation) |
openldap_operations_initiated_total | count | operation | Суммарное число инициированных операций по серверу |
openldap_operations_completed_total | count | operation | Суммарное число завершённых операций по серверу |
Статистика передачи данных
| Имя метрики | Тип | Единица | Описание |
|---|---|---|---|
openldap_statistics_bytes | count | byte | Количество байт, отправленных сервером |
openldap_statistics_entries | count | entry | Количество записей (entries), отправленных сервером |
openldap_statistics_pdu | count | packet | Количество PDU-пакетов, отправленных сервером |
openldap_statistics_referrals | count | message | Количество referral’ов, отправленных сервером |
Потоки и ожидающие
Метрика openldap_threads несёт лейбл status:<состояние>.
| Имя метрики | Тип | Единица | Описание |
|---|---|---|---|
openldap_threads | gauge | thread | Число потоков пула, по состояниям (лейбл status) |
openldap_threads_max | gauge | thread | Сконфигурированный максимум потоков пула |
openldap_threads_max_pending | gauge | thread | Максимальное число потоков в очереди ожидания |
openldap_waiter_read | gauge | worker | Текущее число воркеров, ожидающих чтения из сокета |
openldap_waiter_write | gauge | worker | Текущее число воркеров, ожидающих записи в сокет |
Время и доступность
| Имя метрики | Тип | Единица | Описание |
|---|---|---|---|
openldap_uptime | gauge | second | Аптайм сервера slapd (по cn=Start,cn=Time,cn=Monitor) |
openldap_bind_time | gauge | second | Время, которое заняла у проверки операция bind к серверу |
Пользовательские запросы (custom_queries)
Собираются для каждого элемента custom_queries (лейбл query:<name>):
| Имя метрики | Тип | Единица | Описание |
|---|---|---|---|
openldap_query_duration | gauge | second | Время выполнения LDAP-поиска |
openldap_query_entries | gauge | entry | Количество записей, вернувшихся по запросу |
Ключевые метрики для дашбордов и алертов
Доступность сервера
- Отсутствие свежих серий по
url— алерт:slapdнедоступен или агент не может забиндиться кcn=Monitor. - Резкий сброс
openldap_uptime(или значение близкое к нулю при работающем трафике) —slapdперезапустился. openldap_bind_time— рост = сервер отвечает медленно (нагрузка, проблемы с диском/сетью).
Соединения и дескрипторы
openldap_connections_currentблизко кopenldap_connections_max_file_descriptors— сервер скоро упрётся в лимит fd и начнёт отбрасывать соединения; алерт по отношению (например,> 80 %).- Резкий рост
openldap_connections_total(производная) — всплеск подключений (клиенты не переиспользуют соединения / DDoS / неисправный клиент).
Операции
openldap_operations_initiated{operation:search}— основной показатель нагрузки на чтение; ростsearchбез роста числа клиентов = неэффективные запросы (нет индекса → full scan).openldap_operations_initiated_total−openldap_operations_completed_totalстабильно растёт — операции зависают (блокировки, перегрузка пула потоков).- Ненулевой
openldap_operations_initiated{operation:bind}при росте ошибок аутентификации (видно в логах) — перебор паролей.
Пул потоков и backpressure
openldap_threads{status:active}≈openldap_threads_maxиopenldap_threads{status:pending} > 0— пул потоков исчерпан, запросы ждут в очереди; алерт.openldap_waiter_read/openldap_waiter_writeстабильно высокие — много соединений в ожидании ввода-вывода (медленные клиенты или сеть).
Объём отдаваемых данных
- Резкий рост
openldap_statistics_entries/openldap_statistics_bytes(производная) — кто-то делает массовые/нефильтрованные выгрузки ((objectClass=*)по всему дереву). - Ненулевой
openldap_statistics_referralsтам, где referral’ов быть не должно — неверно сконфигурированы chaining/глобальные referral’ы.
Пользовательские запросы
openldap_query_entriesдля контрольногоcustom_queryупал до нуля — ожидаемые данные исчезли из каталога (сломалась репликация, кто-то удалил OU).openldap_query_durationрастёт — деградация конкретного поиска (потеря индекса по атрибуту фильтра).
Сбор логов OpenLDAP
Логи slapd собираются ProtoOBP агентом и отправляются в бэкенд ProtoOBP.
Здесь — только специфичные для OpenLDAP настройки. Включение логов на стороне
агента (logs_enabled, logs_pobp_url) описано в
Получение данных логов.
Уровень логирования slapd
По умолчанию slapd логирует очень скупо. Чтобы логи были информативными,
поднимите olcLogLevel — например, stats (числовое значение 256): он пишет
по строке на каждое соединение и операцию. Уровень задаётся в cn=config:
dn: cn=config
changetype: modify
replace: olcLogLevel
olcLogLevel: stats
В Docker-образах это обычно делается переменной окружения — у osixia/openldap
это LDAP_LOG_LEVEL=256; у bitnami/openldap — LDAP_LOGLEVEL=256.
Конфигурация ProtoOBP агента
Если агент запускается в виде службы на хосте
Куда slapd пишет лог, зависит от роутинга syslog: с olcLogLevel процесс
шлёт записи в syslog facility local4, дальше rsyslog/journald раскладывают их
по файлу (часто /var/log/slapd.log, или /var/log/syslog). Настройте этот
файл в rsyslog (local4.* /var/log/slapd.log), затем дополните существующий
/etc/protoobp-agent/conf.d/openldap.d/conf.yaml (тот же файл, где лежит
instances: для метрик) блоком logs::
logs:
- type: file
path: /var/log/slapd.log
source: openldap
service: openldap
Записи slapd однострочные (syslog-формат <дата> <host> slapd[pid]: conn=… op=… SEARCH …) — правило multi_line не требуется.
Перезапустите агента: 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 к контейнеру slapd. Агент
подхватит stdout/stderr контейнера и пометит записи указанными source и
service:
services:
openldap:
image: osixia/openldap:1.5.0
environment:
LDAP_LOG_LEVEL: "256" # без этого slapd почти ничего не пишет
labels:
com.protoobp.ad.logs: '[{"source": "openldap", "service": "openldap"}]'
Только нужные контейнеры
Если в агенте не задана переменнаяPOBP_LOGS_CONFIG_CONTAINER_COLLECT_ALL=true,
агент собирает логи только тех контейнеров, на которых есть лейбл
com.protoobp.ad.logs.Multi-line
slapd в режиме stats пишет syslog-style записи — по одной строке на событие
соединения/операции. У osixia/openldap к ним добавляются строки bootstrap-скрипта
вида *** INFO | … . Все записи однострочные, поэтому правило log_processing_rules
с type: multi_line здесь не нужно (в отличие от Java-сервисов, где оно
склеивает stack traces).Проверка
В выводе agent status должен быть раздел Logs Agent со статусом running
и источник openldap с ненулевым BytesRead:
docker exec protoobp-agent agent status \
| sed -n '/^==== Logs Agent ====/,/^====/p'