Модуль 29. Kubernetes для ClickHouse
ClickHouse — MPP-СУБД для быстрых аналитических запросов. В Kubernetes он раскрывается через оператор (управление жизненным циклом), StatefulSet-паттерн (устойчивая идентичность подов) и грамотную работу с хранилищем (RWO-блок для «горячего», S3 для «холодного»/бэкапов).
С Iceberg работаем аккуратно: чаще читаем из Iceberg (lakehouse) и пишем туда внешними инструментами (Spark/Trino/dbt-Spark), а не самим ClickHouse — ниже разберём почему.
Оператор ClickHouse: что он делает и как его «впрячь»
Что даёт оператор
- CRD-описание кластера (обычно ClickHouseInstallation/CHI): сколько кластеров, шардов, реплик, какой сторидж и т. п.
- Генерацию StatefulSet/Service/ConfigMap/Secret, управляемые роллинг-обновления (по шард/реплика), health-checks и частичный self-heal.
- Хуки/Actions: прогон DDL-скриптов, запуск бэкапов/восстановлений, подготовка пользователей и пр.
Мини-скелет CHI (идея, не копируйте без адаптации):
apiVersion: clickhouse.altinity.com/v1
kind: ClickHouseInstallation
metadata: { name: ch-analytics }
spec:
configuration:
clusters:
- name: c1
layout:
shardsCount: 2
replicasCount: 2
templates:
podTemplate: ch-tpl
volumeClaimTemplate: ch-data
templates:
podTemplates:
- name: ch-tpl
spec:
containers:
- name: clickhouse
image: clickhouse/clickhouse-server:stable
volumeMounts: [{ name: data, mountPath: /var/lib/clickhouse }]
volumeClaimTemplates:
- name: ch-data
spec:
accessModes: [ReadWriteOnce]
storageClassName: fast-rwo
resources: { requests: { storage: 1Ti } }
Практические заметки
- Оператор сам создаст Headless Service и StatefulSet на реплики; PVC per pod — обязательно.
- Для Keeper (см. ниже) используйте отдельный шаблон (часто — отдельный StatefulSet внутри того же CHI/кластера) либо внешний Keeper-кластер.
Топология: шардинг × репликация и раскладка по зонам
Шард — горизонтальное разбиение данных; реплика — копия шард-данных для HA/чтения. Классический шаблон для прод: 2×2 (2 шарда × 2 реплики) с ростом «вширь».
Правила проектирования
- Разводите реплики по разным нодам/АЗ: podAntiAffinity + TopologySpreadConstraints.
- PDB на группу реплик, чтобы плановые работы/аварии не «убивали» сразу обе копии.
- Храните «ключ шардирования» в одном месте (DDL/инфраструктурный слой), используйте Distributed-таблицы для «единых» запросов.
Read/Write-маршруты
- Чтение в ClickHouse обычно масштабируется «из коробки» (любой репликой шарда).
- Для записи: держите разумный баланс — крупные INSERT батчами, следите за parts и merges (см. наблюдаемость).
Keeper и таблицы ReplicatedMergeTree
ClickHouse Keeper (или ZooKeeper) координирует репликацию и сервисные метаданные. Рекомендуем ClickHouse Keeper (3–5 узлов) как отдельные pod’ы (часто в том же CHI).
- Размер кворума: нечётное число (3/5), разведённые по зонам.
- Хранилище Keeper — быстрый RWO-том, маленький, но надёжный (и Retain).
- В ClickHouse используйте ReplicatedMergeTree (и производные) для таблиц, включающих репликацию.
- Для кластерной агрегации — Distributed таблицы, указывающие на шард/реплику.
Хранилище: «горячее» локально, «холодное» в объектке
Горячие данные / метаданные
- RWO-блок (Ceph RBD/облачные диски/NVMe). FS — XFS (часто лучше для больших последовательных операций), либо ext4 — протестируйте.
- SC c WaitForFirstConsumer и ReclaimPolicy=Retain для прод-томов.
- Избегайте NFS/RWX под основные таблицы — будет боль по метаданным/блокировкам.
Холод/архив — S3
- Через StoragePolicy подключайте S3-диск (MinIO/облако) для второго уровня хранения («tiered storage»), для бэкапов, для внешних таблиц.
- Управляйте размером партиций/частей: мелкие файлы в S3 дают взрыв накладных расходов. Планируйте compaction/TTL.
Идея StoragePolicy (фрагмент):
<storage_configuration>
<disks>
<disk name="local" path="/var/lib/clickhouse/" />
<disk name="s3" type="s3">
<endpoint>https://s3.example</endpoint>
<access_key_id>...</access_key_id> <!-- лучше Secret/ENV -->
<secret_access_key>...</secret_access_key>
<metadata_path>/var/lib/clickhouse/s3_meta/</metadata_path>
</disk>
</disks>
<policies>
<policy name="hot_warm">
<volumes>
<volume name="hot"> <disk>local</disk> </volume>
<volume name="warm"> <disk>s3</disk> </volume>
</volumes>
</policy>
</policies>
</storage_configuration>
(Креды — через Secret/ESO/Vault, не в явном виде в манифестах.)
Интеграция с S3 и Iceberg: практичный взгляд
S3:
- Отлично подходит для lakehouse, «тёплого» слоя, бэкапов и внешних таблиц.
- При tiered-storage следите за частями и мерджами — маленькие части на S3 = долгая агрегация.
- Сжатие/Parquet там, где уместно (внешние источники для чтения через table-функции).
Iceberg:
- Реальный прод-паттерн: ClickHouse читает Iceberg-таблицы (через table-функцию/движок чтения), а пишут/модифицируют их Spark/Trino/dbt-Spark.
- Почему так: транзакционная модель/метаданные Iceberg, оптимизация файлов и компакты — «родное» поле для Spark/Trino. ClickHouse — как быстрый движок чтения/федерации.
- Если всё-таки писать из CH — пилотируйте отдельно, валидируйте метаданные/совместимость версий и готовьтесь к компактам внешней системой.
Наблюдаемость и эксплуатация
Что собирать
- Merged parts, backlog merges, replication queue length, rejected queries, max_part_size, disk usage/inodes.
- По Keeper: лидерские смены, задержки, ошибки диска/сети.
- По кластеру: p95/99 latency на ключевых запросах (по query_log/метрикам экспорта), 5xx (если публикуете HTTP), saturation по CPU/IOPS.
Инструменты
- clickhouse-exporter в Prometheus (есть готовые дашборды для Grafana).
- Логи/аудит — в Loki/EFK; JSON-структура.
-
Алёрты:
- MergesBacklogHigh, ReplicationQueueHigh, SpaceLow(<15%), KeeperUnstable, RejectedQueriesHigh, QueryLatencySLOBurn.
SLO-идеи
- p95 запросов витрин ≤ N секунд; успешность запросов ≥ 99%; backlog merges < порога; репликация без задержек > X минут.
Бэкапы, миграции и DR
Бэкапы
- clickhouse-backup → S3/MinIO (рассылки, расписания через CronJob/Operator action).
- Тестируйте восстановление на отдельный namespace (cold-restore) ежемесячно.
- Для больших таблиц — инкрементальные бэкапы и компакты.
Миграции
- DDL через операторные хуки/скрипты; согласованные изменения таблиц в кластере (порядок: реплики/шарды).
- Расширение кластера: добавляете шарды → rebalancing средствами CH (аккуратно; прогоняйте на стенде).
DR
- Второй кластер (пассивный) + периодические бэкапы и выборочные реплики; метаданные/конфиги — в GitOps.
- Проверяйте RPO/RTO, особенно для «тёплого» слоя в S3.
Безопасность
- Секреты (S3, пользователи CH) — Vault/External Secrets Operator/Secret Store CSI; шифрование Secret’ов at-rest.
- Сетевые политики (NetworkPolicy) — доступ к CH/Keeper/S3 «по белому списку».
- Сигнатуры и скан образов (cosign/Trivy), запрет :latest.
- RBAC — минимальный; операторам не давать «кластер-админа навсегда».
Практика (лабораторка за 1–2 дня)
- Развернуть оператор и кластер 2×2 (две зоны) с Keeper=3.
- Хранилище: SC fast-rwo (RBD/NVMe), PVC per pod, Retain.
- Подключить S3: StoragePolicy hot_warm, вынести архивные партиции в S3; завести пользователя/ключ через ESO.
- Нагрузочный тест (INSERT батчами + SELECT с агрегацией): посмотреть merges/replication backlog.
- Наблюдаемость: включить clickhouse-exporter, собрать дашборд и 5–7 алёртов.
- Бэкап/restore: clickhouse-backup в S3 → восстановление в тестовый ns.
- Чтение Iceberg: настроить доступ к lakehouse (таблица/функция чтения), замерить p95.
Риски и анти-паттерны
|
Риск |
Проявление |
Что делать |
|---|---|---|
|
NFS/RWX под данные |
«Стэлы», тормоза, сбои merges |
Только RWO-блок, XFS/ext4; RWX — только для вспом. файлов |
|
Primary/replica на одной ноде/АЗ |
Сбой = потеря шарда |
Anti-affinity + spread; PDB |
|
Мелкие части в S3 |
Долгие запросы/дорогой S3 |
Батчи INSERT, compaction/TTL, план партиций |
|
Загруженный Keeper |
Репликация лагает, ошибки |
Выделить диски/Keeper-узлы, следить за latency |
|
Readiness «всегда зелен» |
Трафик в «полудохлые» реплики |
Пробы с реальной проверкой роли/доступа к Keeper/диску |
|
Automerge/обновления без стенда |
Простои при DDL |
Стенд, пошаговый rollout, окна изменений |
|
Iceberg записи прямо из CH |
Несогласованность метаданных/файлов |
Писать через Spark/Trino, CH — читать/федерация |
|
Удалили PVC (Delete) |
Потеря данных |
Reclaim=Retain, регламент утилизации PV |
Чек-лист «готово к продакшену (ClickHouse в k8s)»
- Оператор развёрнут; кластеры описаны CR’ами; обновления — через GitOps.
- Топология ≥ 2×2; Anti-affinity/Spread; PDB на реплики.
- Keeper 3–5 узлов, на RWO-дисках; мониторинг Keeper-латентности.
- Диски: RWO-блок, XFS/ext4; SC: WaitForFirstConsumer, Retain.
- StoragePolicy: hot (локально) + warm/архив (S3); секреты — через Vault/ESO.
- Экспортеры/дашборды/алерты: merges/replication backlog, space<15%, rejected, latency.
- Бэкапы (clickhouse-backup→S3) и ежемесячный restore-день; DR-план.
- Политики безопасности: RBAC минимум, image-signing/scan, NetworkPolicy.
Вопрос-ответ
В: С чего начать — один кластер или сразу несколько?
О: Для одной предметной области — один кластер 2×2. Если у вас разные SLA/команды/паттерны данных — несколько кластеров (и изоляция по Namespace/NodePool).
В: Keeper обязательно выносить отдельно?
О: Рекомендуется как минимум логически отделить (свои pod’ы, диски, антиплотность по зонам). Это снижает взаимное влияние и упрощает диагностику.
В: Можно ли хранить всё в S3 (без локального диска)?
О: Для активных MergeTree-таблиц — не лучшая идея. Делайте tiered-storage (горячее локально, холодное — в S3) и следите за частями/компактами.
В: Как правильно шардировать?
О: Ключ по естественной кардинальности (часто — user_id/tenant/дата), чтобы запросы «попадали» в один шард. Для «перекосов» — ребаланс шардов, но это операция не моментальная.
В: Что мониторить в первую очередь?
О: merges backlog, replication queue, rejected queries, дисковое пространство и p95 latency ключевых запросов; по Keeper — лидер/latency/ошибки.
В: Можем ли писать в Iceberg прямо из ClickHouse?
О: Технически — варианты появляются, но для прод-транзакций/эволюции схем надёжнее писать через Spark/Trino и компакты делать там; ClickHouse — читать/федерация.
В: Как бороться с «мелкими файлами»?
О: Крупные INSERT батчами, настройки партиционирования, плановые компакты/TTL и регламенты ingestion.
ClickHouse в Kubernetes — это оператор + правильная топология (шарды×реплики) + дисциплина хранения (RWO-диски для «горячего», S3 для «тёплого/холодного» и бэкапов) + наблюдаемость (merges/replication/latency). Iceberg используем как lakehouse-слой, куда пишут Spark/Trino, а читает ClickHouse. Соблюдая эти принципы, вы получаете быстрый, предсказуемый и восстановимый аналитический кластер под BI/DWH.



