/pgsql_cluster

Высокодоступный кластер PostgreSQL на базе Patroni. С DNS точкой клиентского доступа, с поддержкой геораспределённого кластера. Автоматизация с помощью Ansible.

Primary LanguagePythonMIT LicenseMIT

Высокодоступный кластер PostgreSQL на базе Patroni. С DNS точкой клиентского доступа, с поддержкой геораспределения.

GitHub license GitHub stars


Banner

Развертывание кластера высокой доступности 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 опционально):

PGSQLCluster

Другие варианты реализации архитектуры высокой доступности - смотреть примеры.

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

  • порт 5000 (чтение / запись) мастер
  • порт 5001 (только чтение) все реплики
если переменная "synchronous_mode" равна 'true' (vars/main.yml):
  • порт 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:

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:

Для автоматизации развёртывания Решения используется 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):

По соображениям надёжности синхронная репликация в данном шаблоне включена. Автоматическая отработка отказа выполняется с переходом только на синхронную реплику.

Чтобы ещё более ужесточить требования к надёжности и свести к минимуму риск потери данных при автоматическом переходе на другой ресурс, вы можете настроить параметры следующим образом:

Развёртывание: быстрый старт

  1. Установите 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

  1. Скачайте или клонируйте этот репозиторий

git clone https://github.com/IlgizMamyshev/pgsql_cluster.git

  1. Перейдите в каталог с файлами playbook

cd pgsql_cluster/

  1. Отредактируйте файл инвентаризации
Задайте IP-адреса и параметры подключения (ansible_user, ansible_ssh_pass ...)

vim inventory

  1. Отредактируйте значения переменных в файле 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, чтобы узнать подробности.

Проверка после развёртывания

Patroni

Статус сервиса
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 |           |
+-----------------+--------------+--------------+---------+----+-----------+

DNSCP for Patroni

Журнал событий
sudo grep -i callback /var/log/syslog
Задание Планировщика для обновления динамической DNS-записи
sudo cat /var/spool/cron/crontabs/postgres
RAFT
sudo syncobj_admin -conn pgsql-n2:2379 -pass Password -status

HA Proxy

Статистика

http://pgsql-n2.demo.ru:7000
http://pgsql-n3.demo.ru:7000

PostgreSQL

Журнал событий
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();"

etcd

Статус сервиса
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 |        |
+----------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
Конфигурация PostgreSQL в 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 get service/pgsql-cluster/config

Обслуживание

Данный вопрос выходит за рамки данного описания.

Предлагается изучить следующие дополнительные материалы:

Аварийное восстановление

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

etcd

Узлы Patroni сбрасывают состояние параметров DCS на диск при каждом изменении конфигурации в файл patroni.dynamic.json, расположенный в каталоге данных PostgreSQL. Мастеру (узел Patroni с ролью Лидера) разрешено восстанавливать эти параметры из дампа на диске, если они полностью отсутствуют в DCS или если они недействительны.

Тем не менее, рекомендуется ознакомиться с руководством по аварийному восстановлению кластера etcd:

PostgreSQL (базы данных)

Рекомендуемые средства резервного копирования и восстановления:

Не забывайте тестировать свои резервные копии.

Как начать развёртывание с начала

Если вам нужно начать с самого начала, используйте для очистки следующие команды:

  • на всех узлах СУБД остановить сервис 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

Обратная связь, отчеты об ошибках, запросы и т.п.

Добро пожаловать!