Отказоустойчивый кластер PostgreSQL 16 с Patroni
Когда бизнес работает в режиме 24/7, простой базы данных означает прямой финансовый ущерб и остановку бизнес-процессов. Классическая репликация PostgreSQL (Streaming Replication) обеспечивает копирование данных, но не решает проблему автоматического переключения при сбое (Failover) без риска расщепления кластера (Split-Brain).
В этой статье команда Noxet разбирает проверенную production-архитектуру High Availability кластера на базе PostgreSQL 16, распределенного консенсуса etcd, менеджера высокой доступности Patroni и балансировщика HAProxy.
Целевая архитектура
Для гарантированной отказоустойчивости и соблюдения кворума требуется не менее трех узлов DCS (Distributed Configuration Store). Базовая схема кластера:
+----------------------------------+
| Клиенты / Приложения (App / 1C) |
+-----------------+----------------+
|
+-----------v-----------+
| HAProxy (VRRP / VIP) |
+-----+-----------+-----+
Port 5432 (Write) | | Port 5433 (Read-Only)
(Проверка: /primary)| | (Проверка: /replica)
| |
+-------------+-----------+-------------+
| |
+--------v--------+ +--------v--------+
| pg-node-01 | Streaming Repl | pg-node-02 |
| (Primary/Leader)|====================>| (Replica/Sync) |
| Patroni:8008 | | Patroni:8008 |
+--------+--------+ +--------+--------+
| |
+-------------------+-------------------+
|
+---------------v---------------+
| etcd Кластер (Кворум 3 ноды) |
| [etcd-01] [etcd-02] [etcd-03] |
+-------------------------------+
Компоненты стека:
- PostgreSQL 16: Реляционная СУБД с потоковой репликацией.
- etcd v3: Распределенное хранилище ключей и значений, обеспечивающее кворум и лидерство.
- Patroni: Демон, управляющий жизненным циклом PostgreSQL на каждом узле, отслеживающий здоровье инстанса и выполняющий автоматический промоут реплики.
- HAProxy: Маршрутизатор трафика, проверяющий HTTP health check эндпоинты Patroni (
:8008/primaryи:8008/replica).
1. Конфигурация Patroni (patroni.yml)
Patroni берет на себя инициализацию кластера, управление postgresql.conf и генерацию pg_hba.conf. Ниже приведен рабочий боевой шаблон конфигурации для первичного узла pg-node-01:
scope: pg-ha-cluster
namespace: /service
name: pg-node-01
# Взаимодействие с распределенным консенсусом etcd3
etcd3:
hosts:
- 192.168.10.11:2379
- 192.168.10.12:2379
- 192.168.10.13:2379
# REST API Patroni (используется для health-check балансировщиком и утилитой patronictl)
restapi:
listen: 192.168.10.21:8008
connect_address: 192.168.10.21:8008
# Глобальные параметры кластера (записываются в etcd при bootstrap)
bootstrap:
dcs:
ttl: 30
loop_wait: 10
retry_timeout: 10
maximum_lag_on_failover: 1048576 # 1 MB допустимого лага для автоматического промоута
synchronous_mode: true
synchronous_mode_strict: false
postgresql:
use_pg_rewind: true
use_slots: true
parameters:
wal_level: replica
max_wal_senders: 10
max_replication_slots: 10
hot_standby: "on"
wal_keep_size: 2048MB
max_connections: 500
shared_buffers: 8GB
effective_cache_size: 24GB
maintenance_work_mem: 2GB
checkpoint_completion_target: 0.9
wal_compression: "on"
initdb:
- encoding: UTF8
- data-checksums
pg_hba:
- host replication replicator 192.168.10.0/24 md5
- host all all 192.168.10.0/24 md5
- host all all 127.0.0.1/32 md5
# Локальные параметры PostgreSQL на узле
postgresql:
listen: 192.168.10.21:5432
connect_address: 192.168.10.21:5432
data_dir: /var/lib/postgresql/16/main
bin_dir: /usr/lib/postgresql/16/bin
pgpass: /var/lib/postgresql/.pgpass
authentication:
replication:
username: replicator
password: "StrongReplicationSecret2026!"
superuser:
username: postgres
password: "StrongSuperuserSecret2026!"
tags:
nofailover: false
noloadbalance: false
clonefrom: false
nosync: false
Для второго и третьего узлов (pg-node-02, pg-node-03) меняются только имя узла name и локальные IP-адреса в секциях restapi и postgresql.
2. Настройка балансировки в HAProxy
HAProxy маршрутизирует трафик приложений. Для разделения нагрузки на запись и чтение настраиваются два пула портов:
- Порт 5432: Направляет запросы строго на текущий Leader/Primary.
- Порт 5433: Балансирует read-only запросы между репликами.
Фрагмент /etc/haproxy/haproxy.cfg:
global
log /dev/log local0
maxconn 4096
user haproxy
group haproxy
defaults
log global
mode tcp
option tcplog
timeout connect 5000ms
timeout client 50000ms
timeout server 50000ms
# --- Master / Primary (Read-Write) ---
frontend pg_cluster_write
bind 0.0.0.0:5432
default_backend pg_cluster_primary
backend pg_cluster_primary
mode tcp
option httpchk GET /primary
http-check expect status 200
default-server inter 3s fall 3 rise 2 on-marked-down shutdown-sessions
server pg-node-01 192.168.10.21:5432 maxconn 300 check port 8008
server pg-node-02 192.168.10.22:5432 maxconn 300 check port 8008
server pg-node-03 192.168.10.23:5432 maxconn 300 check port 8008
# --- Replicas (Read-Only) ---
frontend pg_cluster_read
bind 0.0.0.0:5433
default_backend pg_cluster_replicas
backend pg_cluster_replicas
mode tcp
balance roundrobin
option httpchk GET /replica
http-check expect status 200
default-server inter 3s fall 3 rise 2
server pg-node-01 192.168.10.21:5432 check port 8008
server pg-node-02 192.168.10.22:5432 check port 8008
server pg-node-03 192.168.10.23:5432 check port 8008
3. Защита от Split-Brain и механизмы восстановления
Один из главных рисков в распределенных кластерах — ситуация Split-Brain, когда из-за сетевой изоляции два узла считают себя мастерами и начинают независимо принимать операции записи, разрушая консистентность данных.
Как Patroni предотвращает Split-Brain:
- Лидерский ключ с TTL (Time to Live): Текущий Primary непрерывно продлевает свой ключ в etcd каждые
loop_waitсекунд (по умолчанию 10 с). - Аппаратный Watchdog: Patroni интегрируется с Linux watchdog (
/dev/watchdog). Если демон Patroni зависает или теряет связь с etcd, watchdog принудительно перезагружает ОС хоста через заданный таймаут до того, как истечет TTL ключа. - Автоматический pg_rewind: Если старый мастер вернулся в сеть после сбоя, Patroni запускает
pg_rewind, откатывает локальный WAL до развилки таймлайна и переводит сервер в режим реплики без необходимости полного повторного клонирования базы (pg_basebackup).
4. Эксплуатация и мониторинг кластера
Управление кластером выполняется через утилиту patronictl:
# Просмотр текущего статуса и топологии кластера
patronictl -c /etc/patroni/patroni.yml list
# Ручной плановый switchover (переключение мастера без даунтайма)
patronictl -c /etc/patroni/patroni.yml switchover --master pg-node-01 --candidate pg-node-02
# Перезапуск узла после изменения параметров СУБД
patronictl -c /etc/patroni/patroni.yml restart pg-ha-cluster pg-node-01
Метрики для Prometheus:
Patroni экспортирует стандартные метрики через HTTP-эндпоинт /metrics. В Prometheus настраивается сбор лага репликации (patroni_replication_lag), текущей роли инстанса (patroni_is_leader) и статуса etcd-кворума.
Итог
Такой стек обеспечивает RTO (время восстановления) в пределах 5–15 секунд и RPO (потерю данных) равным 0 при синхронной репликации. Архитектура успешно справляется с падениями отдельных серверов, сетевыми разделениями и регламентным обновлением кластера без простоя приложений.
Если вашему проекту требуется аудит текущей СУБД или развертывание отказоустойчивой архитектуры PostgreSQL под высокие нагрузки — свяжитесь с командой Noxet.