$ cat "Сборка отказоустойчивого кластера PostgreSQL 16 для Enterprise: пошаговый гайд.md"

Отказоустойчивый кластер 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] |
                 +-------------------------------+

Компоненты стека:

  1. PostgreSQL 16: Реляционная СУБД с потоковой репликацией.
  2. etcd v3: Распределенное хранилище ключей и значений, обеспечивающее кворум и лидерство.
  3. Patroni: Демон, управляющий жизненным циклом PostgreSQL на каждом узле, отслеживающий здоровье инстанса и выполняющий автоматический промоут реплики.
  4. 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:

  1. Лидерский ключ с TTL (Time to Live): Текущий Primary непрерывно продлевает свой ключ в etcd каждые loop_wait секунд (по умолчанию 10 с).
  2. Аппаратный Watchdog: Patroni интегрируется с Linux watchdog (/dev/watchdog). Если демон Patroni зависает или теряет связь с etcd, watchdog принудительно перезагружает ОС хоста через заданный таймаут до того, как истечет TTL ключа.
  3. Автоматический 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.