Кластер ClickHouse: 2 ноды + keeper в compose, smoke ON CLUSTER #12

Closed
opened 2026-07-30 16:43:52 +03:00 by ddmitry · 1 comment
Owner

Родитель

#3 — Этап 1: каркас стенда, кластерный compose.

Что сделать

Поднять в compose кластер ClickHouse: две ноды и отдельный clickhouse-keeper (координатор именно keeper, а не ZooKeeper — так решено по бюджету памяти). Топология — 2 шарда × 1 реплика, и это единственный режим: выключателя «стенд без кластера» нет.

У каждой ноды свои макросы shard и replica и одинаковое описание кластера. Локальные таблицы создаются движками семейства Replicated*, путь в keeper собирается из макросов; поверх локальных таблиц — Distributed. Балансировщика нет: балансировать нечего, в доках про это остаётся абзац «в бою здесь был бы балансировщик».

Роли нод закладываются сразу, потому что от них зависят следующие тикеты: нода 1 — инициатор DDL и будущее подключение Airflow, к ноде 2 позже подключается Superset.

Критерии приёмки

  • Часть make up, отвечающая за ClickHouse, поднимает две ноды и keeper; все три контейнера доходят до здорового состояния.
  • SELECT * FROM system.clusters на обеих нодах показывает один и тот же кластер из двух шардов.
  • SELECT * FROM system.macros на каждой ноде отдаёт свои значения shard и replica; между нодами они различаются.
  • keeper отвечает с обеих нод: SELECT * FROM system.zookeeper WHERE path = '/' выполняется без ошибки.
  • CREATE TABLE ... ON CLUSTER с движком Replicated* проходит, и созданная таблица видна в system.tables на обеих нодах — то есть DDL-очередь не повисла.
  • Путь в keeper у реплицированной таблицы собран из макросов, а не вписан руками.
  • Поверх реплицированной таблицы создана Distributed-таблица ON CLUSTER: вставка на ноду 1 читается через Distributed со второй ноды.
  • DROP TABLE ... ON CLUSTER убирает временные объекты проверки с обеих нод — стенд остаётся чистым.
  • Команда (или скрипт) smoke-проверки одна, её вывод понятен: что проверялось и что зелёное; как её запускать — записано в документации стенда.

Границы

  • Остальные сервисы стенда (Kafka, Airflow, Superset, мониторинг) — не здесь, у них свой тикет этапа.
  • Реплики (топология 2×2), балансировщик — вне спеки, не добавлять.
  • Рабочие DDL слоёв STG/ODS/DDS/DM — этап 2 и дальше. Здесь создаются только временные таблицы для проверки.

Сначала прочитать

  • docs/specs/2026-07-30-stand-v2-realism.md: раздел 6 (топология, макросы, роли нод, бюджет памяти) и 1.3 (ключи, шардирование по cityHash64(ClientID)).
  • AGENTS.md. Синтаксис кластерных DDL ClickHouse — как раз тот спорный API, который правила велят сверять через MCP Context7 до написания кода.

Проверка

  • Поднять стенд: make up.
  • Прогнать smoke-проверку из критериев приёмки (создание ON CLUSTER, вставка на одной ноде, чтение через Distributed со второй).
  • Заглянуть в очередь распределённых DDL: незавершённых записей быть не должно (system.distributed_ddl_queue).

Блокируется

Нет.

## Родитель #3 — Этап 1: каркас стенда, кластерный compose. ## Что сделать Поднять в compose кластер ClickHouse: две ноды и отдельный `clickhouse-keeper` (координатор именно keeper, а не ZooKeeper — так решено по бюджету памяти). Топология — 2 шарда × 1 реплика, и это единственный режим: выключателя «стенд без кластера» нет. У каждой ноды свои макросы `shard` и `replica` и одинаковое описание кластера. Локальные таблицы создаются движками семейства `Replicated*`, путь в keeper собирается из макросов; поверх локальных таблиц — Distributed. Балансировщика нет: балансировать нечего, в доках про это остаётся абзац «в бою здесь был бы балансировщик». Роли нод закладываются сразу, потому что от них зависят следующие тикеты: нода 1 — инициатор DDL и будущее подключение Airflow, к ноде 2 позже подключается Superset. ## Критерии приёмки - [x] Часть `make up`, отвечающая за ClickHouse, поднимает две ноды и keeper; все три контейнера доходят до здорового состояния. - [x] `SELECT * FROM system.clusters` на обеих нодах показывает один и тот же кластер из двух шардов. - [x] `SELECT * FROM system.macros` на каждой ноде отдаёт свои значения `shard` и `replica`; между нодами они различаются. - [x] keeper отвечает с обеих нод: `SELECT * FROM system.zookeeper WHERE path = '/'` выполняется без ошибки. - [x] `CREATE TABLE ... ON CLUSTER` с движком `Replicated*` проходит, и созданная таблица видна в `system.tables` на обеих нодах — то есть DDL-очередь не повисла. - [x] Путь в keeper у реплицированной таблицы собран из макросов, а не вписан руками. - [x] Поверх реплицированной таблицы создана Distributed-таблица ON CLUSTER: вставка на ноду 1 читается через Distributed со второй ноды. - [x] `DROP TABLE ... ON CLUSTER` убирает временные объекты проверки с обеих нод — стенд остаётся чистым. - [x] Команда (или скрипт) smoke-проверки одна, её вывод понятен: что проверялось и что зелёное; как её запускать — записано в документации стенда. ## Границы - Остальные сервисы стенда (Kafka, Airflow, Superset, мониторинг) — не здесь, у них свой тикет этапа. - Реплики (топология 2×2), балансировщик — вне спеки, не добавлять. - Рабочие DDL слоёв STG/ODS/DDS/DM — этап 2 и дальше. Здесь создаются только временные таблицы для проверки. ## Сначала прочитать - `docs/specs/2026-07-30-stand-v2-realism.md`: раздел 6 (топология, макросы, роли нод, бюджет памяти) и 1.3 (ключи, шардирование по `cityHash64(ClientID)`). - `AGENTS.md`. Синтаксис кластерных DDL ClickHouse — как раз тот спорный API, который правила велят сверять через MCP Context7 до написания кода. ## Проверка - Поднять стенд: `make up`. - Прогнать smoke-проверку из критериев приёмки (создание ON CLUSTER, вставка на одной ноде, чтение через Distributed со второй). - Заглянуть в очередь распределённых DDL: незавершённых записей быть не должно (`system.distributed_ddl_queue`). ## Блокируется Нет.
ddmitry added the ready-for-agent label 2026-07-30 16:43:52 +03:00
Author
Owner

Работа выполнена в ветке feat/12-clickhouse-cluster, закрывается PR #16.

Все девять критериев приёмки прошли на живом стенде: холодный make up — 11,7 с и три здоровых контейнера, make smoke — 8 из 8, make smoke-guards — 3 из 3, make clean — стенд удалён без остатка.

Итоги ревью: девять находок, восемь починены, одна отклонена с доводом (пустые каталоги /clickhouse/tables/{shard} в keeper — общее пространство имён будущих таблиц, а не мусор проверки; довод признан верным при перепроверке). Главное исправление — smoke при упавшей ноде висел 362 секунды и не прерывался по Ctrl-C; стало 107–118 мс, а при падении ноды посреди прогона — 13 секунд с ограниченной по времени уборкой.

Решения, не предрешённые тикетом: образ зафиксирован точным LTS-выпуском 26.3.17.56; документация стенда живёт быстрым стартом в README; файл compose называется compose.yaml, легаси-имя не используется.

Наблюдения, вынесенные дальше: три в #13, одно в #4.

Работа выполнена в ветке `feat/12-clickhouse-cluster`, закрывается PR #16. Все девять критериев приёмки прошли на живом стенде: холодный `make up` — 11,7 с и три здоровых контейнера, `make smoke` — 8 из 8, `make smoke-guards` — 3 из 3, `make clean` — стенд удалён без остатка. Итоги ревью: девять находок, восемь починены, одна отклонена с доводом (пустые каталоги `/clickhouse/tables/{shard}` в keeper — общее пространство имён будущих таблиц, а не мусор проверки; довод признан верным при перепроверке). Главное исправление — smoke при упавшей ноде висел 362 секунды и не прерывался по Ctrl-C; стало 107–118 мс, а при падении ноды посреди прогона — 13 секунд с ограниченной по времени уборкой. Решения, не предрешённые тикетом: образ зафиксирован точным LTS-выпуском 26.3.17.56; документация стенда живёт быстрым стартом в README; файл compose называется `compose.yaml`, легаси-имя не используется. Наблюдения, вынесенные дальше: три в #13, одно в #4.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Reference: ddmitry/clickstream-data-platform#12