Настройка кластера ClickHouse в Debian 12 Bookworm

Содержание

Введение

Я уже описывал установку и настройку самостоятельного сервера ClickHouse и установку и настройку сервиса координации ClickHouse Keeper в самостоятельной и кластерной конфигурациях. Теперь, основываясь на этих двух статьях можно заняться настройкой кластера ClickHouse.

У кластеров бывает два основных предназначения - обеспечить масштабируемость и отказоустойчивость. Бывают только отказоустойчивые кластеры, если нагрузка и объём данных небольшие. Например, в том же сервисе координации ClickHouse Keeper всегда есть один ведущий узел, который выполняет операции записи, так что такой кластер не масштабируется по операциями записи, но масштабируется по операциям чтения и обеспечивает отказоустойчивость.

ClickHouse позволяет настраивать как масштабируемые кластеры, так и отказоустойчивые. Кластер может состоять из нескольких шардов - частей, каждая из которых хранит своё подмножество общих данных. В свою очередь, каждый шард может состоять из одной или нескольких реплик, содержащих копии данных одного шарда.

В этой статье описывается настройка одного шарда, состоящего из двух взаимных реплик. Используется внешний кластер координации ClickHouse Keeper, ранее настроенный по статье Настройка кластера ClickHouse Keeper в Debian 12 Bookworm.

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

Для того, чтобы клиентам не нужно было выбирать IP-адрес, который в настоящее время способен выполнять запросы на запись, на узлы-реплики устанавливается сервис keepalived. Этот сервис согласует по протоколу VRRP, какой из исправных узлов в настоящее время будет выполнять функции главного, и назначает этому узлу выделенный IP-адрес, по которому к нему будут подключаться клиенты.

В описываемой ниже конфигурации используются следующие IP-адреса:

IP-адрес Имя узла Назначение
192.168.122.18 ch Виртуальный IP-адрес, назначаемый VRRP-сервером keepalived одному из узлов: ch0 или ch1
192.168.122.19 ch0 Сервер ClickHouse с использованием встроенной функции координации, VRRP-сервер keepalived
192.168.122.20 ch1 Сервер ClickHouse с использованием встроенной функции координации, VRRP-сервер keepalived

Настройка базовых репозиториев

Пропишем в файл /etc/apt/sources.list репозитории Debian 12 Bookworm, расположенные на зеркале mirror.ufanet.ru:

deb http://mirror.ufanet.ru/debian/ bookworm main contrib non-free-firmware
deb http://mirror.ufanet.ru/debian/ bookworm-updates main contrib non-free-firmware
deb http://mirror.ufanet.ru/debian/ bookworm-proposed-updates main contrib non-free-firmware
deb http://mirror.ufanet.ru/debian-security/ bookworm-security main contrib non-free-firmware

Отключим установку предлагаемых зависимостей, создав файл /etc/apt/apt.conf.d/suggests со следующим содержимым:

APT::Install-Suggests "false";

Отключим установку рекомендуемых зависимостей, создав файл /etc/apt/apt.conf.d/recommends со следующим содержимым:

APT::Install-Recommends "false";

Для ограничения объёма кэша пакетов 200 мегабайтами, хранящегося в каталоге /var/cache/apt/archives/, создадим файл /etc/apt/apt.conf.d/cache со следующим содержимым:

APT::Cache-Limit "209715200";

Чтобы уменьшить время ожидания при недоступности репозитория пятью секундами, создадим файл /etc/apt/apt.conf.d/timeouts со следующим содержимым:

Acquire::http::Timeout "5";
Acquire::https::Timeout "5";
Acquire::ftp::Timeout "5";

Обновим список пакетов, доступных через репозитории:

# apt-get update

Установка пакетов

Обновим уже установленные в системе пакеты:

# apt-get upgrade
# apt-get dist-upgrade

Установим дополнительные пакеты, которые могут пригодиться при работе с системой:

# apt-get install acpi-support-base vim less apt-file binutils sysstat tcpdump file dnsutils telnet psmisc traceroute net-tools man-db bzip2 ca-certificates apt-transport-https wget unzip sudo needrestart

Я привык использовать в качестве редактора по умолчанию vim, поэтому выберу его как системный редактор по умолчанию:

# update-alternatives --set editor /usr/bin/vim.basic

Настройка репозиториев ClickHouse

Устанавливаем утилиты, необходимые для установки GPG-ключа репозитория:

# apt-get install gpg dirmngr

Установим сам GPG-ключ репозитория:

# gpg --keyserver hkp://keyserver.ubuntu.com:80 --receive-key 3E4AD4719DDE9A38
# gpg --export --armor 3E4AD4719DDE9A38 > /etc/apt/trusted.gpg.d/clickhouse.asc

Пропишем в файл /etc/apt/sources.list репозиторий ClickHouse:

deb http://repo.yandex.ru/clickhouse/deb/ stable main

Обновим список пакетов, доступных через репозитории:

# apt-get update

Установка сервера ClickHouse

Установим сервер ClickHouse:

# apt-get install clickhouse-server clickhouse-client

В процессе установки будет запрошен пароль пользователя default, который в хэшированном виде будет записан в файл конфигурации /etc/clickhouse-server/users.d/default-password.xml.

Установка и настрйока клиента

Установим клиента ClickHouse:

# apt-get install clickhouse-client

Для того, чтобы от имени системного пользователя root можно было подключаться к серверу ClickHouse локально с помощью клиента clickhouse-client, создадим файл /root/.clickhouse-client/config.xml следующего вида:

<config>
        <host>localhost</host>
        <port>9000</port>
        <user>default</user>
        <password>p4$$w0rd</password>
        <database>default</database>
</config>

Поменяем права доступа к каталогу и файлу с настройками клиента так, чтобы посторонние пользователи системы не смогли их увидеть:

# chmod go= -R /root/.clickhouse-client/

Настройка сервера ClickHouse

Для изменения настроек сервера предусмотрены каталоги /etc/clickhouse-server/config.d/ и `/etc/clickhouse-server/users.d/'. Воспользуемся ими для того, чтобы облегчить обновления файлов конфигурации при дальнейших обновлениях сервера.

Настройка журналов

Первым делом настроим ведение журналиров, разместив изменённые настройки в файле /etc/clickhouse-server/config.d/logs.xml:

<clickhouse>
        <logger>
                <level>warning</level>
                <size>10M</size>
        </logger>
        <query_log remove="1" />
        <trace_log remove="1" />
        <query_thread_log remove="1" />
        <query_views_log remove="1" />
        <part_log remove="1" />
        <text_log remove="1" />
        <metric_log remove="1" />
        <asynchronous_metric_log remove="1" />
        <opentelemetry_span_log remove="1" />
        <crash_log remove="1" />
        <session_log remove="1" />
        <processors_profile_log remove="1" />
        <asynchronous_insert_log remove="1" />
        <backup_log remove="1" />
        <s3queue_log remove="1" />
        <blob_storage_log remove="1" />
</clickhouse>

Здесь я настроил уровень подробности журнала, при котором в него записываются только сообщения с уровнем важности "предупреждение" или выше. Объём одного файла журнала уменьшен с 1000 мегабайт до 10 мегабайт. Ниже отключены все средства журналирования, которые пишут данные в таблицы внутри базы данных system. Настройки по умолчанию хороши для крупных кластеров ClickHouse, в которых разнообразная журнальная и отладочная информация по сравнению с основными данными не занимает много места и не создаёт сколь-нибудь заметной дополнительной нагрузки на оборудование. Поскольку в моём кластере не предполагается хранить много информации, журнальная и отладочная информация могут заметно повысить нагрузку на серверы и занять значительный объём места на диске. При необходимости я всегда смогу снова включить это снова.

Настройка адресов и портов

Далее в файле /etc/clickhouse-server/config.d/listen.xml я поменял настройки адреса и портов, на которых сервер будет ожидать поступления входящих подключений. Подключения принимаются на всех адресах IPv4 сервера, отключается приём подклюений к портам, на которых реализуется поддержка протоколов MySQL и PostgreSQL, поскольку я пока не собираюсь пользовться этой функциональностью:

<clickhouse>
        <listen_host>0.0.0.0</listen_host>
        <mysql_port remove="1" />
        <postgresql_port remove="1" />
</clickhouse>

Настройка управления пользователями

Для включения управления доступом через SQL-запросы создадим файл /etc/clickhouse-server/config.d/access_management.xml со следующим содержимым:

<clickhouse>
        <profiles>
                <default>
                        <access_management>1</access_management>
                </default>
        </profiles>
</clickhouse>

Настройка размеров кэшей

В файле /etc/clickhouse-server/config.d/cache.xml я размещу настройки кэшей, которые совпадают с настройками по умолчанию, но которые будет удобно будет при необходимости изменить, открыв один файл:

<clickhouse>
        <profiles>
                <default>
                        <use_uncompressed_cache>0</use_uncompressed_cache>
                </default>
        </profiles>
        <uncompressed_cache_size>8589934592</uncompressed_cache_size>
        <mark_cache_size>5368709120</mark_cache_size>
</clickhouse>

Снятие ограничений на удаление

По умолчанию ClickHouse не даёт удалять таблицы и разделы объёмом больше 50 гигабайт. Чтобы снять эти ограничнения, я создал файл /etc/clickhouse-server/config.d/max_size_to_drop.xml со следующим содержимым:

<clickhouse>
        <max_table_size_to_drop>0</max_table_size_to_drop>
        <max_partition_size_to_drop>0</max_partition_size_to_drop>
</clickhouse>

Настройка количества потоков

Для ускорения запуска сервера при большом количестве фрагментов в таблицах и ускорить удаление устаревших фрагментов, уже объединённых в более крупные или оставшихся после копирования актуальных данных в новый фрагмент при очистке устаревших данных, создадим файл /etc/clickhouse-server/config.d/max_part_threads.xml с настройками количества потоков:

<clickhouse>
        <merge_tree>
                <max_part_loading_threads>16</max_part_loading_threads>
                <max_part_removal_threads>16</max_part_removal_threads>
        </merge_tree>
</clickhouse>

Настройка асинхронной вставки

Для снижения нагрузки на сервер от синхронной вставки данных создадим файл конфигурации /etc/clickhouse-server/config.d/async_insert.xml со следующими настройками:

<clickhouse>
        <profiles>
                <default>
                        <async_insert>1</async_insert>
                        <wait_for_async_insert>0</wait_for_async_insert>
                        <async_insert_max_data_size>10485760</async_insert_max_data_size>
                        <async_insert_busy_timeout_ms>1000</async_insert_busy_timeout_ms>
                </default>
        </profiles>
</clickhouse>

Настройка резервного копирования

Для настройки резервного копирование баз данных ClickHouse я создал файл /etc/clickhouse-server/config.d/backups.xml со следующим содержимым:

<clickhouse>
        <storage_configuration>
                <disks>
                        <backups>
                                <type>local</type>
                                <path>/backups/</path>
                        </backups>
                </disks>
        </storage_configuration>
        <backups>
                <allowed_disk>backups</allowed_disk>
                <allow_concurrent_backups>false</allow_concurrent_backups>
                <allow_concurrent_restores>false</allow_concurrent_restores>
        </backups>
</clickhouse>

Сразу же создадим каталог для резервных копий и поменяем права доступа к нему так, чтобы сервер ClickHouse мог работать с этим каталогом, а посторонние пользователи не имели бы к нему доступа:

# mkdir /backups/
# chown clickhouse:clickhouse /backups/
# chmod o= /backups/

Настройка координатора

При использовании внешнего сервиса координации нужно указать адреса и порты узлов, входящих в кластер координации. Эти настройки можно поместить в файл с именем /etc/clickhouse-server/config.d/keeper.xml:

<clickhouse>
        <zookeeper>
                <node>
                        <host>ck0</host>
                        <port>9181</port>
                </node>
                <node>
                        <host>ck1</host>
                        <port>9181</port>
                </node>
                <node>
                        <host>ck2</host>
                        <port>9181</port>
               </node>
        </zookeeper>
</clickhouse>

Настройка самого внешнего сервиса координации ClickHouse Keeper описана в статье Настройка кластера ClickHouse Keeper в Debian 12 Bookworm. Также в качестве внешнего сервиса координации можно использовать ZooKeeper.

Настройка узла кластера

Для настройки кластера с названием core и общим секретным ключом $3cr3t, состоящего из одного шарда и двух взаимных реплик ch0 и ch1 внутри него, создадим файл конфигурации /etc/clickhouse-server/config.d/cluster_node.xml со следующим содержимым:

<clickhouse>
        <display_name>ch0</display_name>
        <macros>
                <shard>0</shard>
                <replica>0</replica>
                <cluster>core</cluster>
        </macros>
        <remote_servers replace="1">
                <core>
                        <secret>$3cr3t</secret>
                        <shard>
                                <internal_replication>true</internal_replication>
                                <replica>
                                        <host>ch0</host>
                                        <port>9000</port>
                                </replica>
                                <replica>
                                        <host>ch1</host>
                                        <port>9000</port>
                                </replica>
                        </shard>
                </core>
        </remote_servers>
</clickhouse>

Запуск сервера ClickHouse

Осталось поменять права доступа ко всем этим файлам и можно запустить сервер ClickHouse:

# cd /etc/clickhouse-server/config.d/
# chown clickhouse:clickhouse *.xml
# systemctl start clickhouse-server

Настройка второго узла

Второй узел настраивается аналогично, меняются только идентфикатор keeper_server/server_id в файле /etc/clickhouse-server/config.d/keeper.xml:

<clickhouse>
        <keeper_server>
                <server_id>1</server_id>
        </keeper_server>
</clickhouse>

В файле /etc/clickhouse-server/config.d/cluster_node.xml меняются значения display_name и macros/replica:

<clickhouse>
        <display_name>ch1</display_name>
        <macros>
                <replica>1</replica>
        </macros>
</clickhouse>

Настройка файла имён

Чтобы не работа кластера не зависела от исправности и задержек в работе системы DNS, можно на каждом из узлов прописать в файл /etc/hosts соответствие IP-адресов и имён узлов кластера:

192.168.122.15 ck0
192.168.122.16 ck1
192.168.122.17 ck2
192.168.122.19 ch0
192.168.122.20 ch1

Установка и настройка keepalived

Установим пакет keepalived на первых двух узлах, на которых установлен сервер ClickHouse:

# apt-get install keepalived

Создадим файл /etc/keepavlived/keepalived.conf со следующим содержимым:

global_defs {
    enable_script_security
}

vrrp_script iamlive {
    script "/etc/keepalived/iamlive.sh"
    interval 1
    rise 1
    fall 3
    user root
}

vrrp_instance clickhouse {
    state BACKUP
    interface enp1s0
    virtual_router_id 18
    priority 100
    advert_int 1
    nopreempt
    #notify /etc/keepalived/keepalived-notify.sh root
    authentication {
        auth_type PASS
        auth_pass keep4liv
    }
    virtual_ipaddress {
        192.168.122.18
    }
    track_script {
        iamlive
    }
}

Для проверки исправности сервера ClickHouse и его доступности для операций записи на текущем узле создадим скрипт /etc/keepalived/iamlive.sh со следующим содержимым:

#!/bin/sh

RO=`clickhouse-client -c /root/.clickhouse-client/config.xml -q 'SELECT SUM(is_readonly) FROM system.replicas' 2>/dev/null`
if [ $? -ne 0 ] ; then
        echo "ClickHouse server does not reply"
        exit 1
fi
if [ "$RO" -ne 0 ] ; then
        echo "ClickHouse server is in read only state"
        exit 1
fi

NUM=`clickhouse-client -c /root/.clickhouse-client/config.xml -q 'SELECT COUNT(*) FROM system.replicas' 2>/dev/null`
if [ $? -ne 0 ] ; then
        echo "ClickHouse server does not reply"
        exit 1
fi
if [ "$NUM" -eq 0 ] ; then
        echo "ClickHouse does not have replicated tables"
        exit 1
fi

Поменяем права доступа к скрипту так, чтобы его можно было выполнять:

# chmod +x /etc/keepalived/iamlive.sh

Скрпит возвращает код завершения 0, если текущий узел исправен, а в противном случае какой-либо другой код.

Включим и запустим сервис keepalived:

# systemctl enable keepalived
# systemctl start keepalived

Каждый демон keepalive начнёт рассылать мультикаст-пакеты на адрес 224.0.0.18 с номером виртуального маршрутизатора, указанным в поле virtual_router_id. Они согласуют, у кого из них будет IP-адрес, указанный в секции virtual_ipaddress и поменяют настройки сетевого интефрейса, указанного в опции interface так, чтобы IP-адрес был назначен только у одного из них.

Если оба узла активны и могут выполнять функции записи, то виртуальный IP-адрес должен быть назначен только одному из них. В таком случае принимаются во внимание опции nopreempt и priority. Опция nopreempt указывает, что при переходе одного из узлов из неисправного состояния в исправное IP-адрес должен оставаться у того исправного узла, который уже находился в исправном состоянии ранее и владел этим IP-адресом. Если эта опция не указана, то IP-адрес вернётся тому узлу, у которого в поле priority указано большее значение.

Для проверки, на каком из узлов сейчас настроен переходящий IP-адрес, можно воспользоваться командой:

# ip addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host noprefixroute 
       valid_lft forever preferred_lft forever
2: enp1s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 52:54:00:6e:dc:22 brd ff:ff:ff:ff:ff:ff
    inet 192.168.122.19/24 brd 192.168.122.255 scope global enp1s0
       valid_lft forever preferred_lft forever
    inet 192.168.122.18/32 scope global enp1s0
       valid_lft forever preferred_lft forever
    inet6 fe80::5054:ff:fe6e:dc22/64 scope link 
       valid_lft forever preferred_lft forever

Использованные материалы