Построение отказоустойчивого кластера PostgreSQL. Настройка внешней синхронизации на PostgreSQL для механизма копий баз данных.: различия между версиями
imported>Vix Нет описания правки |
Vix (обсуждение | вклад) |
||
(не показано 26 промежуточных версий 2 участников) | |||
Строка 1: | Строка 1: | ||
Введение | =='''Введение'''== | ||
Целью данной статьи является описание способов построения отказоустойчивого кластера PostgreSQL, для систем на базе 1С:Предприятие, подобного решению "MS SQL Server Always On Availability Groups" от Microsoft. Построение такого отказоустойчивого кластера затруднено тем, что в PostgreSQL не предоставляет механизмов автоматического переключения на резервный сервер. Ниже будет описано, каким образом можно реализовать автоматическое переключение на резервный сервер в случае сбоя ведущего сервера PostgreSQL. | Целью данной статьи является описание способов построения отказоустойчивого кластера PostgreSQL, для систем на базе 1С:Предприятие, подобного решению "MS SQL Server Always On Availability Groups" от Microsoft. Построение такого отказоустойчивого кластера затруднено тем, что в PostgreSQL не предоставляет механизмов автоматического переключения на резервный сервер. Ниже будет описано, каким образом можно реализовать автоматическое переключение на резервный сервер в случае сбоя ведущего сервера PostgreSQL. | ||
Используемые программные продукты | =='''Используемые программные продукты'''== | ||
Patroni - шаблон для построения отказоустойчивых кластеров на базе PostgreSQL. Обеспечивает автоматическое переключение на резервный сервер при сбое ведущего сервера. Patroni управляет экземпляром базы данных PostgreSQL и использует внешние системы (ZooKeeper, etcd, Consul или Kubernetes) для хранения общей для всех узлов кластера информации, такой как список узлов кластера и положение ведущего сервера. | Patroni - шаблон для построения отказоустойчивых кластеров на базе PostgreSQL. Обеспечивает автоматическое переключение на резервный сервер при сбое ведущего сервера. Patroni управляет экземпляром базы данных PostgreSQL и использует внешние системы (ZooKeeper, etcd, Consul или Kubernetes) для хранения общей для всех узлов кластера информации, такой как список узлов кластера и положение ведущего сервера. | ||
* Напомню, что такое Patroni, для чего предназначен и что умеет. | |||
Patroni — это шаблон для построения HA из коробки. Так написано в документации и с моей точки зрения — это очень правильное уточнение. То есть Patroni — это не серебряная пуля, которую поставил и она решит все проблемы. Нужно приложить усилия, чтобы он начал работать и приносить пользу. | |||
Patroni — агентская служба. Устанавливается на каждом сервере с базой данных и является своего рода init-системой для PostgreSQL: запускает, останавливает, перезапускает, меняет конфигурацию и топологию кластера. | |||
Patroni хранит «состояние кластера» в DCS. Чтобы хранить состояние кластера, его текущее представление, нужно хранилище. Patroni хранит состояние во внешней системе — распределенном хранилище конфигураций. Это может быть один из вариантов: Etcd, Consul, ZooKeeper либо Etcd Kubernetes. | |||
Автофейловер в Patroni включен по умолчанию. Вы получаете автофейловер из коробки, сразу же после установки Patroni. | |||
etcd - согласованное распределенное хранилище пар ключ-значение, обеспечивающее надежный способ хранения данных, к которым могут обращаться распределенная система или кластер машин. | etcd - согласованное распределенное хранилище пар ключ-значение, обеспечивающее надежный способ хранения данных, к которым могут обращаться распределенная система или кластер машин. | ||
Строка 10: | Строка 20: | ||
HAProxy - прокси сервер TCP и HTTP трафика. Позволяет создать единую точку подключения к PostgreSQL, не зависящую от распределения ролей в кластерах PostgreSQL. | HAProxy - прокси сервер TCP и HTTP трафика. Позволяет создать единую точку подключения к PostgreSQL, не зависящую от распределения ролей в кластерах PostgreSQL. | ||
Развёртывание стенда | =='''Развёртывание стенда'''== | ||
Описание стенда | Описание стенда | ||
Для демонстрации работы кластера будет использоваться четыре машины под управлением CentOS 7: | Для демонстрации работы кластера будет использоваться четыре машины под управлением CentOS 7: | ||
Строка 47: | Строка 57: | ||
СУБД PostgreSQL для Linux x86 (64-bit) одним архивом (RPM) (https://releases.1c.ru/project/AddCompPostgre), использовалась версия 11.5_12.1C | СУБД PostgreSQL для Linux x86 (64-bit) одним архивом (RPM) (https://releases.1c.ru/project/AddCompPostgre), использовалась версия 11.5_12.1C | ||
Установка дистрибутивов | =='''Установка дистрибутивов'''== | ||
Core.example | Core.example | ||
На этот сервер следует установить и запустить сервер 1С:Предприятие. Подробную инструкцию по установке можно найти | На этот сервер следует установить и запустить сервер 1С:Предприятие.<br> | ||
Подробную инструкцию по установке можно найти [https://its.1c.ru/db/metod8dev#content:5953:hdoc тут] | |||
DBOne.example, DBTwo.example, DBThree.example | DBOne.example, DBTwo.example, DBThree.example | ||
Строка 70: | Строка 81: | ||
Ниже описано создание кластера etcd и добавление нового узла в кластер. Затем будет построен кластер Patroni, использующий etcd для хранения своей конфигурации. После будет настроен HAProxy, который будет отслеживать смену ведущего сервера и скрывать это событие от 1С:Предприятие. | Ниже описано создание кластера etcd и добавление нового узла в кластер. Затем будет построен кластер Patroni, использующий etcd для хранения своей конфигурации. После будет настроен HAProxy, который будет отслеживать смену ведущего сервера и скрывать это событие от 1С:Предприятие. | ||
=='''Установка Etcd'''== | |||
Кластер etcd будет развёрнут на всех машинах стенда. | Кластер etcd будет развёрнут на всех машинах стенда. | ||
Строка 94: | Строка 105: | ||
ETCD_HEARTBEAT_INTERVAL="1000" | ETCD_HEARTBEAT_INTERVAL="1000" | ||
ETCD_ELECTION_TIMEOUT="5000" | ETCD_ELECTION_TIMEOUT="5000" | ||
ETCDCTL_API=2 | |||
#[Clustering] | #[Clustering] | ||
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://core.example:2380" ETCD_ADVERTISE_CLIENT_URLS="http://core.example:2379" | ETCD_INITIAL_ADVERTISE_PEER_URLS="http://core.example:2380" | ||
ETCD_ADVERTISE_CLIENT_URLS="http://core.example:2379" | |||
ETCD_INITIAL_CLUSTER="core=http://core.example:2380" | ETCD_INITIAL_CLUSTER="core=http://core.example:2380" | ||
ETCD_INITIAL_CLUSTER_TOKEN="etcd-example" | ETCD_INITIAL_CLUSTER_TOKEN="etcd-example" | ||
Строка 148: | Строка 161: | ||
Копировать в буфер обмена | Копировать в буфер обмена | ||
> sudo systemctl enable etcd.service | > sudo systemctl enable etcd.service | ||
Created symlink from /etc/systemd/system/multi-user.target.wants/etcd.service to /usr/lib/systemd/system/etcd.service. | Created symlink from /etc/systemd/system/multi-user.target.wants/etcd.service to /usr/lib/systemd/system/etcd.service. | ||
При запуске etcd пытается найти все узлы, перечисленные в параметре "ETCD_INITIAL_CLUSTER". Если какой-то из узлов не будет найден - запуск завершится сбоем. Если что-то пошло не так, удалите содержимое каталога из параметра | При запуске etcd пытается найти все узлы, перечисленные в параметре "ETCD_INITIAL_CLUSTER". Если какой-то из узлов не будет найден - запуск завершится сбоем. Если что-то пошло не так, удалите содержимое каталога из параметра:<br> | ||
'''ETCD_DATA_DIR''' | |||
Добавление нового узла etcd | * Добавление нового узла '''etcd''' | ||
Добавление нового узла в кластер etcd происходит в два этапа. На первом этапе кластер предупреждается о появлении нового узла. На втором запускается сам новый узел. | Добавление нового узла в кластер etcd происходит в два этапа. На первом этапе кластер предупреждается о появлении нового узла.<br> | ||
Следующие действия необходимо последовательно выполнить на всех оставшихся серверах стенда. Для примера будет использоваться dbtwo.example | На втором запускается сам новый узел.<br> | ||
Следующие действия необходимо последовательно выполнить на всех оставшихся серверах стенда.<br> | |||
Для примера будет использоваться dbtwo.example | |||
На core.example выполняем оповещение кластера о появлении нового узла | На core.example выполняем оповещение кластера о появлении нового узла | ||
Копировать в буфер обмена | Копировать в буфер обмена | ||
> etcdctl member add dbtwo http://dbtwo.example:2380 | > etcdctl member add dbtwo http://dbtwo.example:2380 | ||
Added member named dbtwo with ID 871ff309aeb9cd1 to cluster ETCD_NAME="dbtwo" ETCD_INITIAL_CLUSTER="dbtwo=http://dbtwo.example:2380,core=http://core.example:2380" ETCD_INITIAL_CLUSTER_STATE="existing" | Added member named dbtwo with ID 871ff309aeb9cd1 to cluster | ||
ETCD_NAME="dbtwo" | |||
ETCD_INITIAL_CLUSTER="dbtwo=http://dbtwo.example:2380,core=http://core.example:2380" | |||
ETCD_INITIAL_CLUSTER_STATE="existing" | |||
Устанавливаем etcd на новый узел и откладываем настройки по умолчанию | Устанавливаем etcd на новый узел и откладываем настройки по умолчанию | ||
Копировать в буфер обмена | Копировать в буфер обмена | ||
Строка 198: | Строка 216: | ||
Копировать в буфер обмена | Копировать в буфер обмена | ||
> sudo systemctl enable etcd.service | > sudo systemctl enable etcd.service | ||
Created symlink from /etc/systemd/system/multi-user.target.wants/etcd.service to /usr/lib/systemd/system/etcd.service. | Created symlink from /etc/systemd/system/multi-user.target.wants/etcd.service to /usr/lib/systemd/system/etcd.service. | ||
Завершение установки etcd | Завершение установки etcd | ||
После установки и успешного запуска etcd на всех серверах, следует привести содержание файла /etc/etcd/etcd.conf в окончательное состояние. Для этого необходимо изменить следующие параметры в этом файле на всех серверах. | После установки и успешного запуска etcd на всех серверах, следует привести содержание файла /etc/etcd/etcd.conf в окончательное состояние. Для этого необходимо изменить следующие параметры в этом файле на всех серверах. | ||
Строка 204: | Строка 222: | ||
параметр "ETCD_INITIAL_CLUSTER" должен быть одинаковым на всех узлах | параметр "ETCD_INITIAL_CLUSTER" должен быть одинаковым на всех узлах | ||
Копировать в буфер обмена | Копировать в буфер обмена | ||
ETCD_INITIAL_CLUSTER="core=http://core.example:2380,dbone=http://dbonew.example:2380,dbtwo=http://dbtwo.example:2380,dbthree=http://dbthree.example:2380" | ETCD_INITIAL_CLUSTER="core=http://core.example:2380,dbone=http://dbonew.example:2380,dbtwo=http://dbtwo.example:2380,dbthree=http://dbthree.example:2380" | ||
параметр "ETCD_INITIAL_CLUSTER_STATE" следует установить в значение "existing" | параметр "ETCD_INITIAL_CLUSTER_STATE" следует установить в значение "existing" | ||
Строка 233: | Строка 252: | ||
User: root | User: root | ||
Roles: root | Roles: root | ||
Установка Patroni | =='''Установка Patroni'''== | ||
Следующие действия выполняются на всех серверах PostgreSQL (dbone.example, dbtwo.example и dbthree.exemple). | Следующие действия выполняются на всех серверах PostgreSQL (dbone.example, dbtwo.example и dbthree.exemple). | ||
Строка 252: | Строка 271: | ||
Копировать в буфер обмена | Копировать в буфер обмена | ||
> sudo python3 -m pip install patroni[etcd] | > sudo python3 -m pip install patroni[etcd] | ||
Проверяем установку | |||
Копировать в буфер обмена | Копировать в буфер обмена | ||
> patroni --version | > patroni --version | ||
Строка 446: | Строка 465: | ||
Копировать в буфер обмена | Копировать в буфер обмена | ||
> patronictl list | > patronictl list | ||
или | |||
> patronictl -c /etc/patroni/patronictl.yml list | |||
+----------+------------+---------------+--------+---------+----+-----------+-----------------+ | +----------+------------+---------------+--------+---------+----+-----------+-----------------+ | ||
| Cluster | Member | Host | Role | State | TL | Lag in MB | Pending restart | | | Cluster | Member | Host | Role | State | TL | Lag in MB | Pending restart | | ||
Строка 451: | Строка 472: | ||
| postgres | dbone | dbone.example | Leader | running | 1 | 0.0 | | | | postgres | dbone | dbone.example | Leader | running | 1 | 0.0 | | | ||
+----------+------------+---------------+--------+---------+----+-----------+-----------------+ | +----------+------------+---------------+--------+---------+----+-----------+-----------------+ | ||
Добавление нового узла Patroni | * Добавление нового узла Patroni | ||
Для добавления нового узла в кластер Patroni, выполняются действия из раздела "Первый узел Patroni". Различия будут заключаться только в файле /etc/patroni/patroni.yml - все изменения заключаются в замене "dbone" на имя текущего сервера. Поэтому для dbtwo.example содержимое будет следующим: | Для добавления нового узла в кластер Patroni, выполняются действия из раздела "Первый узел Patroni". Различия будут заключаться только в файле /etc/patroni/patroni.yml - все изменения заключаются в замене "dbone" на имя текущего сервера. Поэтому для dbtwo.example содержимое будет следующим: | ||
Строка 541: | Строка 562: | ||
| postgres | dbthree | 10.0.0.23 | | running | 1 | 0.0 | | | | postgres | dbthree | 10.0.0.23 | | running | 1 | 0.0 | | | ||
+----------+------------+---------------+--------+---------+----+-----------+-----------------+ | +----------+------------+---------------+--------+---------+----+-----------+-----------------+ | ||
Установка HAProxy | =='''Установка HAProxy'''== | ||
В настройках информационной базы, в кластере 1С:Предприятие, необходимо указывать имя сервера СУБД. В нашем случае им может быть один из серверов PostgreSQL. Так как указать все имена сразу мы не можем, а роли серверов (ведущий сервер и резервный сервер) могут поменяться в любой момент, следует создать точку подключения к PostgreSQL. В качестве точки подключения будет выступать HAProxy установленный на core.example. В задачe HAProxy будет входить слежение за ролями серверов PostgreSQL и, в случае их изменения, оперативное перенаправление запросов от 1С:Предприятие к СУБД на новый ведущий сервер. | В настройках информационной базы, в кластере 1С:Предприятие, необходимо указывать имя сервера СУБД. В нашем случае им может быть один из серверов PostgreSQL. Так как указать все имена сразу мы не можем, а роли серверов (ведущий сервер и резервный сервер) могут поменяться в любой момент, следует создать точку подключения к PostgreSQL. В качестве точки подключения будет выступать HAProxy установленный на core.example. В задачe HAProxy будет входить слежение за ролями серверов PostgreSQL и, в случае их изменения, оперативное перенаправление запросов от 1С:Предприятие к СУБД на новый ведущий сервер. | ||
Строка 643: | Строка 664: | ||
Проведём несколько проверок отказоустойчивости кластера. | Проведём несколько проверок отказоустойчивости кластера. | ||
Подготовка | =='''Подготовка'''== | ||
Создаём информационную базу в кластере 1С:Предприятие. Параметры создания информационной базы: | Создаём информационную базу в кластере 1С:Предприятие. Параметры создания информационной базы: | ||
Строка 667: | Строка 688: | ||
в колонке "Lag in MB" должно быть 0.0 | в колонке "Lag in MB" должно быть 0.0 | ||
Тесты | =='''Тесты'''== | ||
Для выполнения тестов, откроем информационную базу "Test" в режиме 1С:Предприятие. | Для выполнения тестов, откроем информационную базу "Test" в режиме 1С:Предприятие. | ||
Строка 714: | Строка 735: | ||
Ниже приведена последовательность действий для проверки восстановления резервной копии на демонстрационном стенде. Поэтому, в реальной ситуации, раздел "Удаление данных" должен быть пересмотрен с учётом реальных обстоятельств сбоя. Раздел "Восстановление" предполагает, что описанное решение по созданию отказоустойчивого кластера Patroni полностью выполнено и его лишь надо наполнить данными. | Ниже приведена последовательность действий для проверки восстановления резервной копии на демонстрационном стенде. Поэтому, в реальной ситуации, раздел "Удаление данных" должен быть пересмотрен с учётом реальных обстоятельств сбоя. Раздел "Восстановление" предполагает, что описанное решение по созданию отказоустойчивого кластера Patroni полностью выполнено и его лишь надо наполнить данными. | ||
Удаление данных | =='''Удаление данных'''== | ||
Проверяем текущие роли узлов кластера Patroni | Проверяем текущие роли узлов кластера Patroni | ||
Копировать в буфер обмена | Копировать в буфер обмена | ||
Строка 768: | Строка 789: | ||
Для снятия этого ограничения требуется развёртывание дополнительного кластера PostgreSQL, доступного для записи данных. Ниже будет описан пример развёртывания такого сервера. | Для снятия этого ограничения требуется развёртывание дополнительного кластера PostgreSQL, доступного для записи данных. Ниже будет описан пример развёртывания такого сервера. | ||
Создание дополнительного кластера PostgreSQL | =='''Создание дополнительного кластера PostgreSQL'''== | ||
Для создания дополнительного кластера PostgreSQL можно добавить новый сервер и установить на него PostgreSQL. В этом случае порядок действий не отличается от обычной установки PostgreSQL. | Для создания дополнительного кластера PostgreSQL можно добавить новый сервер и установить на него PostgreSQL. В этом случае порядок действий не отличается от обычной установки PostgreSQL. | ||
В случае, если добавление нового сервера нежелательно, дополнительный кластер PostgreSQL можно разместить на одном из существующих серверов PostgreSQL. Ниже показан пример развёртывания дополнительного кластера на уже существующем сервере. | В случае, если добавление нового сервера нежелательно, дополнительный кластер PostgreSQL можно разместить на одном из существующих серверов PostgreSQL. Ниже показан пример развёртывания дополнительного кластера на уже существующем сервере. | ||
Строка 774: | Строка 795: | ||
Данные кластера будут расположены в каталоге /var/lib/pgsql/11/proxy | Данные кластера будут расположены в каталоге /var/lib/pgsql/11/proxy | ||
Инициализируем кластер | * '''Инициализируем кластер''' | ||
Копировать в буфер обмена | Копировать в буфер обмена | ||
> export LANG="ru_RU.UTF-8" | > export LANG="ru_RU.UTF-8" | ||
Строка 900: | Строка 921: | ||
В результате выполнения указанных настроек внешняя синхронизация для механизма копий баз данных при использовании СУБД MS SQL Server, а также выполнение запросов на копии, должны работать корректно. | В результате выполнения указанных настроек внешняя синхронизация для механизма копий баз данных при использовании СУБД MS SQL Server, а также выполнение запросов на копии, должны работать корректно. | ||
Реструктуризация информационной базы | =='''Реструктуризация информационной базы'''== | ||
В случае изменения структуры метаданных информационной базы в структуру базы данных вносятся соответствующие изменения. Эти изменения необходимо перенести в промежуточную базу данных. Для этого следует удалить импортированные таблицы и импортировать схему заново. | В случае изменения структуры метаданных информационной базы в структуру базы данных вносятся соответствующие изменения. Эти изменения необходимо перенести в промежуточную базу данных. Для этого следует удалить импортированные таблицы и импортировать схему заново. | ||
Следующие действия выполнятся на dbthree.example. | Следующие действия выполнятся на dbthree.example. | ||
Строка 913: | Строка 934: | ||
Копировать в буфер обмена | Копировать в буфер обмена | ||
IMPORT FOREIGN SCHEMA public FROM SERVER standby_server INTO public; | IMPORT FOREIGN SCHEMA public FROM SERVER standby_server INTO public; | ||
'''ИСТОЧНИК:''' | |||
<hr> | |||
* [https://its.1c.ru/db/metod8dev/content/5971/hdoc Настройка кластера PostgreSQL и внешней синхронизации для механизма копий баз данных.] | |||
=='''Полезное:'''== | |||
* [[ETCD - Управление]] | |||
* [https://habr.com/ru/post/322036/ Кластер PostgreSQL высокой надежности на базе Patroni, Haproxy, Keepalived] | |||
* [https://habr.com/ru/post/482314/ Построение кластера PostgreSQL высокой доступности с использованием Patroni, etcd, HAProxy] | |||
* [https://dreamcatcher.ru/2021/02/15/postgresql-%D0%B8-%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80-patroni/ PostgreSQL и кластер patroni] | |||
* [https://www.pvsm.ru/postgresql/349224 Истории аварий с Patroni, или Как уронить PostgreSQL-кластер] | |||
* [https://dotsandbrackets.com/quick-intro-etcd-ru/ Краткое введение в etcd] | |||
* [https://itnan.ru/post.php?c=1&p=482314 Построение кластера PostgreSQL высокой доступности с использованием Patroni, etcd, HAProxy] | |||
* [https://repo.quantom.info/qhb/std-1/doc/1.5.1/ru/Appendix/add_modules/patroni.html Patroni (Управление высокодоступными кластерами)] | |||
* [https://dreamcatcher.ru/2021/02/15/postgresql-%D0%B8-%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80-patroni/ Кластер PostgreSQL с использованием patroni] | |||
* [https://postgrespro.ru/docs/postgresql/15/creating-cluster PostgresPro - Создание кластера баз данных] | |||
* [https://habr.com/ru/sandbox/150526/ Репликация в PostgreSQL без проблем] | |||
* [https://efsol.ru/manuals/postgresql-patroni-install.html EFSOL - Настройка PostgreSQL Patroni Cluster] | |||
* [https://elma365.com/ru/help/platform/configure-postgresql.html Кластер PostgreSQL] | |||
-- | |||
* [https://infostart.ru/1c/articles/1498463/ Опыт использования PostgreSQL cluster под управлением Patroni для 200 баз] | |||
* [https://habr.com/ru/articles/504044/ Управление высокодоступными PostgreSQL кластерами с помощью Patroni. А.Клюкин, А.Кукушкин] | |||
* [https://resql.ru/forum/topic.php?fid=53&tid=2186886 Увеличить wal_keep_size Patroni] | |||
* [https://stackoverflow.com/questions/75039034/pg-wal-is-very-big-size PG_WAL is very big size] | |||
* [https://translated.turbopages.org/proxy_u/en-ru.ru.f48bb0eb-65b0fa86-7e9cc091-74722d776562/https/github.com/zalando/patroni/issues/2072 Моя позиция wal превышает максимальную задержку репликации] | |||
* [https://russianblogs.com/article/7923804638/ Схема репликации PostgreSQL] | |||
* [https://github.com/zalando/patroni/issues/1571 How to properly restore cluster using WAL-G (WAL-E) to a specific time (PITR) on Postgres 12? #1571] | |||
* [https://www.percona.com/blog/rebuild-patroni-replica-using-pgbackrest/ Rebuild Patroni Replica Using pgBackRest] | |||
* [https://ittutorial.org/postgresql-high-availability-installations-patroni/ PostgreSQL High Availability installations Patroni] | |||
* [https://habr.com/ru/companies/avito/articles/781892/ Архивная репликация в PostgreSQL: пошаговая инструкция] | |||
* [https://stackoverflow.com/questions/65294993/patroni-synchronous-mode-vs-maximum-lag-on-failover Patroni: synchronous_mode vs maximum_lag_on_failover] | |||
* [https://habr.com/ru/companies/otus/articles/753294/ Высокодоступные кластеры PostgreSQL с Patroni: Ваша очередь протестировать сценарии отказов] |
Текущая версия от 20:29, 7 июня 2024
Введение
Целью данной статьи является описание способов построения отказоустойчивого кластера PostgreSQL, для систем на базе 1С:Предприятие, подобного решению "MS SQL Server Always On Availability Groups" от Microsoft. Построение такого отказоустойчивого кластера затруднено тем, что в PostgreSQL не предоставляет механизмов автоматического переключения на резервный сервер. Ниже будет описано, каким образом можно реализовать автоматическое переключение на резервный сервер в случае сбоя ведущего сервера PostgreSQL.
Используемые программные продукты
Patroni - шаблон для построения отказоустойчивых кластеров на базе PostgreSQL. Обеспечивает автоматическое переключение на резервный сервер при сбое ведущего сервера. Patroni управляет экземпляром базы данных PostgreSQL и использует внешние системы (ZooKeeper, etcd, Consul или Kubernetes) для хранения общей для всех узлов кластера информации, такой как список узлов кластера и положение ведущего сервера.
- Напомню, что такое Patroni, для чего предназначен и что умеет.
Patroni — это шаблон для построения HA из коробки. Так написано в документации и с моей точки зрения — это очень правильное уточнение. То есть Patroni — это не серебряная пуля, которую поставил и она решит все проблемы. Нужно приложить усилия, чтобы он начал работать и приносить пользу.
Patroni — агентская служба. Устанавливается на каждом сервере с базой данных и является своего рода init-системой для PostgreSQL: запускает, останавливает, перезапускает, меняет конфигурацию и топологию кластера.
Patroni хранит «состояние кластера» в DCS. Чтобы хранить состояние кластера, его текущее представление, нужно хранилище. Patroni хранит состояние во внешней системе — распределенном хранилище конфигураций. Это может быть один из вариантов: Etcd, Consul, ZooKeeper либо Etcd Kubernetes.
Автофейловер в Patroni включен по умолчанию. Вы получаете автофейловер из коробки, сразу же после установки Patroni.
etcd - согласованное распределенное хранилище пар ключ-значение, обеспечивающее надежный способ хранения данных, к которым могут обращаться распределенная система или кластер машин.
HAProxy - прокси сервер TCP и HTTP трафика. Позволяет создать единую точку подключения к PostgreSQL, не зависящую от распределения ролей в кластерах PostgreSQL.
Развёртывание стенда
Описание стенда Для демонстрации работы кластера будет использоваться четыре машины под управлением CentOS 7:
Имя IP-адрес Описание Core.example 10.0.0.11 симуляция инфраструктуры DBOne.example 10.0.0.21 первый сервер PostgreSQL DBTwo.example 10.0.0.22 второй сервер PostgreSQL DBThree.example 10.0.0.23 третий сервер PostgreSQL
Предполагается, что:
Машины уже созданы и на них установлена операционная система Операционная система обновлена Машины находятся в одной сети Машины могут обнаруживать друг друга по DNS именам (core.example, dbone.example, dbtwo.example, dbthree.example). Дополнительные настройки Приведём имя машины к её имени в DNS и проверим результат. Для этого выполняем следующие команды:
на core.example
Копировать в буфер обмена
> sudo hostnamectl set-hostname core.example --static > hostname core.example на dbone.example
Копировать в буфер обмена
> sudo hostnamectl set-hostname dbone.example --static > hostname dbone.example на dbtwo.example
Копировать в буфер обмена
> sudo hostnamectl set-hostname dbtwo.example --static > hostname dbtwo.example на dbthree.example
Копировать в буфер обмена
> sudo hostnamectl set-hostname dbthree.example --static > hostname dbthree.example
Подготовка дистрибутивов Следует скачать следующие дистрибутивы:
Сервер 1С:Предприятия для RPM-based Linux-систем (https://releases.1c.ru/project/Platform83), использовалась версия 8.3.16.1224
СУБД PostgreSQL для Linux x86 (64-bit) одним архивом (RPM) (https://releases.1c.ru/project/AddCompPostgre), использовалась версия 11.5_12.1C
Установка дистрибутивов
Core.example
На этот сервер следует установить и запустить сервер 1С:Предприятие.
Подробную инструкцию по установке можно найти тут
DBOne.example, DBTwo.example, DBThree.example
На этом этапе настройки этих машин не отличаются. На обоих необходимо установить PostgreSQL с модификациями фирмы 1С.
Установим PostgreSQL версии 11.5_12.1С. Для этого в каталоге с распакованным дистрибутивом PostgreSQL 11.5_12.1C выполняем:
Копировать в буфер обмена
> sudo yum install -y postgresql11-1c-*.rpm
Кластер инициализировать не нужно. Это будет выполнено при установке Patroni.
Запрещаем автоматический запуск PostgreSQL при старте операционной системы.
Копировать в буфер обмена
> sudo systemctl disable postgresql-11
Removed symlink /etc/systemd/system/multi-user.target.wants/postgresql-11.service. Остановкой и запуском PostgreSQL будет управлять Patroni и автоматический запуск будет только мешать Patroni.
Развёртывание отказоустойчивого кластера PostgreSQL + Patroni + etcd + HAProxy Ниже описано создание кластера etcd и добавление нового узла в кластер. Затем будет построен кластер Patroni, использующий etcd для хранения своей конфигурации. После будет настроен HAProxy, который будет отслеживать смену ведущего сервера и скрывать это событие от 1С:Предприятие.
Установка Etcd
Кластер etcd будет развёрнут на всех машинах стенда.
Создание кластера etcd Создадим первый узел кластера. На core.example выполняем следующие действия:
Устанавливаем etcd из пакета
Копировать в буфер обмена
> sudo yum install -y etcd
Откладываем в сторону настройки по умолчанию
Копировать в буфер обмена
> sudo mv /etc/etcd/etcd.conf /etc/etcd/etcd.conf.def
Используя текстовый редактор создаём новый файл настроек /etc/etcd/etcd.conf и помещаем в него следующие настройки:
Копировать в буфер обмена
#[Member] ETCD_DATA_DIR="/var/lib/etcd" ETCD_LISTEN_PEER_URLS="http://0.0.0.0:2380" ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:2379" ETCD_NAME="core" ETCD_HEARTBEAT_INTERVAL="1000" ETCD_ELECTION_TIMEOUT="5000" ETCDCTL_API=2 #[Clustering] ETCD_INITIAL_ADVERTISE_PEER_URLS="http://core.example:2380" ETCD_ADVERTISE_CLIENT_URLS="http://core.example:2379" ETCD_INITIAL_CLUSTER="core=http://core.example:2380" ETCD_INITIAL_CLUSTER_TOKEN="etcd-example" ETCD_INITIAL_CLUSTER_STATE="new"
Рассмотрим введённые параметры:
ETCD_DATA_DIR - указывает расположение каталога данных кластера ETCD_LISTEN_PEER_URLS - задаёт схему и точку подключения для остальных узлов кластера, по шаблону scheme://IP:port. Схема может быть http, https. Альтернатива, unix:// или unixs:// для юникс сокетов. Если в качестве IP адреса указано 0.0.0.0, то указанный порт будет прослушиваться на всех интерфейсах. ETCD_LISTEN_CLIENT_URLS - задаёт схему и точку подключения для клиентов кластера. В остальном совпадает с ETCD_LISTEN_PEER_URLS. ETCD_NAME - человекочитаемое имя этого узла кластера. Должно быть уникально в кластере. Для первого узла может быть любым. Для последующих должно совпадать с именем, указанным при добавлении узла. ETCD_HEARTBEAT_INTERVAL - время в миллисекудах, между рассылками лидером оповещений о том, что он всё ещё лидер. Рекомендуется задавать с учётом сетевой задержки между узлами кластера. ETCD_ELECTION_TIMEOUT - время в миллисекундах, которое проходит между последним принятым оповещением от лидера кластера, до попытки захватить роль лидера на ведомом узле. Рекомендуется задавать его в несколько раз большим, чем ETCD_HEARTBEAT_INTERVAL. Более подробно о этих параметрах можно прочесть в документации. ETCD_INITIAL_ADVERTISE_PEER_URLS - Список равноправных URL-адресов, по которым его могут найти остальные узлы кластера. Эти адреса используются для передачи данных по кластеру. По крайней мере, один из этих адресов должен быть маршрутизируемым для всех членов кластера. Могут содержать доменные имена. Используется только при первом запуске нового узла кластера. ETCD_ADVERTISE_CLIENT_URLS - Список равноправных URL-адресов, по которым его могут найти остальные узлы кластера. Эти адреса используются для передачи данных по кластеру. По крайней мере, один из этих адресов должен быть маршрутизируемым для всех членов кластера. Могут содержать доменные имена. ETCD_INITIAL_CLUSTER - Список узлов кластера на момент запуска. Используется только при первом запуске нового узла кластера. ETCD_INITIAL_CLUSTER_TOKEN - Токен кластера. Должен совпадать на всех узлах кластера. Используется только при первом запуске нового узла кластера. ETCD_INITIAL_CLUSTER_STATE - может принимать два значения "new" и "existing". Значение "new" используется при первом запуске первого узла в кластере. При значении "existing", узел при старте будет пытаться установить связь с остальными узлами кластера.
Запускаем демон etcd
Копировать в буфер обмена
> sudo systemctl start etcd.service
Проверяем результат
Демон должен быть запущен и находиться в состоянии "active"
Копировать в буфер обмена
> sudo systemctl status etcd.service ? etcd.service - Etcd Server Loaded: loaded (/usr/lib/systemd/system/etcd.service; disabled; vendor preset: disabled) Active: active (running) since Wed 2020-03-04 07:39:43 UTC; 18s ago Main PID: 16423 (etcd) CGroup: /system.slice/etcd.service ??16423 /usr/bin/etcd --name=core --data-dir=/var/lib/etcd --listen-client-urls=http://0.0.0.0:2379 Mar 04 07:39:43 core.example etcd[16423]: 18cd9dc4a590c73e became leader at term 6 Mar 04 07:39:43 core.example etcd[16423]: raft.node: 18cd9dc4a590c73e elected leader 18cd9dc4a590c73e at term 6 Mar 04 07:39:43 core.example etcd[16423]: setting up the initial cluster version to 3.3 Mar 04 07:39:43 core.example etcd[16423]: published {Name:core ClientURLs:[http://core.example:...eb8af0 Mar 04 07:39:43 core.example etcd[16423]: ready to serve client requests Mar 04 07:39:43 core.example etcd[16423]: serving insecure client requests on [::]:2379, this is strongly discouraged! Mar 04 07:39:43 core.example systemd[1]: Started Etcd Server. Если запуск завершился с ошибкой, следует проверить сообщения в системном журнале
Копировать в буфер обмена
> journalctl -xel
Кластер должен состоять из одного узла
Копировать в буфер обмена
> etcdctl cluster-health member 6390c5e1e694effa is healthy: got healthy result from http://core.example:2379 cluster is healthy
Если всё хорошо, то добавляем etcd в автозапуск
Копировать в буфер обмена
> sudo systemctl enable etcd.service Created symlink from /etc/systemd/system/multi-user.target.wants/etcd.service to /usr/lib/systemd/system/etcd.service.
При запуске etcd пытается найти все узлы, перечисленные в параметре "ETCD_INITIAL_CLUSTER". Если какой-то из узлов не будет найден - запуск завершится сбоем. Если что-то пошло не так, удалите содержимое каталога из параметра:
ETCD_DATA_DIR
- Добавление нового узла etcd
Добавление нового узла в кластер etcd происходит в два этапа. На первом этапе кластер предупреждается о появлении нового узла.
На втором запускается сам новый узел.
Следующие действия необходимо последовательно выполнить на всех оставшихся серверах стенда.
Для примера будет использоваться dbtwo.example
На core.example выполняем оповещение кластера о появлении нового узла Копировать в буфер обмена
> etcdctl member add dbtwo http://dbtwo.example:2380 Added member named dbtwo with ID 871ff309aeb9cd1 to cluster ETCD_NAME="dbtwo" ETCD_INITIAL_CLUSTER="dbtwo=http://dbtwo.example:2380,core=http://core.example:2380" ETCD_INITIAL_CLUSTER_STATE="existing"
Устанавливаем etcd на новый узел и откладываем настройки по умолчанию Копировать в буфер обмена
> sudo yum install -y etcd > sudo mv /etc/etcd/etcd.conf /etc/etcd/etcd.conf.def
Создаём файл /etc/etcd/etcd.conf со следующим содержимым: Копировать в буфер обмена
#[Member] ETCD_DATA_DIR="/var/lib/etcd" ETCD_LISTEN_PEER_URLS="http://0.0.0.0:2380" ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:2379" ETCD_NAME="dbtwo" ETCD_HEARTBEAT_INTERVAL="1000" ETCD_ELECTION_TIMEOUT="5000" #[Clustering] ETCD_INITIAL_ADVERTISE_PEER_URLS="http://dbtwo.example:2380" ETCD_ADVERTISE_CLIENT_URLS="http://dbtwo.example:2379" ETCD_INITIAL_CLUSTER="core=http://core.example:2380,dbtwo=http://dbtwo.example:2380" ETCD_INITIAL_CLUSTER_TOKEN="etcd-example" ETCD_INITIAL_CLUSTER_STATE="existing"
Не забывайте менять значение параметра "ETCD_NAME". Параметр "ETCD_INITIAL_CLUSTER" важен для первого запуска, если в нём будут указаны несуществующие сервера или допущены другие ошибки - запуск завершится сбоем. Запускаем демон etcd на dbtwo.example Копировать в буфер обмена
> sudo systemctl start etcd.service
Проверяем результат демон должен быть запущен и находится в состоянии "active" Копировать в буфер обмена
> sudo systemctl status etcd.service
в списке узлов кластера новый узел должен быть в состоянии "healthy" Копировать в буфер обмена
> etcdctl cluster-health member 871ff309aeb9cd1 is healthy: got healthy result from http://core.example:2379 member 99789c1c8817dff1 is healthy: got healthy result from http://dbtwo.example:2379 cluster is healthy > etcdctl member list 871ff309aeb9cd1: name=dbtwo peerURLs=http://dbtwo.example:2380 clientURLs=http:dbtwo.example:2379 isLeader=true 99789c1c8817dff1: name=core peerURLs=http://core.example:2380 clientURLs=http://core.example:2379 isLeader=false
Если всё хорошо, тогда добавляем etcd в автозапуск
Копировать в буфер обмена > sudo systemctl enable etcd.service Created symlink from /etc/systemd/system/multi-user.target.wants/etcd.service to /usr/lib/systemd/system/etcd.service.
Завершение установки etcd После установки и успешного запуска etcd на всех серверах, следует привести содержание файла /etc/etcd/etcd.conf в окончательное состояние. Для этого необходимо изменить следующие параметры в этом файле на всех серверах.
параметр "ETCD_INITIAL_CLUSTER" должен быть одинаковым на всех узлах Копировать в буфер обмена
ETCD_INITIAL_CLUSTER="core=http://core.example:2380,dbone=http://dbonew.example:2380,dbtwo=http://dbtwo.example:2380,dbthree=http://dbthree.example:2380"
параметр "ETCD_INITIAL_CLUSTER_STATE" следует установить в значение "existing" Копировать в буфер обмена
ETCD_INITIAL_CLUSTER_STATE="existing"
Создание пользователя в etcd Добавим авторизацию по логину и паролю при обращениях на клиентский интерфейс etcd.
Создаём пользователя "root" Копировать в буфер обмена
> etcdctl user add root New password: User root created
Это первый пользователь и поэтому ему автоматически назначается роль "root". Копировать в буфер обмена
> etcdctl user get root User: root Roles: root
Включаем проверку логина и пароля Копировать в буфер обмена
> etcdctl auth enable
Authentication Enabled Проверяем, что изменения вступили в силу Копировать в буфер обмена
> etcdctl user get root Insufficient credentials > etcdctl --username root user get root Password: User: root Roles: root
Установка Patroni
Следующие действия выполняются на всех серверах PostgreSQL (dbone.example, dbtwo.example и dbthree.exemple).
Устанавливаем Python Копировать в буфер обмена
> sudo yum install -y python3 > sudo python3 -m pip install --upgrade pip
проверяем результат: Копировать в буфер обмена
> python3 --version Python 3.6.8
Устанавливаем зависимости Копировать в буфер обмена
> sudo yum install -y gcc python3-devel > sudo python3 -m pip install psycopg2-binary
Устанавливаем Patroni Копировать в буфер обмена
> sudo python3 -m pip install patroni[etcd]
Проверяем установку Копировать в буфер обмена
> patroni --version patroni 1.6.4
Первый узел Patroni Следующие действия выполняются на dbone.example
Создаём каталог настроек Patroni
Копировать в буфер обмена
> sudo mkdir /etc/patroni > sudo chown postgres:postgres /etc/patroni > sudo chmod 700 /etc/patroni
Создаём файл настроек /etc/patroni/patroni.yml со следующим содержимым
Копировать в буфер обмена
name: dbone namespace: /db/ scope: postgres restapi: listen: 0.0.0.0:8008 connect_address: dbone.example:8008 authentication: username: patroni password: patroni etcd: hosts: localhost:2379 username: root password: rootpassword bootstrap: dcs: ttl: 30 loop_wait: 10 retry_timeout: 10 maximum_lag_on_failover: 1048576 master_start_timeout: 300 postgresql: use_pg_rewind: true use_slots: true parameters: wal_level: replica hot_standby: "on" wal_keep_segments: 8 max_wal_senders: 5 max_replication_slots: 5 checkpoint_timeout: 30 initdb: - auth-host: md5 - auth-local: peer - encoding: UTF8 - data-checksums - locale: ru_RU.UTF-8 pg_hba: - host replication replicator samenet md5 - host replication all 127.0.0.1/32 md5 - host replication all ::1/128 md5 users: usr1cv8: password: usr1cv8 options: - superuser postgresql: listen: 0.0.0.0:5432 connect_address: dbone.example:5432 config_dir: /var/lib/pgsql/11/data bin_dir: /usr/pgsql-11/bin/ data_dir: /var/lib/pgsql/11/data pgpass: /tmp/pgpass authentication: superuser: username: postgres password: V6OxPStvMPh0V7Q982DG replication: username: replicator password: PdR2lIAdwNdcSP4erAXc rewind: username: rewind_user password: WfcuDtEzEbLCHBaYQXX3 parameters: unix_socket_directories: '/var/run/postgresql/' tags: nofailover: false noloadbalance: false clonefrom: false nosync: false
В приведённом примере настроек, есть ряд параметров, влияющих на выполнение переключения на резервный сервер.
maximum_lag_on_failover - максимальное количество байт, на которые может отставать резервный сервер от ведущего, участвующий в выборах нового лидера. master_start_timeout - задержка в секундах, между обнаружением аварийной ситуации и началом отработки переключения на резервный сервер. По умолчанию 300 секунд. Если задано 0, то переключение начнётся немедленно. При использовании асинхронной репликации (как в приведённом примере) это может привести к потере последних транзакций. Максимальное время переключения на реплику равно "loop_wait" + "master_start_timeout" + "loop_wait". Если "master_start_timeout" установленно в 0, то это время становится равно значению параметра "loop_wait". Подробнее о возможных вариантах репликации можно прочитать в документации Создаём сервис для запуска демона Patroni
Создаём unit файл /etc/systemd/system/patroni.service Копировать в буфер обмена
[Unit] Description=Runners to orchestrate a high-availability PostgreSQL After=syslog.target network.target [Service] Type=simple User=postgres Group=postgres ExecStart=/usr/local/bin/patroni /etc/patroni/patroni.yml ExecReload=/bin/kill -s HUP $MAINPID KillMode=process TimeoutSec=30 Restart=no [Install] WantedBy=multi-user.target
В приведённых настройках запуска особенно важны два параметра
TimeoutSec - время в секундах, которое система будет ожидать при запуске и остановке сервиса, перед тем как произвести попытку его внештатного завершения.
Restart - может принимать значения: no, on-success, on-failure, on-abnormal, on-watchdog, on-abort, или always. Определяет политику перезапуска сервиса в случае, если он завершает работу не по команде от systemd. Обновляем системные настройки Копировать в буфер обмена
> sudo systemctl daemon-reload
Запускаем демон Patroni
Копировать в буфер обмена
> sudo systemctl start patroni.service
Проверяем успешность запуска
Статус службы должен быть "active" Копировать в буфер обмена
> sudo systemctl status patroni.service ? patroni.service - Runners to orchestrate a high-availability PostgreSQL Loaded: loaded (/etc/systemd/system/patroni.service; disabled; vendor preset: disabled) Active: active (running) since Wed 2020-03-04 09:22:32 UTC; 7s ago Main PID: 19572 (patroni) CGroup: /system.slice/patroni.service ??19572 /usr/bin/python3 /usr/local/bin/patroni /etc/patroni/patroni.yml ??19581 /usr/pgsql-11/bin/pg_ctl initdb -D /var/lib/pgsql/11/data -o --encoding=UTF8 --data-checksums --locale=ru_RU.UTF-8 --use... ??19583 /usr/pgsql-11/bin/initdb -D /var/lib/pgsql/11/data --encoding=UTF8 --data-checksums --locale=ru_RU.UTF-8 --username=post... Mar 04 09:22:33 dbone.example patroni[19572]: Data page checksums are enabled. Mar 04 09:22:33 dbone.example patroni[19572]: fixing permissions on existing directory /var/lib/pgsql/11/data ... ok Mar 04 09:22:33 dbone.example patroni[19572]: creating subdirectories ... ok Mar 04 09:22:33 dbone.example patroni[19572]: selecting default max_connections ... 100 Mar 04 09:22:33 dbone.example patroni[19572]: selecting default shared_buffers ... 128MB Mar 04 09:22:33 dbone.example patroni[19572]: selecting default timezone ... UTC Mar 04 09:22:33 dbone.example patroni[19572]: selecting dynamic shared memory implementation ... posix Mar 04 09:22:33 dbone.example patroni[19572]: creating configuration files ... ok Mar 04 09:22:33 dbone.example patroni[19572]: running bootstrap script ... ok Mar 04 09:22:34 dbone.example patroni[19572]: performing post-bootstrap initialization ... ok
В каталоге указанном в параметре "data_dir" из секции "postgresql" (/var/lib/pgsql/11/data) должна появиться структура каталогов кластера PostgreSQL Копировать в буфер обмена
> sudo ls -l /var/lib/pgsql/11/data drwx------. 5 postgres postgres 38 Mar 4 09:28 base drwx------. 2 postgres postgres 4096 Mar 4 09:28 global drwx------. 2 postgres postgres 6 Mar 4 09:28 pg_commit_ts drwx------. 2 postgres postgres 6 Mar 4 09:28 pg_dynshmem -rw-------. 1 postgres postgres 4581 Mar 4 09:28 pg_hba.conf -rw-------. 1 postgres postgres 1636 Mar 4 09:28 pg_ident.conf drwx------. 4 postgres postgres 65 Mar 4 09:28 pg_logical drwx------. 4 postgres postgres 34 Mar 4 09:28 pg_multixact drwx------. 2 postgres postgres 17 Mar 4 09:28 pg_notify drwx------. 2 postgres postgres 6 Mar 4 09:28 pg_replslot drwx------. 2 postgres postgres 6 Mar 4 09:28 pg_serial drwx------. 2 postgres postgres 6 Mar 4 09:28 pg_snapshots drwx------. 2 postgres postgres 6 Mar 4 09:28 pg_stat drwx------. 2 postgres postgres 6 Mar 4 09:28 pg_stat_tmp drwx------. 2 postgres postgres 17 Mar 4 09:28 pg_subtrans drwx------. 2 postgres postgres 6 Mar 4 09:28 pg_tblspc drwx------. 2 postgres postgres 6 Mar 4 09:28 pg_twophase -rw-------. 1 postgres postgres 3 Mar 4 09:28 PG_VERSION drwx------. 3 postgres postgres 58 Mar 4 09:28 pg_wal drwx------. 2 postgres postgres 17 Mar 4 09:28 pg_xact -rw-------. 1 postgres postgres 88 Mar 4 09:28 postgresql.auto.conf -rw-------. 1 postgres postgres 24084 Mar 4 09:28 postgresql.conf PostgreSQL должен быть запущен и слушать порт 5432
Копировать в буфер обмена
> ss -ltn | grep 5432 LISTEN 0 128 0.0.0.0:5432 0.0.0.0:*
Должна быть возможность подключения к кластеру PostgreSQL под пользователем usr1cv8 Копировать в буфер обмена
> psql -U usr1cv8 -d postgres
Если все хорошо, добавляем patroni.service в автозапуск
Копировать в буфер обмена
> sudo systemctl enable patroni.service
Created symlink from /etc/systemd/system/multi-user.target.wants/patroni.service to /etc/systemd/system/patroni.service. Настройка patronictl Создание файла с настройками по умолчанию позволит не указывать настройки подключения для patronictl.
Создаём файл ~/.config/patroni/patronictl.yaml со следующим содержимым: Копировать в буфер обмена
dcs_api: etcd://localhost:2379 namespace: /db/ scope: postgres authentication: username: patroni password: patroni
Проверяем результат выполненных настроек Копировать в буфер обмена
> patronictl list
или
> patronictl -c /etc/patroni/patronictl.yml list +----------+------------+---------------+--------+---------+----+-----------+-----------------+ | Cluster | Member | Host | Role | State | TL | Lag in MB | Pending restart | +----------+------------+---------------+--------+---------+----+-----------+-----------------+ | postgres | dbone | dbone.example | Leader | running | 1 | 0.0 | | +----------+------------+---------------+--------+---------+----+-----------+-----------------+
- Добавление нового узла Patroni
Для добавления нового узла в кластер Patroni, выполняются действия из раздела "Первый узел Patroni". Различия будут заключаться только в файле /etc/patroni/patroni.yml - все изменения заключаются в замене "dbone" на имя текущего сервера. Поэтому для dbtwo.example содержимое будет следующим:
Копировать в буфер обмена
name: dbtwo namespace: /db/ scope: postgres restapi: listen: 0.0.0.0:8008 connect_address: dbtwo.example:8008 authentication: username: patroni password: patroni etcd: hosts: localhost:2379 username: root password: rootpassword bootstrap: dcs: ttl: 30 loop_wait: 10 retry_timeout: 10 maximum_lag_on_failover: 1048576 master_start_timeout: 300 postgresql: use_pg_rewind: true use_slots: true parameters: wal_level: replica hot_standby: "on" wal_keep_segments: 8 max_wal_senders: 5 max_replication_slots: 5 checkpoint_timeout: 30 initdb: - auth-host: md5 - auth-local: peer - encoding: UTF8 - data-checksums - locale: ru_RU.UTF-8 pg_hba: - host replication replicator samenet md5 - host replication all 127.0.0.1/32 md5 - host replication all ::1/128 md5 users: usr1cv8: password: usr1cv8 options: - superuser postgresql: listen: 0.0.0.0:5432 connect_address: dbtwo.example:5432 config_dir: /var/lib/pgsql/11/data bin_dir: /usr/pgsql-11/bin/ data_dir: /var/lib/pgsql/11/data pgpass: /tmp/pgpass authentication: superuser: username: postgres password: V6OxPStvMPh0V7Q982DG replication: username: replicator password: PdR2lIAdwNdcSP4erAXc rewind: username: rewind_user password: WfcuDtEzEbLCHBaYQXX3 parameters: unix_socket_directories: '/var/run/postgresql/' tags: nofailover: false noloadbalance: false clonefrom: false nosync: false
После запуска Patroni на резервном сервере происходит следующее:
Patroni подключается к кластеру на dbone.example Создаётся новый кластер PostgreSQL и заполняется данными с dbone.example Новый кластер PostgreSQL переводится в "slave mode" В результате в кластере Patroni должно быть три узла:
Копировать в буфер обмена
> patronictl list +----------+------------+---------------+--------+---------+----+-----------+-----------------+ | Cluster | Member | Host | Role | State | TL | Lag in MB | Pending restart | +----------+------------+---------------+--------+---------+----+-----------+-----------------+ | postgres | dbone | 10.0.0.21 | Leader | running | 1 | | | | postgres | dbtwo | 10.0.0.22 | | running | 1 | 0.0 | | | postgres | dbthree | 10.0.0.23 | | running | 1 | 0.0 | | +----------+------------+---------------+--------+---------+----+-----------+-----------------+
Установка HAProxy
В настройках информационной базы, в кластере 1С:Предприятие, необходимо указывать имя сервера СУБД. В нашем случае им может быть один из серверов PostgreSQL. Так как указать все имена сразу мы не можем, а роли серверов (ведущий сервер и резервный сервер) могут поменяться в любой момент, следует создать точку подключения к PostgreSQL. В качестве точки подключения будет выступать HAProxy установленный на core.example. В задачe HAProxy будет входить слежение за ролями серверов PostgreSQL и, в случае их изменения, оперативное перенаправление запросов от 1С:Предприятие к СУБД на новый ведущий сервер.
Следующие действия выполняются на core.example
Устанавливаем HPAroxy из пакета и откладываем в сторону настройки по умолчанию Копировать в буфер обмена
> sudo yum install -y haproxy > sudo mv /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.conf.def
Создаём файл /etc/haproxy/haproxy.cfg со следующим содержимым Копировать в буфер обмена
global maxconn 100 defaults log global mode tcp retries 2 timeout client 30m timeout connect 4s timeout server 30m timeout check 5s listen stats mode http bind *:7000 stats enable stats uri / listen postgres bind *:5432 option httpchk http-check expect status 200 default-server inter 3s fastinter 1s fall 2 rise 2 on-marked-down shutdown-sessions server dbone dbone.example:5432 maxconn 100 check port 8008 server dbtwo dbtwo.example:5432 maxconn 100 check port 8008 server dbthree dbthree.example:5432 maxconn 100 check port 8008
Запускаем демон haproxy Если SELinux не выключался, то перед запуском необходимо внести изменения в настройки SELinux, разрешающие HAProxy обращаться на внешние адреса. Копировать в буфер обмена
> sudo setsebool -P haproxy_connect_any=1 > sudo systemctl start haproxy.service
Проверяем результат запуска Копировать в буфер обмена
> sudo systemctl status haproxy.service ? haproxy.service - HAProxy Load Balancer Loaded: loaded (/usr/lib/systemd/system/haproxy.service; disabled; vendor preset: disabled) Active: active (running) since Wed 2020-03-04 10:59:47 UTC; 2s ago Main PID: 17617 (haproxy-systemd) CGroup: /system.slice/haproxy.service ??17617 /usr/sbin/haproxy-systemd-wrapper -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid ??17618 /usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid -Ds ??17619 /usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid -Ds Mar 04 10:59:47 core.example systemd[1]: Started HAProxy Load Balancer. Mar 04 10:59:47 core.example systemd[1]: Starting HAProxy Load Balancer... Mar 04 10:59:47 core.example haproxy-systemd-wrapper[17617]: haproxy-systemd-wrapper: executing /usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid -Ds
Поверяем в интерфейсе haproxy (http://core.example:7000/), что узлы кластера Patroni найдены и их роли определены корректно. Ведущий сервер будет отмечен как "UP", резервные как "DOWN". Если запуск успешен, добавляем демон в автозагрузку Копировать в буфер обмена
> sudo systemctl enable haproxy.service
Created symlink from /etc/systemd/system/multi-user.target.wants/haproxy.service to /usr/lib/systemd/system/haproxy.service. Изменение настроек PostgreSQL через Patroni Так как PostgreSQL теперь управляется Patroni, то и настройки PostgreSQL задаются через конфигурационный файл Paroni. Рекомендуется поддерживать данные настройки одинаковыми на всех узлах. Для задания настроек PostgreSQL используется параметр "parameters" в секции "postgresql" файла /etc/patroni/patroni.yml Сейчас он выглядит следующим образом:
Копировать в буфер обмена parameters:
unix_socket_directories: '/var/run/postgresql/'
Следующие действия выполняются на серверах PostgreSQL.
Приводим "parameters" к следующему виду Копировать в буфер обмена
parameters: unix_socket_directories: '/var/run/postgresql/' shared_buffers: '1024MB' temp_buffers: '256MB' work_mem: '64MB' standard_conforming_strings: off escape_string_warning: off shared_preload_libraries: 'online_analyze, plantuner' plantuner.fix_empty_table: on online_analize.enable: on online_analize.table_type: 'temporary' online_analize.local_tracking: on online_analize.verbose: off maintenance_work_mem: '256MB' max_locks_per_transaction: 256 lc_messages: 'en_US.UTF-8' log_line_prefix: '%m [%p] %q%u@%d '
Значения параметров приведены только в качестве примера задания значений для этих параметров. Для определения значений парметров следует обратится к следующим статьям Настройки PostgreSQL для работы с 1С:Предприятием и Настройки PostgreSQL для работы с 1С:Предприятием. Часть 2 Применяем настройки Копировать в буфер обмена
> patronictl reload postgres dbone > patronictl restart postgres dbone > patronictl reload postgres dbtwo > patronictl restart postgres dbtwo > patronictl reload postgres dbthree > patronictl restart postgres dbthree
Проверяем изменения настроек Копировать в буфер обмена
> psql -U usr1cv8 -d postgres postgres> SHOW ALL;
Проверка переключения на резервный сервер PostgreSQL Проведём несколько проверок отказоустойчивости кластера.
Подготовка
Создаём информационную базу в кластере 1С:Предприятие. Параметры создания информационной базы:
Копировать в буфер обмена
Имя: test
Сервер баз данных: localhost Тип СУБД: PostgreSQL База данных: test Пользователь сервера БД: usr1cv8 Пароль пользователя сервера БД: usr1cv8 Загружаем в базу произвольную конфигурацию. После окончания загрузки проверяем, что данные переданы на резервный сервер
Копировать в буфер обмена
> patronictl list +----------+------------+---------------+--------+---------+----+-----------+-----------------+ | Cluster | Member | Host | Role | State | TL | Lag in MB | Pending restart | +----------+------------+---------------+--------+---------+----+-----------+-----------------+ | postgres | dbone | 10.0.0.21 | Leader | running | 10 | | | | postgres | dbtwo | 10.0.0.22 | | running | 1 | 0.0 | | | postgres | dbthree | 10.0.0.23 | | running | 1 | 0.0 | | +----------+------------+---------------+--------+---------+----+-----------+-----------------+
в колонке "Lag in MB" должно быть 0.0
Тесты
Для выполнения тестов, откроем информационную базу "Test" в режиме 1С:Предприятие.
Плановое переключение ведущего сервера На dbone.example выполняем команду смены ведущего сервера Копировать в буфер обмена
> patronictl failover
Проверяем переключение Копировать в буфер обмена
> patronictl list +----------+------------+---------------+--------+---------+----+-----------+-----------------+ | Cluster | Member | Host | Role | State | TL | Lag in MB | Pending restart | +----------+------------+---------------+--------+---------+----+-----------+-----------------+ | postgres | dbone | 10.0.0.21 | | running | 10 | 0.0 | | | postgres | dbtwo | 10.0.0.22 | Leader | running | 1 | | | | postgres | dbthree | 10.0.0.23 | | running | 10 | 0.0 | | +----------+------------+---------------+--------+---------+----+-----------+-----------------+
Проверяем работу в информационной базе - 1С:Предприятие изменений в инфраструктуре заменить не должно Сбой ведущего сервера На dbtwo.example выполняем команду для перезагрузки Копировать в буфер обмена
> shutdown -r
На dbone.example проверяем переключение Копировать в буфер обмена
> patronictl list +----------+------------+---------------+--------+---------+----+-----------+-----------------+ | Cluster | Member | Host | Role | State | TL | Lag in MB | Pending restart | +----------+------------+---------------+--------+---------+----+-----------+-----------------+ | postgres | dbone | 10.0.0.21 | Leader | running | 10 | | | | postgres | dbtwo | 10.0.0.22 | | running | 1 | 0.0 | | | postgres | dbthree | 10.0.0.23 | | running | 1 | 0.0 | | +----------+------------+---------------+--------+---------+----+-----------+-----------------+
Проверяем работу в информационной базе - 1С:Предприятие изменений в инфраструктуре заменить не должно
Резервное копирование Ниже приведён пример создания резервной копии кластера PostgreSQL, теми средствами, что идут в его поставке. Резервная копия может быть снята не только на ведущем сервере, но и на резервном сервере.
Создаём резервную копию Копировать в буфер обмена
> pg_basebackup -D ~/postgres.bak -Ft -z -P -U usr1cv8
Проверяем, что копия создана Копировать в буфер обмена
> ls ~/postgres.bak base.tar.gz pg_wal.tar.gz
Восстановление после сбоев Ниже приведена последовательность действий для проверки восстановления резервной копии на демонстрационном стенде. Поэтому, в реальной ситуации, раздел "Удаление данных" должен быть пересмотрен с учётом реальных обстоятельств сбоя. Раздел "Восстановление" предполагает, что описанное решение по созданию отказоустойчивого кластера Patroni полностью выполнено и его лишь надо наполнить данными.
Удаление данных
Проверяем текущие роли узлов кластера Patroni Копировать в буфер обмена
> patronictl list
Останавливаем Patroni и PostgreSQL на резервных серверах Копировать в буфер обмена
> sudo systemctl stop patroni > sudo systemctl stop postgresql-11
Останавливаем Patroni и PostgreSQL на ведущем сервере Копировать в буфер обмена
> sudo systemctl stop patroni > sudo systemctl stop postgresql-11
Удаляем кластер Patroni Копировать в буфер обмена
> patronictl remove postgres
На всех серверах PostgreSQL удаляем каталоги кластера Копировать в буфер обмена
> sudo rm -rf /var/lib/pgsql/11/data
Восстановление Восстанавливаем каталог кластера PostgreSQL на новом ведущем сервере Следующие действия выполняются на dbone.example
Копировать в буфер обмена
> sudo mkdir /var/lib/pgsql/11/data > sudo chown postgres:postgres /var/lib/pgsql/11/data > sudo chmod 700 /var/lib/pgsql/11/data > sudo tar xzf base.tar.gz -C /var/lib/pgsql/11/data > sudo tar xzf pg_wal.tar.gz -C /var/lib/pgsql/11/data/pg_wal > sudo rm /var/lib/pgsql/11/data/recovery.conf > sudo rm /var/lib/pgsql/11/data/recovery.done > sudo systemctl start patroni
Переносим файл резервной копии на новый резерный сервер Следующие действия выполняются на dbone.example
Копировать в буфер обмена
> scp -r ~/postgres.bak dbtwo.example:postgres.bak > scp -r ~/postgres.bak dbthree.example:postgres.bak
Восстанавливаем каталог кластера PostgreSQL на резервном сервере. На dbtwo.example и dbthree.example, повторяем действия выполненные на dbone.example
Проверяем результат
Копировать в буфер обмена
> patronictl list +----------+------------+---------------+--------+---------+----+-----------+-----------------+ | Cluster | Member | Host | Role | State | TL | Lag in MB | Pending restart | +----------+------------+---------------+--------+---------+----+-----------+-----------------+ | postgres | dbone | 10.0.0.21 | Leader | running | 1 | | | | postgres | dbtwo | 10.0.0.22 | | running | 1 | 0.0 | | | postgres | dbthree | 10.0.0.23 | | running | 1 | 0.0 | | +----------+------------+---------------+--------+---------+----+-----------+-----------------+
Использование резервного сервера PostgreSQL для механизма копий базы данных Механизм копий баз данных имеет особенность в использовании внешнего типа репликации данных при размещении данных в PostgreSQL. Особенность связана с тем, что резервный сервер PostgreSQL доступен только на чтение, включая временные таблицы. Такое ограничение приводит к тому, что запросы к СУБД, с созданием временных таблиц, выполняемые 1С:Предприятие, будут завершаться с ошибкой. Для снятия этого ограничения требуется развёртывание дополнительного кластера PostgreSQL, доступного для записи данных. Ниже будет описан пример развёртывания такого сервера.
Создание дополнительного кластера PostgreSQL
Для создания дополнительного кластера PostgreSQL можно добавить новый сервер и установить на него PostgreSQL. В этом случае порядок действий не отличается от обычной установки PostgreSQL. В случае, если добавление нового сервера нежелательно, дополнительный кластер PostgreSQL можно разместить на одном из существующих серверов PostgreSQL. Ниже показан пример развёртывания дополнительного кластера на уже существующем сервере. Следующие действия выполняются на dbthree.example Данные кластера будут расположены в каталоге /var/lib/pgsql/11/proxy
- Инициализируем кластер
Копировать в буфер обмена
> export LANG="ru_RU.UTF-8" > sudo -u postgres /usr/pgsql-11/bin/initdb -D /var/lib/pgsql/11/proxy --auth-local=peer --auth-host=md5 The files belonging to this database system will be owned by user "postgres". This user must also own the server process. The database cluster will be initialized with locales COLLATE: ru_RU.UTF-8 CTYPE: ru_RU.UTF-8 MESSAGES: ru_RU.UTF-8 MONETARY: en_GB.UTF-8 NUMERIC: en_GB.UTF-8 TIME: en_GB.UTF-8 The default database encoding has accordingly been set to "UTF8". The default text search configuration will be set to "russian". Data page checksums are disabled. creating directory /var/lib/pgsql/11/proxy ... ok creating subdirectories ... ok selecting default max_connections ... 100 selecting default shared_buffers ... 128MB selecting default timezone ... Europe/Moscow selecting dynamic shared memory implementation ... posix creating configuration files ... ok running bootstrap script ... ok performing post-bootstrap initialization ... ok syncing data to disk ... ok Success. You can now start the database server using: /usr/pgsql-11/bin/pg_ctl -D /var/lib/pgsql/11/proxy -l logfile start
Создаём unit файл /etc/systemd/system/postgresql-11-proxy.service Копировать в буфер обмена
[Unit] Description=PostgreSQL 11 database proxy server After=syslog.target After=network.target [Service] Type=notify User=postgres Group=postgres Environment=PGDATA=/var/lib/pgsql/11/proxy/ OOMScoreAdjust=-1000 ExecStartPre=/usr/pgsql-11/bin/postgresql-11-check-db-dir ${PGDATA} ExecStart=/usr/pgsql-11/bin/postmaster -D ${PGDATA} ExecReload=/bin/kill -HUP $MAINPID KillMode=mixed KillSignal=SIGINT TimeoutSec=300 [Install]
WantedBy=multi-user.target В файле /var/lib/pgsql/11/proxy/postgre.sql задаём порт, на котором будут приниматься подключения от клиентов Копировать в буфер обмена
#------------------------------------------------------------------------------ # CONNECTIONS AND AUTHENTICATION #------------------------------------------------------------------------------ # - Connection Settings - listen_addresses = '*' # what IP address(es) to listen on; # comma-separated list of addresses; # defaults to 'localhost'; use '*' for all # (change requires restart) port = 5433
Обновляем системные настройки и запускаем второй демон PostgreSQL Копировать в буфер обмена
> sudo systemctl daemon-reload > sudo systemctl start postgresql-11-proxy.service
Проверяем успешность запуска Копировать в буфер обмена
> ss -ltn | grep 5433 LISTEN 0 128 0.0.0.0:5433 0.0.0.0:*
Если запуск успешен, добавляем демон в автозапуск Копировать в буфер обмена
> sudo systemctl enable postgresql-11-proxy.service
Настройка кластера Создаём пользователя для 1С:Предприятие входим пользователем postgres Копировать в буфер обмена
> sudo -u postgres psql -p 5433
создаём нового пользователя Копировать в буфер обмена
posgres> CREATE USER usr1cv8 WITH SUPERUSER LOGIN ENCRYPTED PASSWORD 'usr1cv8';
Создаём информационную базу в кластере 1С:Предприятие Копировать в буфер обмена Имя: test Сервер баз данных: dbthree.example port=5433 Тип СУБД: PostgreSQL База данных: test Пользователь сервера БД: usr1cv8 Пароль пользователя сервера БД: usr1cv8 Создание информационной базы необходимо для корректного создания базы данных в кластере PostgreSQL. При создании базы данных 1С:Предприятие выполняет тонкие настройки в создаваемой базе данных, которые могут зависеть от версии платформы 1С:Предприятие. Настройка промежуточной базы данных Входим пользователем postgres в созданную базу данных Копировать в буфер обмена
> sudo -u postgres psql -p 5433 -d test
Удаляем все таблицы Копировать в буфер обмена
select 'DROP TABLE ' || string_agg(tablename, ', ') || ';' from pg_tables where schemaname = 'public' \gexec
Создаём в базе расширение postgres_fdw Копировать в буфер обмена
CREATE EXTENSION postgres_fdw;
Создаём сервер, указывая параметры для подключения к резервному серверу Копировать в буфер обмена
CREATE SERVER standby_server FOREIGN DATA WRAPPER postgres_fdw OPTIONS (host , dbname 'test', port '5432');
Создаём отображение для пользователей промежуточного сервера Копировать в буфер обмена
CREATE USER MAPPING FOR postgres SERVER standby_server OPTIONS (user 'usr1cv8', password 'usr1cv8'); CREATE USER MAPPING FOR usr1cv8 SERVER standby_server OPTIONS (user 'usr1cv8', password 'usr1cv8');
Импортируем таблицы внешней базы Копировать в буфер обмена
IMPORT FOREIGN SCHEMA public FROM SERVER standby_server INTO public;
В настройках подключения к копии базы данных следует указывать промежуточную базу:
Копировать в буфер обмена Сервер: dbthree.example port=5433 База данных: test В варианте использования резервного сервера для копии базы данных, имеет смысл запретить Patroni выбирать этот сервер в качестве ведущего. Для этого следует изменить секцию "tags" patroni.yml По умолчанию, секция "tags" содержит следующие параметры:
Копировать в буфер обмена
tags: nofailover: false noloadbalance: false clonefrom: false nosync: false
nofailover - значение "true" запрещает выбирать этот узел в качестве ведущего clonefrom - значение "true" рекомендует выбирать этот узел для создания резервной копии при развёртывании нового узла Patroni. Если значение "true" установлено у нескольких узлов, будет случайным образом выбран один из них noloadbalance - устанавливает HTTP код возврата 503 для запроса GET /replica REST API nosync - значение true запрещает выбирать этот узел для синхронной репликации В результате выполнения указанных настроек внешняя синхронизация для механизма копий баз данных при использовании СУБД MS SQL Server, а также выполнение запросов на копии, должны работать корректно.
Реструктуризация информационной базы
В случае изменения структуры метаданных информационной базы в структуру базы данных вносятся соответствующие изменения. Эти изменения необходимо перенести в промежуточную базу данных. Для этого следует удалить импортированные таблицы и импортировать схему заново. Следующие действия выполнятся на dbthree.example.
Входим пользователем postgres в промежуточную базу данных Копировать в буфер обмена
> sudo -u postgres psql -p 5433 -d test
Удаляем импортированные таблицы Копировать в буфер обмена
select 'DROP FOREIGN TABLE ' || string_agg(table_name, ', ') || ';' from information_schema.tables where table_type = 'FOREIGN' \gexec
Импортируем таблицы внешней базы Копировать в буфер обмена
IMPORT FOREIGN SCHEMA public FROM SERVER standby_server INTO public;
ИСТОЧНИК:
Полезное:
- ETCD - Управление
- Кластер PostgreSQL высокой надежности на базе Patroni, Haproxy, Keepalived
- Построение кластера PostgreSQL высокой доступности с использованием Patroni, etcd, HAProxy
- PostgreSQL и кластер patroni
- Истории аварий с Patroni, или Как уронить PostgreSQL-кластер
- Краткое введение в etcd
- Построение кластера PostgreSQL высокой доступности с использованием Patroni, etcd, HAProxy
- Patroni (Управление высокодоступными кластерами)
- Кластер PostgreSQL с использованием patroni
- PostgresPro - Создание кластера баз данных
- Репликация в PostgreSQL без проблем
- EFSOL - Настройка PostgreSQL Patroni Cluster
- Кластер PostgreSQL
--
- Опыт использования PostgreSQL cluster под управлением Patroni для 200 баз
- Управление высокодоступными PostgreSQL кластерами с помощью Patroni. А.Клюкин, А.Кукушкин
- Увеличить wal_keep_size Patroni
- PG_WAL is very big size
- Моя позиция wal превышает максимальную задержку репликации
- Схема репликации PostgreSQL
- How to properly restore cluster using WAL-G (WAL-E) to a specific time (PITR) on Postgres 12? #1571
- Rebuild Patroni Replica Using pgBackRest
- PostgreSQL High Availability installations Patroni
- Архивная репликация в PostgreSQL: пошаговая инструкция
- Patroni: synchronous_mode vs maximum_lag_on_failover
- Высокодоступные кластеры PostgreSQL с Patroni: Ваша очередь протестировать сценарии отказов