Files
clickstream-ch-kafka-supers…/docs/OPERATIONS.md
T
ddadmin 4917a9a6ad feat(monitoring): add Airflow monitoring via statsd-exporter
- Add statsd-exporter service to docker-compose.yml (prom/statsd-exporter:v0.27.1)
- Add StatsD env vars to airflow-default-env for metrics export
- Add airflow job to prometheus.yml scrape configs
- Add Airflow Overview dashboard (Grafana provisioning)
- Add Airflow alert rules: scheduler down, queue backlog, failures, parse time
- Add configs/statsd_mapping.yml for StatsD → Prometheus conversion
- Use Prometheus naming convention (_total for counters, _seconds for timers)
- Add monitoring plan at plans/monitoring_airflow_plan.md
- Update OPERATIONS.md and Makefile for airflow monitoring

Tested: all 3 jobs (airflow, clickhouse, kafka) showing UP in Prometheus,
metrics flowing (dagbag_size=3, executor slots, heartbeats with _total suffix),
all 4 alert rules loaded in Grafana
2026-02-08 22:27:32 +03:00

290 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Operations Runbook
Операционный runbook для локального запуска и проверки пайплайна.
## Локальный запуск
Базовые команды:
- `make up` (или `docker compose up -d`)
- `make ddl` (применяет SQL из `sql/ddl/00_databases.sql` и `sql/ddl/*/*.sql` в ClickHouse)
- `make data` (пересоздаёт топики и заливает небольшой срез данных в Kafka; полный режим — `FULL=1 make data`)
- `make transform` (запускает batch-процесс ODS -> DDS -> DM)
- `docker compose ps`
- `docker compose logs -f --tail=200 <service>`
- `docker compose down` (сохраняет named volumes, включая `clickhouse-data`)
- `docker compose down -v` (удаляет named volumes, использовать осознанно)
## Порты
Порты задаются в `docker-compose.yml`:
- ClickHouse native: `localhost:8002`
- ClickHouse HTTP: `localhost:9123`
- Kafka: `localhost:9092`
- Kafka UI: `http://localhost:8082`
- Airflow: `http://localhost:8080` (`admin/admin`)
- Prometheus: `http://localhost:9090`
- Grafana: `http://localhost:3000`
## Airflow DAGs
### `ddl_init`
- Запуск: ручной (`Trigger DAG`)
- Параметр: `verify_only` (`bool`, default `false`)
- Назначение: создаёт БД и таблицы в ClickHouse от `00_databases` до `40_dm`
### `kafka_load`
- Запуск: ручной (`Trigger DAG with config`)
- Параметры:
- `limit` (`int`, default `0`) — количество строк (`0` = все)
- `reset_topics` (`bool`, default `true`) — пересоздать топики
- Примеры:
```json
{}
```
```json
{"limit": 100}
```
### `etl_pipeline`
- Запуск: ручной (`Trigger DAG with config`)
- Параметр: `full_refresh` (`bool`, default `true`) — очистить DDS перед загрузкой
- Зависимость: требует наличия данных в STG (от `kafka_load` или `make data`)
## Рекомендуемый сценарий (фаза 2)
```bash
# 1. Запуск инфраструктуры
make up
# 2. Инициализация схемы (один раз)
# Airflow UI -> DAGs -> ddl_init -> Trigger DAG
# 3. Загрузка данных через Airflow
# Airflow UI -> DAGs -> kafka_load -> Trigger DAG with config
# Параметры по умолчанию: limit=0, reset_topics=true
# 4. Запуск ETL
# Airflow UI -> DAGs -> etl_pipeline -> Trigger DAG with config
# {"full_refresh": true}
# 5. Проверка результатов
docker compose exec -T clickhouse clickhouse-client --user=default --password=123456 --query "SELECT count() FROM ods.browser_event"
docker compose exec -T clickhouse clickhouse-client --user=default --password=123456 --query "SELECT count() FROM dds.event"
docker compose exec -T clickhouse clickhouse-client --user=default --password=123456 --query "SELECT * FROM dm.dq_summary"
```
## Быстрые проверки
- Kafka ingest: наличие данных в `stg.*` и типизированных строк в `ods.*`.
- Airflow UI: `http://localhost:8080` показывает DAG `ddl_init`, `kafka_load`, `etl_pipeline`.
- BI: витрина `dm.v_events_enriched` отвечает за разумное время при фильтре по дате.
---
## Мониторинг
### TL;DR после `git pull`
```bash
# Быстрый вариант (make)
make reload-monitoring
# Или вручную:
docker compose up -d prometheus grafana kafka-exporter statsd-exporter
docker compose restart prometheus
curl -s -u admin:admin -X POST http://localhost:3000/api/admin/provisioning/datasources/reload
curl -s -u admin:admin -X POST http://localhost:3000/api/admin/provisioning/dashboards/reload
curl -s -u admin:admin -X POST http://localhost:3000/api/admin/provisioning/alerting/reload
```
Если менялся `configs/prometheus_ch.xml`: `docker compose restart clickhouse`.
### Prometheus + Grafana для ClickHouse, Kafka и Airflow
Стек мониторинга поднимается вместе с остальной инфраструктурой:
```bash
# Проверить статус сервисов мониторинга
docker compose ps prometheus grafana
# Проверить скрейп ClickHouse в Prometheus
curl -s http://localhost:9090/api/v1/targets | grep -o '"health":"[^"]*"'
```
### Конфигурация
- **ClickHouse**: встроенный Prometheus endpoint (`/metrics` на порту `9126`)
- **Kafka**: через `kafka-exporter` (порт `9308`)
- **Airflow**: через `statsd-exporter` (StatsD → Prometheus, порт `9102`)
- Airflow отправляет метрики в StatsD-формате на `statsd-exporter:8125`
- Mapping конфигурация: `configs/statsd_mapping.yml`
- **Grafana provisioning** (`configs/grafana/provisioning/`):
- Дашборды: ClickHouse Overview, Kafka Overview, Airflow Overview
- Алерты: ClickHouse, Kafka, Airflow
### После `git pull`: быстрый апдейт мониторинга
Если прилетели изменения в `configs/grafana/provisioning/*` или `configs/prometheus.yml`, примените их так:
```bash
# Рекомендуемый способ (через make)
make reload-monitoring
# Или вручную:
docker compose up -d prometheus grafana kafka-exporter
docker compose restart prometheus
curl -s -u admin:admin -X POST http://localhost:3000/api/admin/provisioning/datasources/reload
curl -s -u admin:admin -X POST http://localhost:3000/api/admin/provisioning/dashboards/reload
curl -s -u admin:admin -X POST http://localhost:3000/api/admin/provisioning/alerting/reload
```
Проверка результата:
```bash
# Дашборды и алерты
curl -s -u admin:admin http://localhost:3000/api/v1/provisioning/alert-rules | grep -o '"title":"[^"]*"'
# Kafka метрики
curl -s http://localhost:9090/api/v1/targets | grep kafka
curl -s http://localhost:9308/metrics | grep "^kafka_brokers"
```
Если в пулле изменился `configs/prometheus_ch.xml`, дополнительно перезапустите ClickHouse:
```bash
docker compose restart clickhouse
```
Если дашборд Kafka не загрузился (ошибка "Dashboard title cannot be empty" в логах), пересоздайте контейнер Grafana:
```bash
docker compose stop grafana && docker compose rm -f grafana && docker compose up -d grafana
```
### Дашборд ClickHouse Overview
URL: `http://localhost:3000/d/clickhouse-overview/clickhouse-overview`
| Раздел | Метрики |
|--------|---------|
| System Health | CPU Usage, Memory Resident, Memory Code |
| Query Performance | Queries/sec, Active Queries, Failed Queries, Total Queries, Inserted Rows/sec |
| MergeTree Storage | Total Parts, Parts by State, Total Merges, Merges/sec |
Принятое решение по метрикам: сверили naming через Context7 (`/clickhouse/clickhouse-docs`, раздел Prometheus interface) и заменили недоступные в `25.1` серии на фактически экспортируемые (`ClickHouseProfileEvents_InsertedRows`, `ClickHouseAsyncMetrics_TotalPartsOfMergeTreeTables`, `ClickHouseMetrics_Parts*`).
### Дашборд Kafka Overview
URL: `http://localhost:3000/d/kafka-overview/kafka-overview`
| Раздел | Метрики |
|--------|---------|
| Cluster Health | Brokers Up, Topics Count, Total Partitions, Consumer Groups |
| Throughput | Messages In/sec by Topic |
| Consumers | Consumer Lag by Group, Consumer Lag Table |
| Partitions | Partition Offsets (Current), Oldest vs Current Offset Gap |
**Источник метрик:** `kafka-exporter` (danielqsj/kafka-exporter), формат конфигурации подтверждён через Context7 (`/danielqsj/kafka_exporter`, `/prometheus/docs`).
### Проверка метрик
```bash
# Prometheus собирает метрики ClickHouse
curl -s "http://localhost:9090/api/v1/query?query=ClickHouseAsyncMetrics_MemoryResident"
curl -s "http://localhost:9090/api/v1/query?query=ClickHouseProfileEvents_Query"
# Prometheus собирает метрики Kafka
curl -s "http://localhost:9090/api/v1/query?query=kafka_brokers"
curl -s "http://localhost:9090/api/v1/query?query=kafka_consumergroup_lag"
# Прямая проверка kafka-exporter
curl -s http://localhost:9308/metrics | grep "^kafka_"
```
```bash
# Проверить, что Prometheus собирает метрики
curl -s "http://localhost:9090/api/v1/query?query=ClickHouseAsyncMetrics_MemoryResident"
# Проверить счётчик запросов
curl -s "http://localhost:9090/api/v1/query?query=ClickHouseProfileEvents_Query"
```
### Алерты Grafana
**ClickHouse Alerts** — provisioning-файл: `configs/grafana/provisioning/alerting/clickhouse-alert-rules.yml`
Настроены правила:
- `ClickHouse Failed Queries Rate``rate(ClickHouseProfileEvents_FailedQuery[5m]) > 0` в течение `2m`
- `ClickHouse Memory Resident High``MemoryResident / OSMemoryTotal * 100 > 85` в течение `5m`
- `ClickHouse Parts Active High``ClickHouseMetrics_PartsActive > 500` в течение `10m`
**Kafka Alerts** — provisioning-файл: `configs/grafana/provisioning/alerting/kafka-alert-rules.yml`
Настроены правила:
- `Kafka Broker Down``kafka_brokers < 1` в течение `1m`
- `Kafka Consumer Lag High``kafka_consumergroup_lag > 10000` в течение `5m`
- `Kafka No Messages Produced``rate(kafka_topic_partition_current_offset[5m]) < 0.1` в течение `10m`
- `Kafka Consumer Group Missing` не включён: для демо-стенда даёт шум на стартовых прогонах и не повышает диагностику по сравнению с lag/throughput.
Проверка и reload без рестарта контейнера:
```bash
# Список правил unified alerting
curl -s -u admin:admin http://localhost:3000/api/v1/provisioning/alert-rules
# Принудительно перечитать provisioning alerting
curl -s -X POST -u admin:admin http://localhost:3000/api/admin/provisioning/alerting/reload
```
### Troubleshooting мониторинга
**Общие проблемы:**
- **"No data" в Grafana**: проверить, что Prometheus видит target (`Status -> Targets` в UI)
- **Dashboard не загрузился**: проверить логи Grafana — provisioning работает при первом старте контейнера
**ClickHouse:**
- **Метрики не обновляются**: ClickHouse экспортирует метрики на `0.0.0.0:9126` внутри сети Docker
**Kafka:**
- **`connection refused` к Kafka**: проверить, что kafka-exporter использует `kafka:29092` (внутренняя сеть), не `localhost:9092`
- **Метрики Kafka не появляются**: проверить, что kafka-exporter подключился к Kafka — `docker compose logs kafka-exporter`
- **Нет консьюмер-групп**: kafka-exporter показывает lag только при наличии активных консьюмеров с закоммиченными offset
## Troubleshooting
- `etl_pipeline` падает с ошибкой схемы: сначала запустить `ddl_init`.
- `git pull` падает с `Permission denied` на `data/*` или `configs/grafana/provisioning/*`:
- Причина: локально есть файлы/каталоги не вашего пользователя (часто после запуска контейнеров с root-пользователем).
- Диагностика:
```bash
ls -ld data configs/grafana/provisioning
ls -l data | head -n 20
```
- Быстрое восстановление:
```bash
# Владелец и права для рабочей копии репозитория
sudo chown -R "$USER:$USER" .
find . -type d -exec chmod u+rwx {} \;
find . -type f -exec chmod u+rw {} \;
```
- После восстановления повторить `git pull --ff-only`.
- Не запускать `git` через `sudo`.
- `grafana` перезапускается с ошибкой `attempt to write a readonly database`:
- Причина: старый `grafana_lib` содержит `grafana.db`, созданный root-пользователем.
- Простой recovery (сбросить только volume Grafana):
```bash
docker compose stop grafana
docker volume ls | grep grafana_lib
docker volume rm <project>_grafana_lib
docker compose up -d grafana
```
- После `docker compose down -v` нужно повторно прогнать: `ddl_init` -> `kafka_load` -> `etl_pipeline`.
- Для демо по умолчанию использовать малый срез данных; полный прогон делать осознанно.