- Зачем:
- смоук перестал быть быстрым: 42 секунды из 48 съедали шесть проверок,
которые ждут службу — запуск DAG, вход в Superset, Kafka с машины.
- имена целей врали: смоуком звались и глубокая проверка кластера, и
интеграционные проверки; префикс достался им от общего происхождения.
- нигде не было записано, зачем в репозитории каждая цель и куда класть
новую проверку, — без записи скрипт дорастёт снова.
- Что:
- ось деления — кого спрашивают, а не сколько стоит: make smoke (стенд
собран), make check-clickhouse (спрашивают у ClickHouse), новая
make check-services (службы работают).
- шесть тяжёлых проверок переехали в scripts/stand-services.sh; общее —
счёт, обращение к Compose, зависимости машины и check_containers_survived
— вынесено в scripts/stand-common.sh, копипасты нет.
- smoke-cluster переименована в check-clickhouse; имя файла скрипта не
тронуто (в него встраивается проверка договора со схемой), расхождение
названо в карте.
- смоук и check-services печатают своё время в строке ИТОГ; порога по
времени нет — по доводу ADR 0004.
- docs/architecture/testing.md: карта всех семи целей, правило быстрого
смоука словами, лесенка по частоте и правило про краснеющую проверку,
переехавшее из README; указатель из AGENTS.md.
- README: описания целей сокращены, карта не дублируется; быстрый старт
показывает работающий стенд, а не только собранный.
- планка приёмки этапа в спеке названа поимённо: три цели вместо
«smoke-проверки».
- Проверка:
- make config-test, make smoke (19 проверок, 6 с), make check-clickhouse
(8 проверок, 7 с), make check-services (7 проверок, 44 с) — зелёные.
- 19 + 7 = 25 разных проверок, как и до деления: check_containers_survived
считается дважды намеренно.
- краснеют обе разделённые цели: со снятым prometheus смоук дал три ошибки,
с подменённым UUID подключения Superset покраснел check-services.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Учебная дата-платформа кликстрима
Стенд для работы с кликстримом. Преемник учебного стенда clickstream-ch-kafka-superset-demo.
Статус
Репозиторий строится по спеке
«Боевой реализм стенда (v2)».
Сейчас работают кластер ClickHouse из двух шардов, отдельный
clickhouse-keeper, односерверная Kafka в режиме KRaft, Airflow 3.3, Superset,
Prometheus, Grafana и общая база Postgres для метаданных. Начат генератор
кликстрима: в generator/ заведён контракт схемы события, из
которого собрано описание выгрузки.
Быстрый старт
Нужны Docker с Compose и около 8 ГБ памяти, доступной Docker. Это не объём
ноутбука, а то, что отдано самому Docker: в Docker Desktop и WSL2 он живёт
внутри виртуальной машины и получает лишь часть памяти хозяина. Сколько выдано
сейчас, в байтах, покажет docker info --format '{{.MemTotal}}'. В WSL2 это
поднимается параметром memory в файле .wslconfig домашнего каталога
пользователя Windows; после правки нужен wsl --shutdown. Если своей машины не
хватает, стенд одинаково хорошо живёт на недорогом VPS.
Проверкам на поднятом стенде также нужны curl, jq, awk,
grep, sed, tail, sleep и timeout. По умолчанию должны быть свободны
порты 23000, 28080, 28088, 28123, 28124, 29000, 29001, 29090
и 29092. Проверкам без стенда — make config-test, make lint,
make typecheck, make test — и сборке документации make docs нужен uv.
Стенд запускается без .env:
make up
make smoke
make check-clickhouse
make check-services
Первому знакомству нужны все три проверки на стенде: make smoke говорит, что
стенд собран, make check-clickhouse — что кластер работает кластером, а
make check-services — что Airflow запускает DAG, а Superset ходит в базу.
Дальше, в рабочей петле, обычно хватает make smoke.
Чтобы изменить образы, порты или учебные учётные данные, скопируйте образец:
cp .env.example .env
make up
make smoke
.env.example — справочник, а не настройка: в нём перечислены все переменные,
которые читает compose.yaml, с теми же значениями по умолчанию. Стенд его не
читает и на согласованность не проверяет, поэтому расхождение с compose.yaml
обнаружит только читатель. Меняя подстановку ${VAR:-значение} в
compose.yaml, поправьте образец тем же коммитом.
Учётные данные Postgres и Grafana применяются при создании их томов.
После первого запуска меняйте их только вместе с make clean: команда удалит
все локальные данные стенда, а следующий make up создаст их с новыми
значениями.
make up собирает локальные образы Airflow и Superset, поднимает весь стенд и
ждёт здорового состояния долгоживущих контейнеров. В образ Airflow добавлены
закреплённые клиенты ClickHouse и Kafka. Одноразовые airflow-init и
superset-init завершаются с кодом 0. Первый обновляет схему Airflow,
подготавливает администратора и подключение к clickhouse-01. Второй обновляет
Superset, создаёт администратора и импортирует подключение к clickhouse-02.
make smoke за секунды спрашивает, собран ли стенд: зависимости машины,
здоровье контейнеров, устройство keeper, три цели Prometheus, источник Grafana,
компоненты Airflow и подготовленное подключение к clickhouse-01. В конце
проверка спрашивает у Docker, не убивало ли ядро что-нибудь в долгоживущих
контейнерах за нехватку памяти и не включалась ли политика перезапуска: убитый
контейнер Docker поднимает сам, и проверка состояния об этом промолчит.
Одиннадцать проверок здоровья сразу после make up --wait повторяют то, чего
Compose уже дождался: у каждой долгоживущей службы есть своя healthcheck.
Оставлены они потому, что первый вопрос к стенду всё равно «всё ли живо», а
ответ на него стоит меньше секунды. Устройство keeper — другое дело: он должен
работать от пользователя clickhouse, с пределом в 262144 открытых файла и со
своим томом под данные. Всё это объявлено в compose.yaml, но здоровым keeper
выглядит и без этого, поэтому смоук спрашивает у живого контейнера, дошли ли
объявленные настройки до процесса.
make check-services проверяет то, ради чего приходится ждать службу: Kafka
через порт машины, ручной запуск пробников test_clickhouse и test_kafka,
вход в Superset, его метаданные и подключение к clickhouse-02. Первый пробник
создаёт таблицы на обеих нодах и читает через Distributed на ноде 2 строку из
локальной таблицы ноды 1. Второй пишет в Kafka и читает свой маркер. Временный
топик проверки с машины и запуски DAG удаляются; постоянный топик пробника
сохраняется, а старые записи чистит Kafka.
make check-clickhouse запускает отдельную глубокую проверку ClickHouse:
описание кластера, макросы, связь с keeper, ReplicatedMergeTree,
Distributed, очередь распределённых DDL и очистку временных таблиц.
make config-test проверяет Compose, синтаксис Bash и Python и пробельные
ошибки в diff без запуска стенда.
Обычный рабочий цикл — make config-test и make smoke; остальные цели гоняют
тогда, когда правка их касается. Что утверждает каждая проверка, нужен ли ей
поднятый стенд, сколько стоит прогон и куда класть новую — в
карте проверок.
Остановить контейнеры без удаления данных можно командой make down. Для
полного сброса с удалением всех именованных томов используйте make clean.
Повторный make up безопасен: одноразовая подготовка приложений идемпотентна.
Состав и доступ
clickhouse-01— инициатор DDL и точка подключения Airflow;clickhouse-02— точка подключения Superset;clickhouse-keeper— координатор кластера;kafka— один брокер KRaft;postgres-metadata— один Postgres с отдельными базами и пользователямиairflowиsuperset;airflow-apiserver,airflow-schedulerиairflow-dag-processor— Airflow 3.3 с LocalExecutor, без triggerer;superset— интерфейс и подготовленное подключение ClickHouse;prometheusиgrafana— сбор и просмотр встроенных метрик ClickHouse.
Порты доступны только с локальной машины:
- нода 1 —
http://127.0.0.1:28123, нативный порт29000; - нода 2 —
http://127.0.0.1:28124, нативный порт29001; - Kafka —
127.0.0.1:29092; - Airflow —
http://127.0.0.1:28080, пользовательadmin, парольairflow; - Superset —
http://127.0.0.1:28088, пользовательadmin, парольsuperset; - Prometheus —
http://127.0.0.1:29090; - Grafana —
http://127.0.0.1:23000, пользовательadmin, парольadmin.
У локального учебного кластера нет пароля: ноды используют общего пользователя
default для запросов Distributed. Порты поэтому привязаны к 127.0.0.1 и
не открыты во внешнюю сеть.
Пароли интерфейсов, пароли Postgres, ключи Airflow и Superset, отсутствие
пароля ClickHouse и отсутствие проверки доступа у Kafka и Prometheus —
намеренно простые и явно ненастоящие настройки локального учебного стенда. Это
не пример настройки защиты: не копируйте значения из .env.example в рабочую
среду. Все опубликованные порты привязаны только к 127.0.0.1; Postgres наружу
не опубликован.
В бою перед репликами ClickHouse обычно был бы балансировщик. Здесь в каждом шарде одна реплика, поэтому балансировать нечего. Балансировщик и топология 2×2 намеренно не входят в стенд.
Конфигурация сверена 30 июля 2026 года с официальной документацией ClickHouse:
настройками сервера,
Keeper,
ReplicatedMergeTree,
ON CLUSTER и
Distributed.
Описание кластера задаётся через remote_servers, макросы — через macros,
подключение к keeper — через zookeeper; путь ReplicatedMergeTree содержит
{shard} и {replica}, а Distributed получает имя кластера, базу, локальную
таблицу и ключ шардирования. Макросы выбраны, чтобы один DDL через ON CLUSTER
создавал отдельный путь каждого шарда без вписанных вручную значений. Для
образа зафиксирован точный текущий
LTS-выпуск 26.3.17.56;
серверы и keeper используют один образ. Настройки Kafka 4.3.1 сверены с
примером односерверного KRaft.
Секция метрик взята из конфигурации закреплённого образа ClickHouse и проверена
на серверах и keeper. Подготовка источника Grafana сверена с
официальным описанием автоматической настройки.
Prometheus собирает только встроенные метрики двух серверов и keeper; внешних
сборщиков, панелей и правил оповещения пока нет.
После изменения infra/clickhouse/config.d/prometheus.xml выполните
docker compose restart clickhouse-01 clickhouse-02: обычный make up не
перезапускает уже созданные серверы и они продолжают работать со старой
конфигурацией.
Airflow закреплён на 3.3.0. Состав обязательных процессов, LocalExecutor,
публичный airflow.sdk, API здоровья и SimpleAuthManager сверены с
архитектурой Airflow 3.3,
публичным интерфейсом
и описанием здоровья.
Для пробников проверены публичный Connection.get из airflow.sdk и клиент
clickhouse-connect. Официальный провайдер Kafka сам использует
confluent-kafka; отдельное подключение и обёртки провайдера здесь не нужны,
поэтому прямой клиент оставляет образ и пример короче.
Superset закреплён на 6.1.0; драйвер clickhouse-connect, форма
clickhousedb:// и драйвер Postgres сверены с
документацией подключений Superset
и настройкой базы метаданных.
Что здесь будет
- одно широкое событие кликстрима по образцу выгрузки Яндекс Метрики вместо четырёх топиков;
- второй источник — заказы бэкенда, ежедневным слепком в ту же Kafka;
- сверка клиентской покупки с заказом бэкенда: деньги считаем по бэкенду, поведение и атрибуцию — по трекеру;
- анонимный кликстрим и склейка кука↔пользователь через покупки;
- ClickHouse кластером как единственным режимом.
Чем отличается от предшественника
Предшественник остаётся стабильным учебным стендом и заморожен для новых фич: там событие разрезано на четыре топика, есть только просмотры страниц, посетители опознаны по email, ClickHouse — одна нода. Развитие идёт здесь.
Документация
- docs/specs/ — спеки: источник истины о задуманном.
- docs/adr/ — принятые решения с доводами и отвергнутыми вариантами: почему сделано так, а не иначе.
- docs/architecture/ — рабочие справочники по зонам
ответственности: хранилище — конвенции имён,
раскладка по шардам, приём событий, карта таблиц;
проверки — что утверждает каждая цель
makeи куда класть новую проверку. - docs/research/ — исследования; сейчас это формат кликстрима Яндекса, по которому строится модель события.
- docs/formats/ — описания форматов источников: по ним
пишется сторона хранилища. Собираются из кода командой
make docs, руками не правятся. - AGENTS.md — контракт работы в репозитории.