294 материалов в базеАвтор: Андрей Лукин
Практический разборВремя чтения: 6 мин· 6 января 2026 г.0

Архитектура HA-кластера PostgreSQL на Patroni + Etcd: RPO≈0 и защита от split-brain в 2026

Архитектура HA-кластера PostgreSQL на Patroni + Etcd: RPO≈0 и защита от split-brain в 2026

Быстрый ответ: решение за 30 секунд

Построение отказоустойчивого кластера PostgreSQL требует разделения ответственности между механизмом управления состоянием (State Machine) и хранилищем данных (DCS). Patroni выступает в роли State Machine, используя ключи с TTL в etcd для определения лидера. При потере связи с DCS или падении узла ключ истекает, что инициирует автоматический переход (failover) на следующую доступную реплику. Для обеспечения нулевой потери данных (RPO≈0) необходимо включить синхронную репликацию (synchronous_mode = true) и настроить кворум в etcd. Критически важно использовать pg_rewind вместо pg_basebackup для восстановления отставшего узла, сокращая время восстановления (RTO) с минут до секунд.

Технические параметры и сводная таблица

Параметр/Инструмент Значение/Версия Назначение/Команда Примечание
DCS (Data Center Store) Etcd 3.5+ Хранение состояния лидера и TTL Обеспечивает консенсус по протоколу Raft
State Machine Patroni 3.4+ Управление жизненным циклом PG Использует Compare-And-Swap (CAS)
БД PostgreSQL 16+ Хранение данных Поддержка synchronous_commit и wal_log_hints
Кворум etcd 3 узла (n/2 + 1) для доступности Потеря 1 узла не останавливает кластер
Синхронная репликация ANY 1 synchronous_mode = true Гарантирует запись на диск реплики
Восстановление узла pg_rewind --data-checksums Мгновенная синхронизация без бэкапа
Контейнеризация Docker Compose Оркестрация сервисов Изоляция сетей и объемов хранения

Пошаговый алгоритм решения

Шаг 1. Развертывание и конфигурация кластера etcd

Первым этапом является создание высокодоступного хранилища состояния. Кластер etcd требует нечетное количество узлов (минимум 3) для обеспечения кворума при отказе одного узла. Без кворума (majority) DCS переходит в режим read-only, блокируя логику failover Patroni.

Создайте docker-compose.yml для etcd:

version: "3.8"
services:
  etcd-1:
 image: quay.io/coreos/etcd:v3.5.13
 container_name: etcd-1
 command:
 - --name=etcd-1
 - --initial-advertise-peer-urls=http://etcd-1:2380
 - --listen-peer-urls=http://0.0.0.0:2380
 - --listen-client-urls=http://0.0.0.0:2379
 - --advertise-client-urls=http://etcd-1:2379
 - --initial-cluster=etcd-1=http://etcd-1:2380,etcd-2=http://etcd-2:2380,etcd-3=http://etcd-3:2380
 - --initial-cluster-state=new
 - --data-dir=/var/lib/etcd
 ports:
 - "2379:2379"
 - "2380:2380"
 networks:
 - pg-ha-net
 volumes:
 - etcd-data-1:/var/lib/etcd

  etcd-2:
 image: quay.io/coreos/etcd:v3.5.13
 container_name: etcd-2
 command:
 - --name=etcd-2
 - --initial-advertise-peer-urls=http://etcd-2:2380
 - --listen-peer-urls=http://0.0.0.0:2380
 - --listen-client-urls=http://0.0.0.0:2379
 - --advertise-client-urls=http://etcd-2:2379
 - --initial-cluster=etcd-1=http://etcd-1:2380,etcd-2=http://etcd-2:2380,etcd-3=http://etcd-3:2380
 - --data-dir=/var/lib/etcd
 networks:
 - pg-ha-net
 volumes:
 - etcd-data-2:/var/lib/etcd

  etcd-3:
 image: quay.io/coreos/etcd:v3.5.13
 container_name: etcd-3
 command:
 - --name=etcd-3
 - --initial-advertise-peer-urls=http://etcd-3:2380
 - --listen-peer-urls=http://0.0.0.0:2380
 - --listen-client-urls=http://0.0.0.0:2379
 - --advertise-client-urls=http://etcd-3:2379
 - --initial-cluster=etcd-1=http://etcd-1:2380,etcd-2=http://etcd-2:2380,etcd-3=http://etcd-3:2380
 - --data-dir=/var/lib/etcd
 networks:
 - pg-ha-net
 volumes:
 - etcd-data-3:/var/lib/etcd

networks:
  pg-ha-net:
 driver: bridge

volumes:
  etcd-data-1:
  etcd-data-2:
  etcd-data-3:
Важно

КРИТИЧЕСКИ ВАЖНО: Убедитесь, что все узлы etcd находятся в одной сети (pg-ha-net). Потеря связи между узлами etcd приведет к потере кворума, и Patroni перестанет управлять кластером.

Шаг 2. Настройка PostgreSQL и Patroni

Создайте конфигурацию для PostgreSQL, включающую параметры для синхронной репликации и оптимизации WAL. Затем разверните три узла PostgreSQL, каждый из которых будет запущен через контейнер Patroni.

Конфигурация postgresql.conf для всех нод (с учетом переменных окружения для имен):

# Базовые настройки
listen_addresses = '*'
port = 5432
max_connections = 200
shared_buffers = 256MB

# Настройки для HA и репликации
wal_level = replica
max_wal_senders = 10
hot_standby = on
synchronous_commit = on
synchronous_standby_names = 'ANY 1 (node2, node3)'

# Оптимизация для pg_rewind
wal_log_hints = on
data_checksums = on

# Настройки Patroni
wal_keep_size = 64MB
max_replication_slots = 3

Конфигурация patroni.yml (общая для всех нод, с подстановкой имени):

scope: pg-ha
namespace: /service/
name: node1  # Меняйте на node2, node3 для остальных нод
rest_api:
  listen: 0.0.0.0:8001
  connect_address: node1:8001
etcd:
  hosts:
 - etcd-1:2379
 - etcd-2:2379
 - etcd-3:2379
 - etcd-4:2379  # Если есть 4-й узел, но в примере 3
  ttl: 30
  max_retries: 10
  retry_timeout: 10
  max_cache_ttl: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 1000
  max_cache_size: 10
Андрей Лукин
Андрей Лукин Автор

Full-stack разработчик и Digital-спасатель. Пишу о технологиях, ИИ и реальной инженерной практике без воды.

Для читателей этой статьи

Понравился материал?

Подпишитесь на Telegram-канал: свежие инсайты, промпты и разборы первыми. Без спама, только польза.

Подписаться в Telegram
Ещё в рубрике «Разработка»

Материалы по теме

Читаете:Архитектура HA-кластера PostgreSQL на Patroni + Etcd: RPO≈0 и защита от split-brain в 2026Обсудить в TG