Зачем Patroni и когда он нужен
Если приложению необходима высокая доступность (HA) PostgreSQL и сокращение RTO/RPO до секунд, Patroni — один из самых зрелых и понятных инструментов. Он управляет экземплярами PostgreSQL, ведёт их состояние во внешнем DCS (Distributed Configuration Store) и автоматически выполняет failover при отказе лидера. Для небольших и средних продакшенов Patroni отлично чувствует себя на VDS, обеспечивая быстрый старт и прозрачную эксплуатацию.
Важная мысль: Patroni не заменяет резервные копии, дисциплину обновлений и мониторинг. Он лишь автоматизирует управляемый переход роли лидер/реплика, предотвращает split-brain и снижает время простоя. Всё остальное — ваша архитектура, инфраструктура и процедуры.
Архитектура кластера: роли, DCS, кворум
Минимальная живая схема — три узла PostgreSQL (1 лидер, 2 реплики) и отказоустойчивый DCS. Допускается запуск DCS на тех же узлах для экономии ресурсов, но для серьёзных нагрузок лучше выделить его отдельно. DCS хранит метаданные кластера (кто лидер, TTL, кандидаты), а Patroni на узлах конкурирует за лидерство, опираясь на эти данные.
Типовые DCS для Patroni: etcd, Consul и ZooKeeper. На практике чаще берут etcd или Consul из-за простоты и богатой операционной базы. Кворум DCS — нечётное число узлов (3, 5). Два узла в DCS — антипаттерн: при сетевой сегментации легко потерять кворум.
Выбор DCS: etcd vs Consul кратко
etcd — минималистичный key-value с сильной консистентностью, простой моделью и хорошей операционной базой. Consul — богаче по функционалу (DNS, Service Discovery, Health-checks), но это лишняя сложность, если вам нужен только реестр для Patroni. Если команда уже эксплуатирует Consul — берите его. Начинаете с нуля — чаще проще etcd.
Сетевые порты и безопасность
Откройте только необходимое и фильтруйте источники:
- PostgreSQL: 5432/tcp (клиенты и репликация).
- Patroni REST API: 8008/tcp (управление и здоровье; ограничьте доступом по сети и/или базовой аутентификацией).
- etcd: 2379/tcp (client API), 2380/tcp (peer); шифруйте и аутентифицируйте.
Не публикуйте эти порты в Интернет без нужды. Используйте файрвол, шифрование на уровне DCS и PostgreSQL, независимую опорную синхронизацию времени. Для TLS-подключений используйте корпоративный PKI или оформите SSL-сертификаты.
Подготовка узлов VDS
Предположим три узла VDS с современной ОС (например, Debian/Ubuntu LTS), одинаковыми версиями PostgreSQL, временем (chrony) и системной локалью. На всех узлах создайте пользователя postgres, настройте SSH-доступ администратора и включите файрвол с минимально необходимыми правилами.
Установите пакеты PostgreSQL, Patroni и выбранный DCS. На Debian/Ubuntu это часто делается стандартными репозиториями. Версия PostgreSQL на всех узлах должна совпадать. Проверьте дисковые параметры (fsync, write cache, scheduler) и убедитесь, что каталоги данных и WAL на надёжном хранилище.

Разворачиваем DCS (пример — etcd)
Для учебного стенда можно поднять 3 экземпляра etcd на тех же узлах. Для продакшена лучше выделить отдельные малые узлы. Включите TLS между участниками и клиентами, настройте аутентификацию и роли. Ниже — упрощённый пример без TLS для локальной сети (для реального продакшена обязательно включайте шифрование и авторизацию).
# Установка (пример для Debian/Ubuntu)
sudo apt update
sudo apt install etcd
# Базовая проверка версии
etcd --version
Сконфигурируйте каждый узел, указав уникальные имя/адрес и общий список участников. Пример для узла node1 (адаптируйте IP):
# /etc/default/etcd (или аналогичный файл окружения)
ETCD_NAME="node1"
ETCD_DATA_DIR="/var/lib/etcd"
ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:2379"
ETCD_ADVERTISE_CLIENT_URLS="http://10.0.0.11:2379"
ETCD_LISTEN_PEER_URLS="http://0.0.0.0:2380"
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://10.0.0.11:2380"
ETCD_INITIAL_CLUSTER="node1=http://10.0.0.11:2380,node2=http://10.0.0.12:2380,node3=http://10.0.0.13:2380"
ETCD_INITIAL_CLUSTER_STATE="new"
ETCD_INITIAL_CLUSTER_TOKEN="pg-ha-token"
Повторите для node2/node3 с их адресами. Запустите и проверьте кластер etcd:
sudo systemctl enable --now etcd
etcdctl endpoint status --write-out=json
Убедитесь, что все 3 участника видят друг друга и кворум есть. В продакшене дополнительно включите TLS и задайте пользователи/роли в etcd.
Конфигурация Patroni и PostgreSQL
Patroni запускает PostgreSQL, следит за здоровьем, управляет репликацией и переключениями. Базовый сценарий: один файл YAML на узел с общим блоком dcs и индивидуальными параметрами (имя узла, адреса). В bootstrap задаются опции initdb, а также первичный pg_hba.conf.
# /etc/patroni/node1.yml
scope: pg-ha
namespace: "/service/"
name: node1
restapi:
listen: 0.0.0.0:8008
connect_address: 10.0.0.11:8008
dcs:
ttl: 10
loop_wait: 5
retry_timeout: 10
maximum_lag_on_failover: 16MB
postgresql:
use_pg_rewind: true
use_slots: true
parameters:
wal_level: replica
hot_standby: on
max_wal_senders: 10
max_replication_slots: 10
wal_keep_size: 256MB
synchronous_commit: off
etcd:
host: 10.0.0.11:2379,10.0.0.12:2379,10.0.0.13:2379
bootstrap:
dcs:
synchronous_mode: false
initdb:
- encoding: UTF8
- data-checksums
pg_hba:
- host replication repl 10.0.0.0/24 md5
- host all all 10.0.0.0/24 md5
postgresql:
listen: 0.0.0.0:5432
connect_address: 10.0.0.11:5432
data_dir: /var/lib/postgresql/16/main
bin_dir: /usr/lib/postgresql/16/bin
authentication:
replication:
username: repl
password: STRONG_REPL_PASSWORD
superuser:
username: postgres
password: STRONG_POSTGRES_PASSWORD
tags:
nofailover: false
noloadbalance: false
clonefrom: false
nosync: false
На остальных узлах меняются только name, connect_address, пути и адреса. Убедитесь, что каталог данных пуст на старте первого кластера, либо используйте механизмы join/rewind.
Ключевые моменты:
ttl/loop_wait/retry_timeoutопределяют скорость детекции отказа и переизбрания лидера. Чем агрессивнее — тем выше риск ложных срабатываний при jitter. Начните с консервативных значений и тестируйте.maximum_lag_on_failoverограничивает отставание кандидата при аварийном failover. Это ваш RPO-ограничитель.use_pg_rewindпомогает безопасно возвращать бывшего лидера в реплики после failover, если включеныdata-checksumsи есть нужные WAL.use_slotsдержит репликационные слоты, чтобы WAL не удалялись преждевременно. Следите за ростом WAL при недоступных репликах.- Синхронная репликация: включите
synchronous_mode: true, если критично нулевое RPO, но учтите задержки и риски стопора при потере синхронного стендбая. Режимsynchronous_mode_strictещё жёстче — применяйте осознанно.
Запуск и порядок включения
Порядок: сначала DCS (etcd), затем Patroni на каждом узле. На первом запуске Patroni инициализирует кластер, поднимет лидера, остальные узлы склонируются и станут репликами. Проверьте REST-статусы и список узлов.
sudo systemctl enable --now patroni
patronictl -c /etc/patroni/node1.yml list
Репликация и сценарии переключений
Patroni управляет потоковой репликацией PostgreSQL и переключениями ролей:
- Switchover — плановая смена лидера без потери данных. Используется для обновлений, обслуживания и балансировки.
- Failover — аварийное переключение при недоступности лидера (по TTL на DCS). Возможна потеря последних транзакций в асинхронном режиме.
Команды администратора:
# Плановая смена лидера на указанный узел
patronictl -c /etc/patroni/node1.yml switchover --master node1 --candidate node2
# Принудительный failover (когда лидер недоступен)
patronictl -c /etc/patroni/node2.yml failover --candidate node2
# Снятие с узла права участвовать в failover
patronictl -c /etc/patroni/node3.yml edit-config
В асинхронной схеме ставьте реалистичный maximum_lag_on_failover, чтобы не переключиться на далёко отставшую реплику. В синхронной схеме контролируйте состав синхронных стендбаев и влияние на латентность запросов.
Подключение клиентов: виртуальный адрес или прокси
Клиенты должны всегда попадать на текущего лидера. Типовые варианты:
- Виртуальный IP (VRRP/keepalived) — простой способ, когда сеть позволяет перемещать адрес между узлами.
- TCP-прокси (HAProxy, nginx stream) — проксирование на активного лидера. Узнать лидера можно по REST Patroni или меткам DCS.
- Пулеры (PgBouncer) — актуально для большого числа соединений; пулинг совмещают с логикой выбора лидера.
Если используете прокси, предусмотрите health-check к REST Patroni (порт 8008) с проверкой, что узел лидер. При VRRP гарантируйте быстрый перенос IP при switchover. По пулерам см. практики из материала «Руководство по PgBouncer и пулингу соединений» — это помогает снизить нагрузку на Postgres и ускорить переключения: PgBouncer: пулинг соединений для PostgreSQL.

Тестирование отказоустойчивости
Не выводите в прод без дотошных испытаний. Прогоны, которые надо сделать:
- Остановка PostgreSQL на лидере и проверка автоматического failover.
- Обрыв сети между лидером и DCS (симуляция изоляции лидера).
- Потеря узла DCS и проверка поведения при деградации кворума.
- Плановый switchover под нагрузкой и оценка паузы для клиента.
Настройте логирование Patroni и PostgreSQL так, чтобы видеть детальные причины переключения. Отдельно измерьте суммарное время: детекция отказа (TTL), выбор кандидата, запуск/поднятие ролей, перестройка прокси/VIP.
Производительность и типичные ловушки
Несколько практических советов:
- WAL и задержки. Убедитесь, что хранилище держит нужный IOPS для WAL и что
wal_keep_sizeхватает на окна недоступности реплик. Следите за ростом каталога WAL при отвалившихся репликах с включёнными слотами. - Синхрон против асинхрон. Синхронная репликация даёт минимальное RPO ценой латентности и риском стопора при потере синхронного участника. Взвесьте требования SLA и бюджет.
- Таймауты Patroni. Слишком агрессивные значения
ttlиloop_waitпри нестабильной сети приводят к ложным failover. Начинайте с 10/5/10 и снижайте только после тестов. - Split-brain. Не запускайте DCS в 2 узла. Следите за временем: без корректной синхронизации часов TTL теряет смысл.
- pg_rewind. Работает не всегда: если окно WAL слишком узкое или реплика сильно отставала. Иметь проверенный план re-provision реплики быстрее и надёжнее.
Обновления и обслуживание
Минорные обновления PostgreSQL и конфигурационные изменения делайте покаскадно: switchover на реплику, обновление бывшего лидера, возврат роли — и так по кругу. Patroni поддерживает rolling restart с контролируемыми паузами.
Мажорные апгрейды планируйте заранее: pg_upgrade с недолгой паузой или логическая репликация между кластерами разных версий. До начала — полный бэкап, валидация восстановления и тестовый апгрейд «в песочнице».
Безопасность: от DCS до клиентов
Минимальные требования:
- Шифруйте трафик DCS (TLS) и включайте аутентификацию пользователей/ролей.
- Ограничьте Patroni REST API по сети и используйте базовую аутентификацию.
- В PostgreSQL настройте
pg_hba.confтолько на нужные подсети, применяйте SCRAM, разделяйте роли (репликация, приложения, администрирование). - Храните секреты вне репозиториев, применяйте ротацию паролей и аудит соединений.
- Журналируйте доступы к DCS и Postgres, храните логи в централизованной системе.
Резервное копирование
HA — не замена бэкапам. Настройте регулярные горячие резервные копии и архивирование WAL (например, в объектное хранилище), периодически проводите восстановление на выделённом стенде. В кластере с Patroni удобно запускать бэкапы с реплики, чтобы снизить влияние на лидера, но восстановление тестируйте на той версии и с теми параметрами, что в проде. Подробности по PITR и архивированию WAL — в материале PITR, WAL и восстановление PostgreSQL.
Наблюдаемость и эксплуатация
Набор наблюдаемости:
- Список узлов и роли:
patronictl list. - REST Patroni: статусы, роль, lag — для health-check и дашбордов.
- Метрики PostgreSQL: экспортёр, лаг репликации, чекпойнты, бэкграунд-автовакуум.
- Мониторинг DCS: состояние кворума, задержки, лидер.
Заведите алерты на: потерю кворума DCS, отставание реплик выше порога, частые переключения лидера, переполнение WAL, отказ бэкапов.
Мини-чеклист перед релизом
Продублируйте этот список в runbook и отработайте на тестовом кластере до автоматизма.
- DCS в 3 узла, проверен кворум, включены TLS и аутентификация.
- Patroni: адекватные
ttl,loop_wait,maximum_lag_on_failover, включёнuse_pg_rewind. - Репликация стабильна, lag в норме, слоты управляются, WAL не растут без контроля.
- Путь клиента к лидеру оттестирован (VIP/прокси), health-check корректен.
- Есть валидированные бэкапы, PITR проверен, есть план re-provision реплики.
- Ограничены порты, настроены роли, аудит и экспорт метрик.
- Отработаны сценарии switchover/failover под нагрузкой.
Итоги
Patroni с DCS (etcd или Consul) даёт предсказуемую, управляемую HA для PostgreSQL на VDS. Ключ к успеху — трезвые настройки таймаутов, аккуратная сеть, дисциплина бэкапов и мониторинга, а также регулярные тренировки сценариев отказа. Начните с трёх узлов, держите конфигурации под управлением, валидируйте каждый шаг и вы получите кластер, который действительно выдерживает сбои без сюрпризов.


