Files
clickstream-data-platform/README.md
T
ddadminandClaude Opus 5 a9d66ed74a fix(stand): снят несуществующий бюджет памяти, нодам ClickHouse — 4 ГиБ
Зачем

Стенд упирался в память ноды ClickHouse: пробник валился на CREATE TABLE
ON CLUSTER, вместе с ним краснели make smoke и make smoke-guards. Причина не
та, что предполагал #21: дело не в заводских кэшах, а в коробке на гигабайт.
Около 550 МиБ RSS праздной ноды — страницы её собственного бинарника, и на
работу оставалось около 350 МиБ, которые пробник добирал за сессию.

Заодно выяснилось, откуда взялся предел 3,4 ГБ. Это была оценка расхода из
спеки, посчитанная по стенду-предшественнику до первой сборки v2 и превращённая
в жёсткий порог проверки. Порог стал критерием приёмки каждого этапа и дальше
блокировал бы любой рост стенда на этапах 2-9.

Что

- ADR 0004: бюджета памяти у стенда нет, есть требование к машине — около 8 ГБ,
  доступных Docker. Ресурсный довод ADR 0001 отозван, сами решения в силе.
- Нодам ClickHouse 4 ГиБ вместо гигабайта. Остальные лимиты не тронуты: ни один
  из них ни разу не сработал, а снять их скопом — то же изменение без
  свидетельств, каким они были выставлены.
- Из make smoke убрана проверка суммарного потребления. Она мерила docker stats
  вместе со страничным кэшем, то есть отвечала на вопрос «сколько файлов стенд
  потрогал», и с появлением настоящих данных краснела бы на здоровом стенде.
  Вместе с ней убрана привязанная к её сообщению проверка docs-guards.
- Взамен smoke спрашивает у Docker, не убивало ли ядро долгоживущий контейнер
  за память и не включалась ли политика перезапуска. Порога у проверки нет:
  убитый контейнер Docker поднимает сам, и без этого вопроса стенд отрапортует
  «всё хорошо» о ноде, которая умирала.
- README и раздел «Ресурсный бюджет» спеки переписаны с предела на требование
  к машине; README объясняет менти, что такое «память, доступная Docker».

Проверка

make config-test; make up; make smoke — 25 из 25; make smoke-cluster — 8 из 8;
make smoke-guards — 3 из 3, включая шаг «после восстановления стенд проходит
make smoke», который падал 31 июля.

На живом стенде с новой коробкой: max_server_memory_usage = 3,60 ГиБ, в журнале
ноды «Lowered mark cache size to 2.00 GiB because the system has limited RAM».
Семантика счётчиков Docker снята отдельными контейнерами: ручной restart
оставляет RestartCount = 0, убийство за память даёт OOMKilled = true и растущий
счётчик, убийство не за память OOMKilled не поднимает.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-01 14:35:36 +03:00

204 lines
16 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.
# Учебная дата-платформа кликстрима
Стенд для работы с кликстримом. Преемник учебного стенда
[clickstream-ch-kafka-superset-demo](https://git.dementev.space/ddmitry/clickstream-ch-kafka-superset-demo).
## Статус
Репозиторий строится по спеке
[«Боевой реализм стенда (v2)»](docs/specs/2026-07-30-stand-v2-realism.md).
Сейчас работают кластер ClickHouse из двух шардов, отдельный
clickhouse-keeper, односерверная Kafka в режиме KRaft, Airflow 3.3, Superset,
Prometheus, Grafana и общая база Postgres для метаданных.
## Быстрый старт
Нужны 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` нужен `uv`.
Стенд запускается без `.env`:
```bash
make up
make smoke
```
Чтобы изменить образы, порты или учебные учётные данные, скопируйте образец:
```bash
cp .env.example .env
make up
make smoke
```
Учётные данные 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` проверяет согласованность `.env.example` с Compose, зависимости
машины, здоровье контейнеров, Kafka через порт машины, три цели Prometheus,
источник Grafana, компоненты Airflow, ручной запуск пробников `test_clickhouse`
и `test_kafka`, метаданные и подключение Superset. Первый пробник создаёт
таблицы на обеих нодах и читает через `Distributed` на ноде 2 строку из
локальной таблицы ноды 1. Второй пишет в Kafka и читает свой маркер. В конце
проверка спрашивает у Docker, не убивало ли ядро какой-нибудь долгоживущий
контейнер за нехватку памяти и не включалась ли политика перезапуска: убитый
контейнер Docker поднимает сам, и проверка состояния об этом промолчит.
Временный топик проверки с машины и запуски DAG удаляются;
постоянный топик пробника сохраняется, а старые записи чистит Kafka.
`make smoke-cluster` запускает отдельную глубокую проверку ClickHouse: описание
кластера, макросы, связь с keeper, `ReplicatedMergeTree`, `Distributed`, очередь
распределённых DDL и очистку временных таблиц.
`make config-test` проверяет Compose, синтаксис Bash и Python, малые проверки
логики пробников и пробельные ошибки в diff без запуска стенда.
`make smoke-guards` сначала проверяет аварийную семантику кластерной проверки,
а затем удаляет служебную таблицу пробника только на второй ноде и
останавливает Prometheus с Kafka. Общая проверка должна назвать Prometheus и
оба пробника, после чего завершиться с ошибкой. В конце стенд восстанавливается.
### Какую проверку когда запускать
Проверки выстроены лесенкой: чем дороже прогон, тем больше связей он трогает.
- `make config-test` — секунды, стенд поднимать не нужно. Видит только то, что
есть в файлах, и о работоспособности не говорит ничего. Дёшево настолько, что
можно гонять перед каждым коммитом.
- `make smoke` — минута-две на поднятом стенде. Дороже, но проверяет связи
между службами, а не отдельные файлы: это интеграционная проверка.
- `make smoke-cluster` — около минуты. Одна связь, зато до дна: межнодовое
устройство ClickHouse.
- `make smoke-guards` — около пяти минут, и отвечает на другой вопрос. Не
«работает ли стенд», а «умеют ли проверки падать»: она намеренно ломает стенд
и смотрит, покраснеет ли `make smoke` и назовёт ли виновника, потом чинит и
убеждается, что стенд снова зелёный. Отсюда и три прогона `make smoke`
внутри — до поломки, во время неё и после починки.
Обычный рабочий цикл — `make config-test` и `make smoke`. `make smoke-guards`
нужна тому, кто правит сами проверки или пробники: без неё легко завести
проверку, которая зелена всегда.
Остановить контейнеры без удаления данных можно командой `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:
[настройками сервера](https://clickhouse.com/docs/operations/server-configuration-parameters/settings),
[Keeper](https://clickhouse.com/docs/guides/oss/deployment-and-scaling/keeper/),
[ReplicatedMergeTree](https://clickhouse.com/docs/engines/table-engines/mergetree-family/replication),
[ON CLUSTER](https://clickhouse.com/docs/sql-reference/distributed-ddl) и
[Distributed](https://clickhouse.com/docs/engines/table-engines/special/distributed).
Описание кластера задаётся через `remote_servers`, макросы — через `macros`,
подключение к keeper — через `zookeeper`; путь `ReplicatedMergeTree` содержит
`{shard}` и `{replica}`, а `Distributed` получает имя кластера, базу, локальную
таблицу и ключ шардирования. Макросы выбраны, чтобы один DDL через `ON CLUSTER`
создавал отдельный путь каждого шарда без вписанных вручную значений. Для
образа зафиксирован точный текущий
[LTS-выпуск 26.3.17.56](https://github.com/ClickHouse/ClickHouse/releases/tag/v26.3.17.56-lts);
серверы и keeper используют один образ. Настройки Kafka 4.3.1 сверены с
[примером односерверного KRaft](https://github.com/apache/kafka/blob/4.3.1/docker/examples/docker-compose-files/single-node/plaintext/docker-compose.yml).
Секция метрик взята из конфигурации закреплённого образа ClickHouse и проверена
на серверах и keeper. Подготовка источника Grafana сверена с
[официальным описанием автоматической настройки](https://grafana.com/docs/grafana/latest/administration/provisioning/).
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](https://airflow.apache.org/docs/apache-airflow/3.3.0/core-concepts/overview.html),
[публичным интерфейсом](https://airflow.apache.org/docs/apache-airflow/3.3.0/public-airflow-interface.html)
и [описанием здоровья](https://airflow.apache.org/docs/apache-airflow/3.3.0/administration-and-deployment/logging-monitoring/check-health.html).
Для пробников проверены публичный `Connection.get` из `airflow.sdk` и клиент
`clickhouse-connect`. Официальный провайдер Kafka сам использует
`confluent-kafka`; отдельное подключение и обёртки провайдера здесь не нужны,
поэтому прямой клиент оставляет образ и пример короче.
Superset закреплён на 6.1.0; драйвер `clickhouse-connect`, форма
`clickhousedb://` и драйвер Postgres сверены с
[документацией подключений Superset](https://superset.apache.org/user-docs/6.1.0/databases/)
и [настройкой базы метаданных](https://superset.apache.org/admin-docs/6.1.0/configuration/configuring-superset/).
## Что здесь будет
- одно широкое событие кликстрима по образцу выгрузки Яндекс Метрики вместо
четырёх топиков;
- второй источник — заказы бэкенда, ежедневным слепком в ту же Kafka;
- сверка клиентской покупки с заказом бэкенда: деньги считаем по бэкенду,
поведение и атрибуцию — по трекеру;
- анонимный кликстрим и склейка кука↔пользователь через покупки;
- ClickHouse кластером как единственным режимом.
## Чем отличается от предшественника
Предшественник остаётся стабильным учебным стендом и заморожен для новых фич:
там событие разрезано на четыре топика, есть только просмотры страниц,
посетители опознаны по email, ClickHouse — одна нода. Развитие идёт здесь.
## Документация
- [docs/specs/](docs/specs/) — спеки: источник истины о задуманном.
- [docs/research/](docs/research/) — исследования; сейчас это формат
кликстрима Яндекса, по которому строится модель события.
- [AGENTS.md](AGENTS.md) — контракт работы в репозитории.