Настройка отказоустойчивого кластера на PostgreSQL
Назад

Настройка отказоустойчивого кластера на PostgreSQL

Настройка отказоустойчивого кластера на PostgreSQL

В данном разделе будут рассмотрены варианты реализации отказоустойчивого кластера на PostgreSQL на примере использования таких решений как Patroni и Postgres Pro BiHA, а также HAProxy для создание единой точки входа со стороны «: Предприятие».

Для создания единой точки входа также можно использовать расширенную строку подключения с указанием нескольких хостов. Эта возможность будет подробно рассмотрена в статье.   

Отказоустойчивый кластер на основе Patroni

Patroni является внешним сервисом по отношению к Postgres и выполняет роль менеджера кластера. Основная задача Patroni - обеспечение надежного переключения роли ведущего узла на резервный узел.

Для максимальной доступности СУБД в кластере Patroni необходимо хранить и, при необходимости, изменять информацию о роли узлов. Для этого используется DCS (Distributed Configuration System), которое реализуется с помощью etcd или consul и представляет собой распределенное хранилище конфигурации ключ/значение.

Схема настройки отказоустойчивого кластера на основе Patroni

На данной схеме (рис. 1) рассмотрен вариант, состоящий из одного мастера и реплики, и который позволяет пережить недоступность одного из узлов. Достоинством такого варианта является его экономичность.

Узлы распределенного хранилище etcd в этом случае расположены на серверах СУБД и сервере . При значительной нагрузке на серверах могут быть замедлены операции с etcd, например, из-за конкуренции записи на диск. При недоступности одного из узлов etcd текущий мастер может сложить с себя полномочия и передать их другому узлу кластера, что может привести к ложным срабатываниям при повышенной загрузке серверов, где расположены узлы etcd.  

В этом случае стоит вынести узлы etcd на другие менее загруженные сервера. Кроме того, можно попробовать скорректировать параметры Patroni ttl, loop_wait, retry_timeout, влияющие на периодичность проверки состояния кластера, чтобы за счет их увеличения пережить кратковременные пики нагрузки.   

Ссылка на документацию: 

https://patroni.readthedocs.io/en/latest/dynamic_configuration.html


Рис. 1 Отказоустойчивый кластер из двух узлов (использование Patroni + Etcd + HAProxy)

Рис. 1 Отказоустойчивый кластер из двух узлов (использование Patroni + Etcd + HAProxy)

На схеме (рис. 2), приведенной ниже, рассмотрен более сложный вариант, состоящий из трех узлов, один из которых синхронный. В отличие от варианта, состоящего из двух узлов (рис. 1), такой кластер может пережить недоступность двух узлов или повторного сбоя в кластере.

Кроме того, за счет синхронной репликации исключаются потери данных, т.к. каждая транзакция фиксируется одновременно на мастере и на реплике. Обратной стороной медали здесь является потеря в производительности операций, т.к. приходится ожидать фиксации транзакции не только на основном, но и на резервном сервере. В случае, если синхронная реплика станет не доступной, Patroni переведет кластер в асинхронный режим для того, чтобы текущий мастер смог принимать клиентские подключения на запись.

Включить синхронную репликацию можно, с помощью параметров Patroni: 

  • synchronous_mode – включение/выключение синхронного режима на уровне всего отказоустойчивого кластера. При включении этого параметра Patroni будет повышать до мастера только синхронные реплики. Если синхронная реплика не будет доступна, то Patroni переведет кластер в асинхронный режим, чтобы иметь возможность принимать запросы на запись от клиентских соединений;   
  • synchronous_mode_strict – более строгий режим синхронной репликации. Мастер не будет переведен в асинхронный режим при недоступности синхронных реплик и перестанет принимать клиентские запросы на запись пока синхронная реплика не появится снова;
  • maximum_lag_on_failover – максимальное количество данных, которые могут быть потеряны при повышении реплики до мастера.

Ссылка на документацию: 

https://patroni.readthedocs.io/en/latest/replication_modes.html

Для администрирования отказоустойчивого кластера используется утилита patronictl (https://patroni.readthedocs.io/en/latest/patronictl.html). С ее помощью можно просматривать информацию о кластере и состоянии его узлов, изменять параметры кластера, выполнять ручное переключение на другой узел, восстанавливать резервные узлы, выполнять перезапуск узлов кластера и т.д.

Единая точка входа из

Для создания единой точки входа со стороны , в связке с Patroni используется HAProxy. 

В качестве точки подключения в нужно указывать сервер, где установлен HAProxy. Порт, по умолчанию, используется стандартный для Postgres 5432.

HAProxy от Patroni по REST API может получить информацию по тому, какой сервер является мастером, а какой репликой, и выполнить подключение только к доступному для записи серверу (запрос к REST API Patroni вернет код 200, если узел работает как мастер).

Настройка осуществляется через конфигурационный файл haproxy.cfg


Рисунок Перед рисунком 2.png
Рис. 2 Отказоустойчивый кластер из трех узлов (использование Patroni + Etcd + HAProxy)

Рис. 2 Отказоустойчивый кластер из трех узлов (использование Patroni + Etcd + HAProxy)

Пошаговую настройку Patroni + Etcd + HAProxy можно выполнить по инструкции с сайта ИТС: https://its.1c.ru/db/metod8dev/content/5971/hdoc (с учетом информации из текущего раздела).

Отказоустойчивый кластер на основе Postgres Pro BiHA

BiHA - это расширение Postgres Pro, которое управляется утилитой bihactl и функциями из состава расширения. В сочетании с доработками ядра, SQL интерфейсом и служебным процессом biha-worker, координирующим узлы кластера, BiHA превращает несколько узлов в кластер с физической репликацией Postgres и встроенным аварийным переключением узлов, отказоустойчивостью и автоматическим восстановлением после отказа.

Ключевые особенности:

  • для организации кластера нужно минимум три сервера, но третий узел можно настроить как рефери, используемый только в роли наблюдателя для обеспечения кворума, т.е. он не может стать лидером;
  • не требуется наличие внешних компонент, для которых также нужно обеспечить отказоустойчивость и доступность;
  • удобное управление кластером с помощью утилиты bihactl (инициализация и добавление узлов), запросам к функциям и представлениям расширения biha (просмотр состояний узлов, ручное переключение на мастер, установка параметров кластера);
  • поддержка синхронной и асинхронной репликации может быть задана для кластера в целом;  
  • с помощью HAProxy возможно настроить единую точку входа со стороны  посредством вызова проверочного скрипта из внешней команды конфигурационного файла haproxy.cfg;
  • реализовано в Postgres Pro Enterprise начиная с версии 16.

Схема настройки отказоустойчивого кластера на основе BiHA

Существует несколько вариантов конфигурации узлов: три и более узлов (рис. 3), два узла (мастер и реплика) и вариант, когда к двум узлам (мастер и реплика) добавляется еще узел рефери.

Вариант, состоящий из двух серверов, в данной статье не рассматривается, т.к. при отказе основного сервера в такой конфигурации, для предотвращения Split Brain (разделение кластера, когда клиентские соединения могут записывать данные на оба сервера) кластер будет доступен только для чтения, т.е. станет фактически недоступным из .

Для решения этой проблемы используется узел-рефери, участвующий в голосовании во время выборов нового мастера при отказе основного сервера, что позволяет избежать потенциального разделения кластера. В зависимости от режима referee или referee_with_wal узел-рефери может принимать только участие в выборе нового мастера, либо также принимать участие в выборах и дополнительно реплицировать данные журнала WAL,  чтобы новый мастер получил все файлы WAL с узла рефери (если там оказались самые последние журнальные записи перед сбоем мастера). 

Рис. 3 Отказоустойчивый кластер из трех узлов (расширенная строка подключения libpq)

Рис. 3: Отказоустойчивый кластер из трех узлов (расширенная строка подключения libpq)

На приведенной схеме (рис. 3) узел-рефери может обладать минимальными аппаратными ресурсами, поскольку он не содержит данных и будет являться только наблюдателем за другими узлами кластера.

Ссылки на документацию:

https://postgrespro.ru/docs/enterprise/16/biha

https://postgrespro.ru/clusters/biha

Инициализация отказоустойчивого кластера

При инициализации кластера можно создать узел мастера и узлы реплики с нуля, либо преобразовать уже существующие узлы и включить их в отказоустойчивый кластер. Для инициализации кластера и добавления в него узлов используется утилита bihactl, также с ее помощью можно посмотреть статус каждого узла (https://postgrespro.ru/docs/enterprise/16/bihactl).

Пример команды для инициализации существующего кластера Postgres (опция --convert):

sudo -u postgres /opt/pgpro/ent-16/bin/bihactl init --convert --biha-node-id=1 --host=192.168.50.01 --port=5432 --biha-port=5433 --nquorum=2 --pgdata=/var/lib/pgpro/ent-16/data/

Описание параметров:

  • biha-node-id – уникальный идентификатор узла
  • host, port – адрес узла
  • biha_port – порт для обмена служебной информацией между узлами
  • nquorum – число работающих узлов, участвующих в голосовании по выбору нового лидера
  • pgdata – каталог данных кластера Postgres

При инициализации кластера BiHA создается файл pg_hba.biha.conf (включается в основной файл pg_hba.conf с помощью команды include pg_hba.biha.conf) и файл postgresql.biha.conf который включен в postgresql.conf. В файле pg_hba.biha.conf для узла может быть указан метод аутентификации scram-sha-256 (в зависимости от версии BiHA), что может быть несовместимо с существующими настройками хранения паролей, например если параметр конфигурации password_encryption установлен в md5. В этом случае метод аутентификации в файле pg_hba.biha.conf нужно также выставить в md5.

Кроме того, чтобы узлы кластера BiHA могли подключаться друг к другу, необходимо для каждого узла в домашней директории пользователя Postgres (/var/lib/postgresql/) заполнить файл паролей .pgpass и разрешить доступ к нему только для владельца:

sudo -u postgres mcedit /var/lib/postgresql/.pgpass

*:5432:*:biha_replication_user:<password> - шаблон для заполнения

sudo chmod 600 /var/lib/postgresql/.pgpass

Добавление ведомого узла в кластер

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

sudo -u postgres psql -h <IPServer> -p 5432 -U biha_replication_user -d postgres

Если подключение проходит успешно, то можно добавить узел в кластер BiHA с помощью команды bihactl add на ведомом узле:

sudo -u postgres /opt/pgpro/ent-16/bin/bihactl add --biha-node-id=2 --host=192.168.50.02 --port=5432 --biha-port=5433 --use-leader "host=192.168.50.01 port=5432 biha-port=5433" --pgdata=/var/lib/pgpro/ent-16/data/

Для добавления существующего кластера можно использовать опцию --convert-standby, если вы уже настраивали репликацию с основного узла.

Таким же образом можно добавить несколько дополнительных ведомых узлов.

Для добавления узла-рефери, который не может стать лидером, но может участвовать в голосовании и таким образом предотвратить потенциальное разделение кластера, необходимо указать параметр –mode

sudo -u postgres /opt/pgpro/ent-16/bin/bihactl add --biha-node-id=3 --host=192.168.50.03 --port=5432 --biha-port=5433 --use-leader "host=192.168.50.01 port=5432 biha-port=5433" --pgdata=/var/lib/pgpro/ent-16/data/ --mode="referee_with_wal"

Параметр --mode может быть равен:

  • referee – узел только участвует в выборах лидера и не содержит данных
  • referee_with_wal – узел участвует в выборах лидера так же, как в режиме referee, и получает все файлы WAL от узла-лидера
Для основных узлов параметр --mode можно не указывать, в этом случае он имеет значение по умолчанию regular (узел может стать как ведущим, так и ведомым)

Администрирование

Администрирование и просмотр состояния кластера осуществляется с помощью SQL-функций и представлений расширения, которые следует вызывать из базы данных biha_db:

  • biha.status_v – просмотр состояний узлов

•	biha.status_v – просмотр состояний узлов

  • biha.config – возвращает значения параметров конфигурации кластера
•	biha.config – возвращает значения параметров конфигурации кластера
  • biha.nodes_v – представление, возвращает список узлов кластера
•	biha.nodes_v – представление, возвращает список узлов кластера
  • biha.set_leader – функция ручного переключения на новый мастер
•	biha.set_leader – функция ручного переключения на новый мастер

•	biha.set_leader – функция ручного переключения на новый мастер

  • biha.remove_node – функция удаления узла из кластера (предварительно этот узел нужно остановить)
•	biha.remove_node – функция удаления узла из кластера (предварительно этот узел нужно остановить)


•	biha.remove_node – функция удаления узла из кластера (предварительно этот узел нужно остановить)

Кроме того, расширение BiHA поддерживает дополнительные конфигурационные параметры для управления отказоустойчивым кластером, например:

  • biha.heartbeat_max_lost – максимальное число сообщений о контроле состояния, которые можно не получить до того, как узел будет считаться недоступным;
  • biha.heartbeat_send_period – частота отправки сообщений о контроле состояния в миллисекундах.
Рисунок11.png

Полное описание параметров в документации по ссылкам ниже:

https://postgrespro.ru/docs/enterprise/16/biha#BIHA-CLUSTER-CONFIGURATION-FUNCTIONS

https://postgrespro.ru/docs/enterprise/16/biha#BIHA-VIEWS

https://postgrespro.ru/docs/enterprise/16/biha#BIHA-CONFIGURATION-PARAMETERS

Синхронный режим

BiHA также поддерживает синхронный режим репликации. Для этого нужно при инициализации кластера добавить параметр --sync-standbys=<число синхронных реплик> к команде bihactl init

При инициализации автоматически будут изменены параметры Postgres synchronous_commit и synchronous_standby_names. Репликация в BiHA кворумная, все ведомые узлы перечислены в synchronous_standby_names, при этом мастер ждет ответа, только от количества, указанного в параметре --sync-standbys.

Узел-рефери в режиме referee_with_wal тоже может участвовать в синхронной репликации, при этом, обратите внимание, если для параметра synchronous_commit установлено значение remote_apply, то рефери не сможет подтверждать транзакции. 

Единая точка входа из

В качестве единой точки входа можно использовать: 

  1. Расширенную строку соединения с несколькими хостами.
  2. Возможность HAProxy выполнять в качестве проверки внешний скрипт.

Рассмотрим более подробно каждый из способов подключения. 

Расширенная строка подключения

В Postgres есть возможность использовать расширенную строку подключения с помощью функции управления подключением к базе данных библиотеки libpq. Пример схемы такого подключения приведен на рис.3

Ссылка на описание в документации:

https://postgrespro.ru/docs/postgresql/16/libpq-connect#LIBPQ-CONNSTRING

поддерживает такую возможность в формате ключ/значение, но с некоторыми нюансами, о которых будет сказано ниже.

Пример из документации по libpq:

host=localhost port=5432 dbname=mydb connect_timeout=10

В строке подключения можно задать несколько узлов (host), к которым клиент будет пытаться подключиться в заданном порядке. Первый доступный узел становится выбранным для подключения, остальные узлы уже не рассматриваются. Параметры host и port в формате ключ/значение принимают списки значений, разделённых запятыми. В каждом определяемом параметре должно содержаться одинаковое число элементов, чтобы, например, первый элемент host соответствовал первому узлу, второй - второму узлу и так далее. Исключение составляет port - если этот параметр содержит только один элемент, то он применяется ко всем узлам.

Если такой формат применить для строки подключения к узлам pgnode-01, pgnode-02, pgnode-03 со стандартным портом 5432  с необходимостью не подключаться к репликам, то строка, которая указывается в поле «Сервер баз данных», должна выглядеть так:

host=pgnode-01, pgnode-02, pgnode-03 port=5432 dbname=db1c target_session_attrs=read-write


Параметр target_session_attrs=read-write как раз позволяет выполнять подключение только к серверам, которые находятся в режиме чтения-записи, игнорируя реплики. Описание параметра из документации: 

https://postgrespro.ru/docs/postgresql/16/libpq-connect#LIBPQ-CONNECT-TARGET-SESSION-ATTRS


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

pgnode-01, pgnode-02, pgnode-03 port=5432 target_session_attrs=read-write

То есть из начала строки убран host= и параметр указания базы данных dbname=db1c, т.к. имя базы данных, как и при стандартном подключении, указывается в поле «База данных» (рис.4). 

Рис.4 Расширенная строка подключения при создании базы в 1С

Рис.4 Расширенная строка подключения при создании базы в

Единая точка входа через HAProxy 

По аналогии с Patroni в качестве единой точки входа можно использовать HAProxy (рис. 5), но т.к. у BiHA на текущий момент нет REST API, который бы мог возвращать текущее состояние узлов кластера, то используется возможность HAProxy выполнять в качестве проверки внешний скрипт. Пример настройки в haproxy.cfg:

Скрин.png

Скрипт pgcheck.sh должен возвращать «0» для разрешенных подключений и «1» для реплик, а также недоступных серверов.

Рис. 5 Отказоустойчивый кластер из трех узлов (использование BiHA + HAProxy)

Рис. 5 Отказоустойчивый кластер из трех узлов (использование BiHA + HAProxy) 

При проверке узлов HAProxy опрашивает их состояния с периодичностью, заданной параметром timeout check и, если скрипт возвращает «0», то сервер считается доступным для подключения. Для реализации проверки можно использовать функцию pg_is_in_recovery(), которая возвращает «f», если кластер не является репликой.

В качестве краткого вывода можно сказать, что с точки зрения функциональных возможностей Patroni и Postgres Pro BiHA похожи и успешно справляются со своими задачами. Главным отличием здесь является то, что Patroni является внешним сервисом по отношению к Postgres и поэтому может не всегда правильно реагировать на временную недоступность сервера для клиентских запросов, например, когда сервер перегружен, т. е. возможны ложные срабатывания. 

BiHA является частью СУБД PostgresPro Enterprise, что отличает ее от сторонних решений, поэтому вероятность ложных срабатываний ниже, т. к. она может точнее отслеживать текущее состояние каждого узла кластера. Кроме того, наличие встроенной интеграции с PostgresPro Enterprise упрощает настройку и управление отказоустойчивым кластером.

Назад