Высокодоступный кластер PostgreSQL на базе Patroni. С DNS точкой клиентского доступа, с поддержкой геораспределения.
Развертывание кластера высокой доступности PostgreSQL на основе Patroni. Автоматизация с помощью Ansible.
Этот Ansible playbook разработан для развёртывания высокодоступного кластера PostgreSQL на выделенных физических серверах для производственной среды.
Развёртывание может быть выполнено в виртуальной среде для тестовой среды или небольших проектов.
В дополнение к развертыванию новых кластеров этот playbook также поддерживает развертывание кластера поверх уже существующего и работающего PostgreSQL. Вы можете преобразовать выделенный экземпляр PostgreSQL в кластер высокой доступности (укажите переменную postgresql_exists='true'
в файле инвентаризации).
Внимание! Ваш экземпляр PostgreSQL будет остановлен перед запуском в составе кластера (запланируйте небольшой простой баз данных).
❗ Пожалуйста, проведите тестирование, прежде чем использовать в производственной среде.
- развёртывание кластера Patroni с СУБД PostgreSQL или Postgres Pro;
- использование встроенного механизма распределённого консенсуса или использование внешней DCS (etcd);
- настройка watchdog для Patroni (защита от split-brain);
- настройка параметров ядра операционной системы Linux;
- настройка сетевого брандмауэра;
- DNS точка подключения клиентов (DNS Connection Point);
- поддержка геораспределенного кластера (DNS Connection Point);
- развёртывание HAProxy для балансировки доступа к репликам только для чтения;
- развёртывание кластера etcd;
Высокодоступный кластер, на базе Patroni (на чистом RAFT) и DNSCP (балансировка с HAProxy опционально):
Другие варианты реализации архитектуры высокой доступности - смотреть примеры.
Применение HAProxy обеспечивает возможность распределения нагрузки по чтению. Это также позволяет масштабировать кластер с репликами только для чтения.
- порт 5000 (чтение / запись) мастер
- порт 5001 (только чтение) все реплики
- порт 5002 (только чтение) только синхронные реплики
- порт 5003 (только чтение) только асинхронные реплики
Для развёртывания кластера без HAProxy задайте
with_haproxy_load_balancing: false
в файле переменных vars/main.yml
Patroni - это шаблон для создания решения высокой доступности с использованием Python и распределенного хранилища конфигурации, собственного или такого как ZooKeeper, etcd, Consul или Kubernetes. Используется для автоматизации управления экземплярами PostgreSQL и автоматического аварийного переключения.
etcd - это распределенное надежное хранилище ключей и значений для наиболее важных данных распределенной системы. etcd написан на Go и использует алгоритм консенсуса Raft для управления высокодоступным реплицированным журналом. Он используется Patroni для хранения информации о состоянии кластера и параметрах конфигурации PostgreSQL.
Что такое Распределенный Консенсус (Distributed Consensus)?
DNS Connection Point for Patroni используется для обеспечения единой точки входа. DNSCP обеспечивает регистрацию DNS-записи как единой точки входа для клиентов и позволяет использовать один или более виртуальных IP-адресов (VIP), принадлежащих одной или нескольким подсетям. DNSCP использует функцию обратных вызовов (callback) Patroni.
HAProxy — очень быстрое и надежное решение, предлагающее высокую доступность, балансировку нагрузки и прокси для приложений на основе TCP и HTTP. HAProxy входит в состав репозиторя ОС Astra Linux, но также можно использовать внешний источник.
PostgreSQL - реляционная база данных с открытым исходным кодом. При использовании ОС Astra Linux возможно использование PostgreSQL в составе репозитория ОС.
Поддерживаются все поддерживаемые версии PostgreSQL.
✅ протестировано: PostgreSQL 11, 14, 15
Postgres Pro - Российская система управления базами данных на основе PostgreSQL. Коммерческий продукт. Поддерживаются все версии Postgres Pro, редакции Standard и Enterprise.
✅ протестировано: Postgres Pro 14, 15
- Debian: 9, 10, 11
- Astra Linux: CE (основан на Debian 9), SE (основан на Debian 10)
✅ протестировано: Astra Linux CE 2.12, Astra Linux SE 1.7
Для автоматизации развёртывания Решения используется Ansible - система управления конфигурациями. При использовании ОС Astra Linux возможно использование Ansible из состава репозитория операционной системы. Минимальная поддерживаемая версия Ansible - 2.7.
Этот playbook требует root привилегий или sudo.
Ansible (Что такое Ansible?)
Список необходимых портов TCP, которые должны быть открыты для кластера баз данных:
5432
(PostgreSQL)8008
(Patroni Rest API)2379
(Patroni RAFT)2379
,2380
(etcd)5000
(HAProxy - (чтение / запись) мастер реплика5001
(HAProxy - (только чтение) все реплики5002
(HAProxy - (только чтение) только синхронные реплики5003
(HAProxy - (только чтение) только асинхронные реплики
- Linux (Операционная Система):
Обновите все операционные системы перед развёртыванием;
Присоедините серверы-узлы кластера СУБД к домену Microsoft Active Directory или Astra Linux Directory. Присоединение к домену является требованием, если вы хотите использовать аутентифицированный доступ к DNS-серверу при регистрации DNS-имени точки клиентского доступа.
- Patroni RAFT:
Patroni может не зависеть от сторонних систем DCS (Distributed Consensus Store, типа etcd, Consul, ZooKeeper) за счёт собственной реализации RAFT. При необходимости возможность использовать внешние системы DCS остаётся.
- DCS (Распределённое Хранилище Конфигурации (Distributed Configuration Store)):
Быстрые диски и надежная сеть являются наиболее важными факторами производительности и стабильности кластера etcd.
Избегайте хранения данных etcd на одном диске вместе с другими процессами (такими как база данных), интенсивно использующими ресурсы дисковой подсистемы!
Храните данные etcd и PostgreSQL на разных дисках (см. переменную etcd_data_dir
), по возможности используйте диски ssd.
Рекомендуется изучить руководства по выбору оборудования и настройке etcd.
Для высоконагруженных СУБД рассмотрите установку кластера etcd на выделенных серверах.
Изучите вопросы планирования кластера etcd. Примеры.
- Как предотвратить потерю данных в случае автоматической отработки отказа (synchronous_modes and pg_rewind):
По соображениям надёжности синхронная репликация в данном шаблоне включена. Автоматическая отработка отказа выполняется с переходом только на синхронную реплику.
Чтобы ещё более ужесточить требования к надёжности и свести к минимуму риск потери данных при автоматическом переходе на другой ресурс, вы можете настроить параметры следующим образом:
- synchronous_mode: 'true' (включен по умолчанию в данном playbook)
- synchronous_mode_strict: 'true' (выключен по умолчанию)
- synchronous_commit: 'on' (или 'remote_apply') ('on' по умолчанию)
- use_pg_rewind: 'false' (включен по умолчанию)
- Установите Ansible на сервер управления, свой компьютер или ноутбук
Пример 1 (установка, используя репозиторий Astra Linux):
sudo apt update
sudo apt install ansible
\
--Установка пакета для работы с pyOpenSSL
sudo apt-get install libssl-dev
sudo pip3 install --upgrade pip
sudo pip install pyOpenSSL
Пример 2 (установка, используя pip ):
sudo apt update && sudo apt install python3-pip sshpass git -y
sudo pip3 install ansible
\
--Установка пакета для работы с pyOpenSSL
sudo apt-get install libssl-dev
sudo pip3 install --upgrade pip
sudo pip install pyOpenSSL
- Скачайте или клонируйте этот репозиторий
git clone https://github.com/IlgizMamyshev/pgsql_cluster.git
- Перейдите в каталог с файлами playbook
cd pgsql_cluster/
- Отредактируйте файл инвентаризации
vim inventory
- Отредактируйте значения переменных в файле vars/main.yml
vim vars/main.yml
5.1 Запустите playbook для установки кластера etcd (опционально, если используете etcd DCS вместо Patroni RAFT):
sudo su
ansible-playbook etcd_cluster.yml
После успешного развёртывания в /vars/main.yml укажите dcs_exists: true
и dcs_type: "etcd"
5.2 Запустите playbook для установки кластера PostgreSQL:
sudo su
ansible-playbook deploy_pgcluster.yml
5.3 Запустите playbook для установки HA Proxy (опционально):
ansible-playbook balancers.yml
Чтобы установить HA Proxy сразу во время развёртывания кластера PostgreSQL в /vars/main.yml укажите with_haproxy_load_balancing: true
Смотри файлы vars/main.yml, system.yml и Debian.yml, чтобы узнать подробности.
sudo systemctl status patroni.service
sudo grep -i patroni /var/log/syslog
sudo tail -n 15 /var/log/syslog
sudo patronictl -c /etc/patroni/patroni.yml list
+ Cluster: PGSQL-CL (1234567890123456789) ----------------+----+-----------+
| Member | Host | Role | State | TL | Lag in MB |
+-----------------+--------------+--------------+---------+----+-----------+
| PGSQL-N2 | 172.16.33.22 | Sync Standby | running | 3 | 0 |
| PGSQL-N3 | 172.16.33.33 | Leader | running | 3 | |
+-----------------+--------------+--------------+---------+----+-----------+
sudo grep -i callback /var/log/syslog
sudo cat /var/spool/cron/crontabs/postgres
sudo syncobj_admin -conn pgsql-n2:2379 -pass Password -status
http://pgsql-n2.demo.ru:7000
http://pgsql-n3.demo.ru:7000
sudo tail -n 20 /var/log/postgresql/postgresql-15.log
/opt/pgpro/std-14/bin/psql -p 5432 -U postgres -d postgres -c "SELECT version();"
sudo systemctl status etcd.service
sudo ETCDCTL_API=2 etcdctl --ca-file="/etc/etcd/ssl/ca.crt" --endpoints https://127.0.0.1:2379 --cert-file=/etc/etcd/ssl/server.crt --key-file=/etc/etcd/ssl/server.key cluster-health
sudo su
ENDPOINTS=$(ETCDCTL_API=3 etcdctl member list --cacert="/etc/etcd/ssl/ca.crt" --cert=/etc/etcd/ssl/server.crt --key=/etc/etcd/ssl/server.key | grep -o '[^ ]\+:2379' | paste -s -d,)
ETCDCTL_API=3 etcdctl --endpoints=$ENDPOINTS endpoint health --write-out=table --cacert="/etc/etcd/ssl/ca.crt" --cert=/etc/etcd/ssl/server.crt --key=/etc/etcd/ssl/server.key
+----------------------------+--------+-------------+-------+
| ENDPOINT | HEALTH | TOOK | ERROR |
+----------------------------+--------+-------------+-------+
| https://172.16.32.11:2379 | true | 23.921885ms | |
| https://172.16.64.22:2379 | true | 35.531942ms | |
| https://172.16.96.33:2379 | true | 36.971386ms | |
+----------------------------+--------+-------------+-------+
ETCDCTL_API=3 sudo etcdctl member list -w table --cacert="/etc/etcd/ssl/ca.crt" --cert=/etc/etcd/ssl/server.crt --key=/etc/etcd/ssl/server.key
+------------------+---------+-----------------+----------------------------+----------------------------+------------+
| ID | STATUS | NAME | PEER ADDRS | CLIENT ADDRS | IS LEARNER |
+------------------+---------+-----------------+----------------------------+----------------------------+------------+
| 1111111111111111 | started | ETCD-N1 | https://172.16.32.11:2380 | https://172.16.32.11:2379 | false |
| 2222222222222222 | started | ETCD-N2 | https://172.16.64.22:2380 | https://172.16.64.22:2379 | false |
| 3333333333333333 | started | ETCD-N3 | https://172.16.96.33:2380 | https://172.16.96.33:2379 | false |
+------------------+---------+-----------------+----------------------------+----------------------------+------------+
sudo su
ENDPOINTS=$(ETCDCTL_API=3 etcdctl member list --cacert="/etc/etcd/ssl/ca.crt" --cert=/etc/etcd/ssl/server.crt --key=/etc/etcd/ssl/server.key | grep -o '[^ ]\+:2379' | paste -s -d,)
ETCDCTL_API=3 etcdctl --endpoints=$ENDPOINTS endpoint status --write-out=table --cacert="/etc/etcd/ssl/ca.crt" --cert=/etc/etcd/ssl/server.crt --key=/etc/etcd/ssl/server.key
+----------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
| ENDPOINT | ID | VERSION | DB SIZE | IS LEADER | IS LEARNER | RAFT TERM | RAFT INDEX | RAFT APPLIED INDEX | ERRORS |
+----------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
| https://172.16.32.11:2379 | 1111111111111111 | 3.5.6 | 20 kB | false | false | 2 | 23 | 23 | |
| https://172.16.64.22:2379 | 2222222222222222 | 3.5.6 | 20 kB | true | false | 2 | 23 | 23 | |
| https://172.16.96.33:2379 | 3333333333333333 | 3.5.6 | 20 kB | false | false | 2 | 23 | 23 | |
+----------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
sudo ETCDCTL_API=2 etcdctl --ca-file="/etc/etcd/ssl/ca.crt" --endpoints https://127.0.0.1:2379 --cert-file=/etc/etcd/ssl/server.crt --key-file=/etc/etcd/ssl/server.key get service/pgsql-cluster/config
Данный вопрос выходит за рамки данного описания.
Предлагается изучить следующие дополнительные материалы:
- Учебник: Управление высокодоступными кластерами PostgreSQL с Patroni
- Документация Patroni
- Руководство по эксплуатации etcd
Кластер высокой доступности обеспечивает механизм автоматического перехода на другой ресурс и не охватывает все сценарии аварийного восстановления. Вы должны позаботиться о резервном копировании своих данных самостоятельно.
Узлы Patroni сбрасывают состояние параметров DCS на диск при каждом изменении конфигурации в файл patroni.dynamic.json, расположенный в каталоге данных PostgreSQL. Мастеру (узел Patroni с ролью Лидера) разрешено восстанавливать эти параметры из дампа на диске, если они полностью отсутствуют в DCS или если они недействительны.
Тем не менее, рекомендуется ознакомиться с руководством по аварийному восстановлению кластера etcd:
Рекомендуемые средства резервного копирования и восстановления:
Не забывайте тестировать свои резервные копии.
Если вам нужно начать с самого начала, используйте для очистки следующие команды:
- на всех узлах СУБД остановить сервис Patroni и удалить кластер баз данных (каталог с базами данных, PGDATA), каталог с конфигурацией Patroni:
sudo systemctl stop patroni sudo rm -rf /var/lib/postgresql/ # будьте осторожны, если есть другие экземпляры PostgreSQL sudo rm -rf /etc/patroni/
- затем, если используется etcd, удалите запись в etcd (можно запустить на любом узле etcd):
sudo ETCDCTL_API=2 etcdctl --ca-file="/etc/etcd/ssl/ca.crt" --endpoints https://127.0.0.1:2379 --cert-file=/etc/etcd/ssl/server.crt --key-file=/etc/etcd/ssl/server.key rm --dir --recursive /service/
Под лицензией MIT License. Подробнее см. в файле LICENSE .
Илгиз Мамышев (Microsoft SQL Server, PostgreSQL DBA)
https://imamyshev.wordpress.com
Виталий Кухарик (PostgreSQL DBA) - автор проекта postgresql_cluster на кодовой базе которого построен pgsql_cluster