Files
clickstream-data-platform/docs/adr/0001-stand-services.md
T
ddadminandClaude Opus 5 64f3418378 feat(airflow): пробные DAG test_clickhouse и test_kafka вместо демонстрационного
Зачем.
Демонстрационный DAG example_clickstream_hello ничего не проверял: он не
обращался ни к ClickHouse, ни к Kafka, поэтому его зелёный результат ничего
не говорил о стенде. Пробники проверяют связи по-настоящему — и тем же
клиентом, каким будут ходить рабочие DAG.

Что.
- test_clickhouse: пишет строку в ReplicatedMergeTree на ноде 1 и читает её
  с ноды 2 через Distributed. Данные проходят путь «нода 2 → все шарды →
  шард ноды 1», то есть проверяется межшардовое чтение, а не одна нода.
- test_kafka: пишет в постоянный топик сообщение с меткой прогона и
  вычитывает его обратно.
- infra/airflow/Dockerfile: clickhouse-connect 1.6.0 и confluent-kafka
  2.15.0 вшиты в образ, импорт проверяется на сборке — при запуске
  контейнера пакеты не доустанавливаются.
- Проверки: scripts/stand-smoke.sh гоняет оба пробника через API Airflow,
  scripts/config-test.sh разбирает DAG без стенда,
  tests/stand-smoke-guards.sh проверяет красный путь,
  tests/dag-probes-unit.py — модульные проверки разбора.
- README и ADR 0001 обновлены тем же изменением.
- Удалён dags/example_clickstream_hello.py.

Проверка.
make config-test — пройдено 3, 3 и 6, ошибок 0.
make clean; cp .env.example .env; make up — 116 с на чистых томах.
make smoke — пройдено 25, ошибок 0; стенд занимает 2244,0 MiB.
make smoke-cluster — все 8 проверок кластера.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-31 14:04:19 +03:00

6.8 KiB
Raw Blame History

ADR 0001. Сервисы каркаса стенда

Дата: 30 июля 2026 года. Статус: принято.

Решение

Стенд использует Airflow 3.3.0 с LocalExecutor. Airflow разделён на одноразовый airflow-init и три долгоживущих процесса: API, планировщик и обработчик DAG. Triggerer не запускается: в каркасе нет отложенных задач. Два интеграционных пробника написаны через публичный airflow.sdk.

Для входа выбран SimpleAuthManager. У него нет команды создания пользователя, поэтому airflow-init записывает пароль администратора из окружения в JSON-файл отдельного тома airflow_auth. Новый именованный том принадлежит root, а Airflow работает от пользователя airflow. Поэтому airflow-init запускается от root, назначает владельца каталога и сразу выполняет Python и команды Airflow через runuser от пользователя airflow. Все файлы репозитория подключены к этому контейнеру только для чтения. JWT-секрет, ключ подписи ссылок на журналы и ключ Fernet одинаковы для всех процессов и приходят из окружения.

Один Postgres 16 хранит две базы метаданных. У Airflow и Superset разные базы, пользователи и строки подключения. Это экономит один контейнер, но сохраняет границу владения данными.

Airflow получает подготовленное общее подключение к clickhouse-01, а Superset — подключение clickhousedb:// к clickhouse-02. Провайдер ClickHouse для Airflow не нужен: локальный образ содержит прямой клиент. Пробник создаёт служебные таблицы ON CLUSTER, пишет на первой ноде и через remote читает Distributed на второй. Разные ноды сохраняют учебную ловушку: забытый ON CLUSTER проявится в Superset, даже если операция Airflow на первой ноде прошла успешно.

Клиент Kafka также добавлен прямо в образ Airflow. Официальный провайдер использует тот же confluent-kafka, а пробнику не нужны его подключение, операторы и обёртки. Топик пробника постоянный, сообщение каждого запуска отличается уникальным маркером.

Superset собирается от apache/superset:6.1.0. В образ добавлены clickhouse-connect для ClickHouse и psycopg2-binary для метаданных Postgres. Подключение ClickHouse импортируется из YAML при подготовке.

Prometheus читает встроенные точки метрик двух серверов ClickHouse и keeper. Отдельные сборщики не нужны. Grafana получает источник Prometheus из файла.

Почему

Разделение Airflow показывает архитектуру третьей версии и даёт честные проверки здоровья процессов. LocalExecutor достаточен для одного учебного компьютера. Отказ от triggerer, второго Postgres и внешних сборщиков удерживает стенд в пределе 3,4 ГБ.

Тома clickhouse_*_data хранят данные keeper и двух нод ClickHouse. kafka_data, postgres_metadata_data, superset_home, prometheus_data и grafana_data хранят состояние своих сервисов. airflow_logs хранит журналы, а airflow_auth — JSON-файл с учебным паролем администратора. Каталог dags/ и все файлы настройки подключены только для чтения, поэтому контейнеры не меняют рабочее дерево.

Что проверено

Исследование задачи сверило через Context7 публичный API DAG с Task SDK Airflow и аргумент schedule. Решение дополнительно проверено по документации Airflow 3.3.0: публичный интерфейс, архитектура процессов, SimpleAuthManager и API здоровья. Оттуда взяты airflow.sdk, обязательный отдельный обработчик DAG, возможность не запускать triggerer и проверка конкретных компонентов здоровья.

Для интеграционных пробников проверены Connection.get в публичном airflow.sdk, запросы через clickhouse-connect и состав официального провайдера Kafka. Выбран прямой confluent-kafka: провайдер строит свои подключения и обёртки поверх него, которые двум коротким пробникам не нужны.

Драйверы и строки подключения проверены по документации Superset 6.1.0: подключения к базам, ClickHouse и база метаданных. Форма декларативного импорта и команда test-db проверены по исходному коду Superset 6.1.0 и на запущенном образе. Конфигурация метрик проверена по файлам закреплённого образа ClickHouse 26.3.17.56 и на живых точках серверов и keeper.