Перейти к основному содержимому
Версия: 5.2

Настройка ClickHouse Keeper

ClickHouse Keeper — это встроенная распределенная координационная служба ClickHouse, отвечающая за работу репликации и выполнение распределенных DDL-запросов. Keeper полностью совместим по протоколу с ZooKeeper, но реализован на C++ и использует алгоритм консенсуса RAFT, что обеспечивает линейризуемые записи и более предсказуемое поведение при отказах.

Когда нужен ClickHouse Keeper

Отдельная настройка ClickHouse Keeper требуется только в кластерных сценариях: когда у вас есть несколько узлов ClickHouse и используются реплицируемые таблицы (ReplicatedMergeTree) или распределенные запросы ON CLUSTER. В односерверной установке Keeper не обязателен и может быть не развернут.


Варианты развертывания Keeper

ClickHouse Keeper может работать в двух режимах:

  1. Как отдельный сервис. Устанавливается пакетом clickhouse-keeper и запускается как отдельный процесс со своим конфигурационным файлом:

    • основной файл конфигурации: /etc/clickhouse-keeper/keeper_config.xml
    • дополнительные файлы: /etc/clickhouse-keeper/keeper_config.d/*.xml или *.yaml
  2. Как часть процесса clickhouse-server. В этом случае конфигурационный блок <keeper_server> добавляется в основную конфигурацию сервера:

    • основной файл: /etc/clickhouse-server/config.xml
    • либо отдельный файл в /etc/clickhouse-server/config.d/keeper.xml

Рекомендуемый подход для production — отдельные узлы ClickHouse Keeper и отдельные конфигурационные файлы в /etc/clickhouse-keeper/, чтобы независимым образом масштабировать и обслуживать координационный кластер.


Базовая структура конфигурации ClickHouse Keeper

Основной блок конфигурации Keeper — это элемент <keeper_server>. В типичном виде он включает:

Блок конфигурации Keeper
<clickhouse>
<logger>
<level>trace</level>
<log>/var/log/clickhouse-keeper/clickhouse-keeper.log</log>
<errorlog>/var/log/clickhouse-keeper/clickhouse-keeper.err.log</errorlog>
<size>1000M</size>
<count>10</count>
</logger>

<max_connections>4096</max_connections>

<listen_host>0.0.0.0</listen_host>

<keeper_server>
<!-- Порт, на котором клиенты (ClickHouse-серверы или приложения) подключаются к Keeper -->
<tcp_port>9181</tcp_port>

<!-- Уникальный идентификатор узла Keeper в кластере -->
<server_id>1</server_id>

<log_storage_path>/var/lib/clickhouse/coordination/logs</log_storage_path>
<snapshot_storage_path>/var/lib/clickhouse/coordination/snapshots</snapshot_storage_path>

<!-- Внутренние настройки координации -->
<coordination_settings>
<operation_timeout_ms>10000</operation_timeout_ms>
<min_session_timeout_ms>10000</min_session_timeout_ms>
<session_timeout_ms>100000</session_timeout_ms>
<raft_logs_level>information</raft_logs_level>
<compress_logs>false</compress_logs>
</coordination_settings>

<!-- enable sanity hostname checks for cluster configuration (e.g. if localhost is used with remote endpoints) -->
<hostname_checks_enabled>true</hostname_checks_enabled>

<!-- Описание всех узлов Keeper, участвующих в кворуме -->
<raft_configuration>
<server>
<id>1</id>
<!-- Internal port and hostname -->
<hostname>ch-keeper-01</hostname>
<port>9234</port>
</server>
<server>
<id>2</id>
<!-- Internal port and hostname -->
<hostname>ch-keeper-02</hostname>
<port>9234</port>
</server>
<server>
<id>3</id>
<!-- Internal port and hostname -->
<hostname>ch-keeper-03</hostname>
<port>9234</port>
</server>

<!-- Add more servers here -->

</raft_configuration>
</keeper_server>


<openSSL>
<server>
<!-- Used for secure tcp port -->
<!-- openssl req -subj "/CN=localhost" -new -newkey rsa:2048 -days 365 -nodes -x509 -keyout /etc/clickhouse-server/server.key -out /etc/clickhouse-server/server.crt -->
<!-- <certificateFile>/etc/clickhouse-keeper/server.crt</certificateFile> -->
<!-- <privateKeyFile>/etc/clickhouse-keeper/server.key</privateKeyFile> -->
<!-- dhparams are optional. You can delete the <dhParamsFile> element.
To generate dhparams, use the following command:
openssl dhparam -out /etc/clickhouse-keeper/dhparam.pem 4096
Only file format with BEGIN DH PARAMETERS is supported.
-->
<!-- <dhParamsFile>/etc/clickhouse-keeper/dhparam.pem</dhParamsFile> -->
<verificationMode>none</verificationMode>
<loadDefaultCAFile>true</loadDefaultCAFile>
<cacheSessions>true</cacheSessions>
<disableProtocols>sslv2,sslv3</disableProtocols>
<preferServerCiphers>true</preferServerCiphers>
</server>
</openSSL>

</clickhouse>

Ключевые параметры:

  • tcp_port — порт для клиентских подключений (ClickHouse-серверы, clickhouse-keeper-client, утилиты). Рекомендуемое значение — 9181 (во избежание конфликта со стандартным портом ZooKeeper 2181)
  • server_id — уникальный числовой идентификатор узла Keeper. Значения должны быть уникальными. Рекомендуется простая последовательность 1, 2, 3, ...
  • log_storage_path — путь к журналам RAFT-координации
  • snapshot_storage_path — каталог для снапшотов состояния (сжатое состояние дерева znode)
  • coordination_settings — детальная настройка таймаутов, частоты heartbeat-сообщений, параметров снапшотов и логов. В большинстве случаев достаточно базовых значений из примера
  • raft_configuration — описание всех участников RAFT-кворума
Рекомендуется использование нечетного числа узлов

Кластер Keeper должен состоять из нечетного числа узлов (обычно 3 или 5). Это необходимо для достижения кворума и повышения отказоустойчивости.


Настройка RAFT-кворума (<raft_configuration>)

Блок <raft_configuration> описывает все узлы Keeper, которые участвуют в кворуме RAFT:

<raft_configuration>
<secure>false</secure>

<server>
<id>1</id>
<hostname>ch-keeper-01</hostname>
<port>9234</port>
</server>
<server>
<id>2</id>
<hostname>ch-keeper-02</hostname>
<port>9234</port>
</server>
<server>
<id>3</id>
<hostname>ch-keeper-03</hostname>
<port>9234</port>
</server>
</raft_configuration>

Для каждого <server> задаются:

  • id — идентификатор сервера в кворуме RAFT. Он должен совпадать с server_id в <keeper_server> на соответствующем узле
  • hostname — имя хоста, по которому другие узлы могут связаться с этим Keeper. Рекомендуется использовать DNS-имена, а не IP-адреса, чтобы сохранять стабильное соответствие server_idhostname
  • port — порт внутреннего взаимодействия между узлами Keeper (межсерверный RAFT-порт). Он отличается от tcp_port, который используется клиентами
Стабильность идентификаторов

При замене или переносе Keeper-узла важно не переиспользовать старый server_id для другого физического сервера и не "перемешивать" соответствия server_id ↔ hostname. Это критично для корректности RAFT-кворума.


Внутренние настройки координации

Блок <coordination_settings> отвечает за таймауты и параметры работы RAFT:

<coordination_settings>
<operation_timeout_ms>10000</operation_timeout_ms>
<min_session_timeout_ms>10000</min_session_timeout_ms>
<session_timeout_ms>100000</session_timeout_ms>
<raft_logs_level>information</raft_logs_level>
<compress_logs>false</compress_logs>
</coordination_settings>

В большинстве случаев достаточно использовать рекомендуемые значения. Их изменение имеет смысл только при явных проблемах (частые пере-выборы лидера, нестабильная сеть, очень большой объем метаданных).


Размещение конфигурации и запуск Keeper

Отдельный сервис clickhouse-keeper

В этом варианте:

  • основной файл конфигурации: /etc/clickhouse-keeper/keeper_config.xml
  • дополнительные файлы: /etc/clickhouse-keeper/keeper_config.d/*.xml или *.yaml

После настройки конфигурации выполните следующие команды:

sudo systemctl enable clickhouse-keeper
sudo systemctl start clickhouse-keeper
sudo systemctl status clickhouse-keeper

Альтернативно, можно запустить Keeper напрямую:

clickhouse-keeper --config /etc/clickhouse-keeper/keeper_config.xml
# или
clickhouse keeper --config /etc/clickhouse-keeper/keeper_config.xml

Встроенный Keeper в процессе clickhouse-server

Если Keeper запускается как часть clickhouse-server, блок <keeper_server> добавляется в конфигурацию сервера:

<clickhouse>
<!-- ... прочие настройки ClickHouse ... -->

<keeper_server> ... </keeper_server>
</clickhouse>

После изменения конфигурации достаточно перезапустить сервер:

sudo systemctl restart clickhouse-server

В этом случае процесс ClickHouse и Keeper общий. В production-окружениях такой вариант обычно используют только для небольших тестовых стендов.


Интеграция ClickHouse Keeper с ClickHouse Server

Со стороны ClickHouse-серверов ClickHouse Keeper выглядит как ZooKeeper-совместимый сервис. На каждом узле ClickHouse необходимо указать координаторов в раззделе <zookeeper>:

<clickhouse>
<!-- ... -->

<zookeeper>
<node>
<host>ch-keeper-01</host>
<port>9181</port>
</node>
<node>
<host>ch-keeper-02</host>
<port>9181</port>
</node>
<node>
<host>ch-keeper-03</host>
<port>9181</port>
</node>
</zookeeper>

<!-- Макросы для настройки реплицируемых таблиц -->
<macros>
<cluster>cluster_name</cluster>
<shard>01</shard>
<replica>01</replica>
</macros>
</clickhouse>

Важно, чтобы список узлов в <zookeeper> соответствовал фактической конфигурации Keeper-кластера (тем же hostname и tcp_port, которые заданы в <keeper_server>).


Параметр <listen_host> и особенности IPv6

По умолчанию ClickHouse создает несколько записей listen_host, чтобы слушать локальный интерфейс по IPv4 и IPv6 (127.0.0.1 и ::1). Если требуется принимать подключения с других хостов, обычно добавляют строку:

<listen_host>0.0.0.0</listen_host>

Это wildcard-адрес только для IPv4: сервер будет слушать все IPv4-интерфейсы узла, но не будет открывать порты на IPv6. Для систем, где используется только IPv4, такой вариант предпочтителен и дополнительно снимает ряд проблем с IPv6.

IPv6 и проблемы с запуском ClickHouse

На некоторых дистрибутивах IPv6 в ядре отключен или не настроен. В этом случае попытка слушать wildcard-адрес IPv6 может приводить к ошибкам.

<listen_host>::</listen_host>

Если на сервере фактически нет IPv6-поддержки, рекомендуется:

  • не использовать <listen_host>::</listen_host>

  • явно указать IPv4-вариант:

    <listen_host>0.0.0.0</listen_host>
  • при необходимости дополнительно отключить IPv6 в конфигурации ClickHouse/Keeper:

    <enable_ipv6>false</enable_ipv6>

Это заставит ClickHouse слушать только IPv4-интерфейсы и избавит от ошибок, связанных с отсутствием IPv6.

Одновременная поддержка IPv4 и IPv6

Если в инфраструктуре используется IPv6 и сервер должен принимать подключения по обоим протоколам, вместо 0.0.0.0 можно использовать wildcard-адрес IPv6:

<listen_host>::</listen_host>

В этом случае ClickHouse откроет порты сразу на всех IPv6- и IPv4-интерфейсах (при условии, что IPv6 включен в системе). Такой режим стоит включать только в сочетании с корректной настройкой фаервола, сетевых ACL и политик доступа пользователей.


Проверка работоспособности ClickHouse Keeper

Через ClickHouse

С точки зрения ClickHouse-серверов состояние Keeper можно проверить запросом к системной таблице system.zookeeper:

SELECT *
FROM system.zookeeper
WHERE path IN ('/', '/clickhouse');

Наличие узлов /clickhouse и служебных веток (например, /clickhouse/task_queue/ddl) говорит о том, что Keeper доступен и используется для координации.

Через утилиту clickhouse-keeper-client

ClickHouse содержит консольную утилиту clickhouse-keeper-client, которая умеет работать с Keeper по его нативному протоколу:

clickhouse-keeper-client -h ch-keeper-01 -p 9181

В интерактивном режиме доступны команды, похожие на ZooKeeper-клиент:

  • ls / — просмотр дочерних znode
  • get '/clickhouse' — чтение значения узла
  • set '/clickhouse/test' 'value' — запись значения
  • exists '/clickhouse' — проверка существования узла

Это удобный способ проверки доступности Keeper и диагностики содержимого дерева znode.

Four-letter команды

Как и ZooKeeper, ClickHouse Keeper поддерживает набор «четырехбуквенных» команд, которые отправляются на клиентский порт по TCP, например через nc:

echo mntr | nc ch-keeper-01 9181
  • команда mntr выводит значения метрик: состояние узла (лидер/фолловер), количество подключений, задержки и т.д.
  • команда stat показывает краткую сводку о состоянии сервера и клиентов, а ruok проверяет доступность службы (возвращает imok при работоспособности)

Рекомендации по эксплуатации

  • для production-кластеров рекомендуется минимум 3 узла ClickHouse Keeper на отдельных хостах или контейнерах
  • при изменении топологии кластера (добавление/удаление Keeper-узлов) внимательно следите за тем, чтобы не нарушить уникальность server_id и соответствие server_id ↔ hostname во всех конфигурациях