Представь, что твоя PostgreSQL база данных внезапно падает в самый неподходящий момент. Реплика не переключается автоматически, админы спят, а пользователи в ярости. Знакомая ситуация? Давай разберем, как Patroni решает эту проблему, превращая твою БД в самовосстанавливающийся организм.
Что такое Patroni и зачем он нужен?
Patroni — это шаблон для создания высокодоступных кластеров PostgreSQL. Он управляет автоматическим переключением (failover), мониторингом состояния и конфигурацией всех узлов кластера. В отличие от стандартной репликации, Patroni обеспечивает:
- Автоматический failover без вмешательства человека
- Централизованное управление конфигурацией через распределенное хранилище (Consul, etcd, ZooKeeper)
- Интеграцию с системами балансировки нагрузки (HAProxy, Keepalived)
- Восстановление вышедших из строя реплик
Архитектура кластера Patroni PostgreSQL
Типичный кластер состоит из:
| Роль | Количество | Описание |
|---|---|---|
| Leader/Master | 1 | Единственный узел, принимающий запись |
| Replica/Standby | 1-N | Узлы только для чтения, готовые стать мастером |
| DCS (Distributed Config Store) | 3 или 5 | Consul, etcd или ZooKeeper для координации |
Пошаговая настройка Patroni PostgreSQL кластера
Шаг 1: Подготовка окружения
Установи необходимые пакеты на всех узлах (предполагаем Ubuntu/Debian):
# Установка PostgreSQL и Patroni
sudo apt update
sudo apt install -y postgresql-15 postgresql-client-15 python3-pip
sudo pip3 install patroni[etcd] # или patroni[consul], patroni[zookeeper]
# Установка etcd (для DCS)
sudo apt install -y etcd
# Или Consul
# wget https://releases.hashicorp.com/consul/1.15.0/consul_1.15.0_linux_amd64.zip
Шаг 2: Настройка DCS (на примере etcd)
Запусти etcd кластер на трех узлах. Конфиг для первого узла:
# /etc/etcd/etcd.conf.yml на node1
name: 'etcd-node1'
data-dir: /var/lib/etcd
listen-client-urls: http://0.0.0.0:2379
advertise-client-urls: http://node1:2379
initial-cluster: 'etcd-node1=http://node1:2380,etcd-node2=http://node2:2380,etcd-node3=http://node3:2380'
initial-cluster-token: 'patroni-cluster'
initial-cluster-state: 'new'
Шаг 3: Конфигурация Patroni
Создай основной конфигурационный файл Patroni. Вот пример для первого PostgreSQL узла:
# /etc/patroni/patroni.yml на node1
scope: postgres-cluster # Имя кластера
namespace: /service/ # Путь в DCS
name: postgresql-node1 # Уникальное имя узла
restapi:
listen: 0.0.0.0:8008
connect_address: 192.168.1.101:8008 # IP этого узла
etcd:
hosts:
- 192.168.1.101:2379
- 192.168.1.102:2379
- 192.168.1.103:2379
bootstrap:
dcs:
ttl: 30
loop_wait: 10
retry_timeout: 10
maximum_lag_on_failover: 1048576
postgresql:
use_pg_rewind: true
use_slots: true
parameters:
wal_level: replica
hot_standby: "on"
wal_keep_size: 1024MB
max_wal_senders: 10
max_replication_slots: 10
wal_log_hints: "on"
initdb:
- encoding: UTF8
- locale: en_US.UTF-8
- data-checksums
pg_hba:
- host replication replicator 192.168.1.0/24 md5
- host all all 0.0.0.0/0 md5
postgresql:
listen: 0.0.0.0:5432
connect_address: 192.168.1.101:5432
data_dir: /var/lib/postgresql/15/main
pgpass: /tmp/pgpass
authentication:
replication:
username: replicator
password: "StrongPassword123"
superuser:
username: postgres
password: "PostgresAdmin456"
parameters:
unix_socket_directories: '/var/run/postgresql'
tags:
nofailover: false
noloadbalance: false
clonefrom: false
nosync: false
Шаг 4: Запуск и инициализация кластера
Запусти Patroni на первом узле (он станет мастером):
# Создай директорию для данных PostgreSQL
sudo mkdir -p /var/lib/postgresql/15/main
sudo chown postgres:postgres /var/lib/postgresql/15/main
# Запусти Patroni
sudo -u postgres patroni /etc/patroni/patroni.yml
# Или как systemd служба (рекомендуется)
sudo systemctl enable patroni
sudo systemctl start patroni
Проверь статус кластера:
# Запрос к REST API Patroni
curl http://192.168.1.101:8008/patroni
# Или через patronictl
patronictl -c /etc/patroni/patroni.yml list
# Пример вывода:
# +---------------------+-----------+--------------+--------+---------+-----------+
# | Cluster | Member | Host | Role | State | Lag in MB |
# +---------------------+-----------+--------------+--------+---------+-----------+
# | postgres-cluster | node1 | 192.168.1.101| Leader | running | |
# +---------------------+-----------+--------------+--------+---------+-----------+
Шаг 5: Добавление реплик в кластер
На втором узле создай аналогичный конфиг, изменив только имя и адреса:
# /etc/patroni/patroni.yml на node2
name: postgresql-node2 # Уникальное имя!
restapi:
listen: 0.0.0.0:8008
connect_address: 192.168.1.102:8008 # IP второго узла
# etcd и остальные секции как на node1
# НЕ включай блок bootstrap на репликах!
postgresql:
listen: 0.0.0.0:5432
connect_address: 192.168.1.102:5432
data_dir: /var/lib/postgresql/15/main
# Остальное как на node1
Запусти Patroni на втором узле — он автоматически подтянет данные с мастера:
# На node2
sudo -u postgres patroni /etc/patroni/patroni.yml
# Проверь, что реплика добавилась
patronictl -c /etc/patroni/patroni.yml list
# Теперь должно быть два узла:
# | postgres-cluster | node1 | 192.168.1.101 | Leader | running | |
# | postgres-cluster | node2 | 192.168.1.102 | Replica| running | 0.0 MB |
Управление кластером Patroni
Основные команды patronictl
# Просмотр состояния кластера
patronictl -c /etc/patroni/patroni.yml list
# Переключение ролей (manual failover)
patronictl -c /etc/patroni/patroni.yml failover
# Перезагрузка кластера
patronictl -c /etc/patroni/patroni.yml restart postgres-cluster
# Просмотр истории переключений
patronictl -c /etc/patroni/patroni.yml history
# Репликация с задержкой (для защиты от человеческих ошибок)
patronictl -c /etc/patroni/patroni.yml edit-config
# Добавь в tags: clonefrom: true
Интеграция с HAProxy для балансировки
Настрой HAProxy для автоматического направления запросов на мастер (запись) и реплики (чтение):
# /etc/haproxy/haproxy.cfg
frontend postgres_frontend
bind *:5000
mode tcp
option tcplog
default_backend postgres_master
backend postgres_master
mode tcp
balance roundrobin
option tcp-check
tcp-check connect port 5432
tcp-check send PGBACKEND\x00\x00\x00\x0C\x00\x00\x00\x00\x00\x00\x00\x00\x00
tcp-check expect string backend
server node1 192.168.1.101:5432 check
server node2 192.168.1.102:5432 check backup
backend postgres_replicas
mode tcp
balance roundrobin
option tcp-check
tcp-check connect port 5432
server node2 192.168.1.102:5432 check
# Добавь другие реплики
Мониторинг и логирование
Настрой мониторинг ключевых метрик:
- Lag реплики: Отставание в байтах/секундах
- Состояние DCS: Доступность etcd/Consul
- Количество подключений: К мастеру и репликам
- Дисковое пространство: На всех узлах
# Проверка лага через Patroni API
curl -s http://192.168.1.102:8008/patroni | jq '.xlog.receive_lag'
# Проверка роли узла
curl -s http://192.168.1.101:8008/patroni | jq '.role'
Частые вопросы (FAQ)
Как Patroni определяет, какой узел должен быть мастером?
Patroni использует алгоритм лидера на основе DCS (Distributed Configuration Store). Узел, который успешно захватывает "lease" (временную блокировку) в DCS, становится мастером. Если мастер теряет связь с DCS или падает, блокировка освобождается, и другой узел может её захватить.
Что происходит при сетевом разрыве между узлами?
При split-brain (разделении мозга) Patroni полагается на DCS. Если мастер теряет связь с DCS, он демотивируется. Узлы, сохранившие связь с DCS, выбирают нового мастера. Важно иметь нечетное количество узлов DCS для избежания неопределенности.
Можно ли настроить Patroni без DCS?
Нет, DCS — обязательный компонент. Он обеспечивает распределенный консенсус и координацию между узлами. Без DCS невозможна корректная работа failover и избежание split-brain ситуаций.
Как обновить PostgreSQL на кластере с Patroni?
Проводи rolling update: обновляй реплики по одной, затем выполни ручной failover на обновленную реплику, обнови старый мастер. Patroni поддерживает разные версии PostgreSQL во время обновления, но минимальное время — только на период failover.
Лучшие практики настройки
- Тестируй failover: Регулярно имитируй сбои в тестовой среде
- Мониторинг DCS: etcd/Consul должны быть стабильнее, чем PostgreSQL
- Резервное копирование: Patroni не заменяет бэкапы! Настрой pgBackRest или Barman
- Тюнинг параметров: Настрой
wal_keep_size,max_wal_sendersпод свою нагрузку - Документация: Задокументируй процедуры аварийного восстановления
Настройка Patroni PostgreSQL кластера — это инвестиция в стабильность твоего приложения. Потрать время на тестирование, настройку мониторинга и создание документации. Когда кластер заработает, ты забудешь о ночных вызовах из-за падения БД и сможешь спать спокойно, зная, что Patroni присмотрит за твоими данными.