Patroni PostgreSQL настройка кластера: пошаговая инструкция | AdminWiki

Patroni PostgreSQL настройка: полное руководство по созданию отказоустойчивого кластера

17 декабря 2025 7 мин. чтения #devops #high availability #patroni #postgresql #базы данных #кластер #настройка

Представь, что твоя PostgreSQL база данных внезапно падает в самый неподходящий момент. Реплика не переключается автоматически, админы спят, а пользователи в ярости. Знакомая ситуация? Давай разберем, как Patroni решает эту проблему, превращая твою БД в самовосстанавливающийся организм.

Что такое Patroni и зачем он нужен?

Patroni — это шаблон для создания высокодоступных кластеров PostgreSQL. Он управляет автоматическим переключением (failover), мониторингом состояния и конфигурацией всех узлов кластера. В отличие от стандартной репликации, Patroni обеспечивает:

  • Автоматический failover без вмешательства человека
  • Централизованное управление конфигурацией через распределенное хранилище (Consul, etcd, ZooKeeper)
  • Интеграцию с системами балансировки нагрузки (HAProxy, Keepalived)
  • Восстановление вышедших из строя реплик
Важно: Patroni не заменяет встроенную репликацию PostgreSQL, а надстраивается над ней, добавляя оркестрацию и автоматизацию.

Архитектура кластера Patroni PostgreSQL

Типичный кластер состоит из:

Роль Количество Описание
Leader/Master 1 Единственный узел, принимающий запись
Replica/Standby 1-N Узлы только для чтения, готовые стать мастером
DCS (Distributed Config Store) 3 или 5 Consul, etcd или ZooKeeper для координации

Пошаговая настройка Patroni PostgreSQL кластера

Шаг 1: Подготовка окружения

Установи необходимые пакеты на всех узлах (предполагаем Ubuntu/Debian):

bash
# Установка 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 кластер на трех узлах. Конфиг для первого узла:

yaml
# /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'
Опасно: Не используй etcd в production без TLS! Это пример для тестовой среды. В production обязательно настрой аутентификацию и шифрование.

Шаг 3: Конфигурация Patroni

Создай основной конфигурационный файл Patroni. Вот пример для первого PostgreSQL узла:

yaml
# /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 на первом узле (он станет мастером):

bash
# Создай директорию для данных 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

Проверь статус кластера:

bash
# Запрос к 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: Добавление реплик в кластер

На втором узле создай аналогичный конфиг, изменив только имя и адреса:

yaml
# /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 на втором узле — он автоматически подтянет данные с мастера:

bash
# На 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

bash
# Просмотр состояния кластера
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 для автоматического направления запросов на мастер (запись) и реплики (чтение):

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
  • Количество подключений: К мастеру и репликам
  • Дисковое пространство: На всех узлах
bash
# Проверка лага через 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 под свою нагрузку
  • Документация: Задокументируй процедуры аварийного восстановления
Профессиональный совет: Начни с тестового кластера из 3 узлов (1 мастер + 2 реплики) и 3 узлов etcd. Только после полного тестирования всех сценариев переходи на production.

Настройка Patroni PostgreSQL кластера — это инвестиция в стабильность твоего приложения. Потрать время на тестирование, настройку мониторинга и создание документации. Когда кластер заработает, ты забудешь о ночных вызовах из-за падения БД и сможешь спать спокойно, зная, что Patroni присмотрит за твоими данными.

Поделиться:
Сохранить гайд? В закладки браузера