Руководство по настройке реплик базы данных через Patroni

Содержание

Руководство по настройке реплик базы данных через Patroni#

Назначение#

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

Аудитория#

Руководство предназначено для системных администраторов и администраторов баз данных, отвечающих за развертывание и поддержку высокодоступных кластеров PostgreSQL в production-среде.

Архитектура решения#

Архитектура решения

Предварительные требования#

Аппаратные требования#

  • 3 сервера БД с минимум 4 CPU, 4GB RAM, 50GB SSD каждый.

  • Сетевые требования: стабильная сеть с задержкой < 1ms между узлами.

  • Дополнительный сервер для HAProxy (может быть виртуальной машиной).

Совет

Перед настройкой репликации стоит сделать дамп базы данных

Программные требования#

  • ОС: Debian 12.

  • PostgreSQL 17.

  • Доступ: права sudo на всех серверах.

  • Сеть: открытые порты между узлами:

    • 5432 (PostgreSQL).

    • 8008 (Patroni API).

    • 2379 (etcd client).

    • 2380 (etcd peer).

Общие настройки для всех узлов PostgreSQL:#

  • Версия PostgreSQL: 17.

  • Имя базы данных: replicatest.

  • Пользователь для репликации: replicator.

  • Пароль для репликации: StrongPassword123!.

  • Пользователь PostgreSQL: postgres.

  • Пароль пользователя PostgreSQL: 12345.

  • Пользователь БД: global.

  • Пароль пользователя БД: globalpass.

IP-адреса узлов:#

  • Основной сервер БД (primaryDB): 192.168.184.151.

  • Реплика 1 (replica1): 192.168.184.152.

  • Реплика 2 (replica2): 192.168.184.153.

  • Сервер HAProxy(haproxy_host): 192.168.184.129.

Примечание

В реальной системе рекомендуется использовать сложные пароли и безопасное их хранение.

Этап 1: Подготовка всех узлов#

На узлах 2 и 3 (репликах) выполняем:

# Обновление системы и установка базовых пакетов
sudo apt update && sudo apt upgrade -y
sudo apt install -y curl wget vim htop net-tools

# Установка PostgreSQL 17
sudo apt install -y postgresql-17 postgresql-client-17 postgresql-server-dev-17

# Останавливаем стандартный PostgreSQL, так как Patroni будет управлять им
sudo systemctl stop postgresql
sudo systemctl disable postgresql

На узле 1 (существующая БД) выполняем только установку зависимостей:

sudo apt update && sudo apt upgrade -y
sudo apt install -y curl wget vim htop net-tools python3-pip python3-dev patroni 

Примечание

Стандартная служба Postgresql конфликтует с Patroni, поэтому мы ее отключаем.

Подготовка существующей БД на узле 1#

На узле 1 (существующая БД) выполняем подготовку:

# Создаем пользователя репликации в существующей БД
sudo -u postgres psql -c "CREATE USER replicator WITH REPLICATION LOGIN PASSWORD 'StrongPassword123!';"

# Создаем пользователя приложения если его нет
sudo -u postgres psql -c "CREATE USER global WITH PASSWORD 'globalpass' CREATEDB CREATEROLE LOGIN;"

# Создаем базу данных если ее нет
sudo -u postgres psql -c "CREATE DATABASE replicatest OWNER global;"
# Останавливаем PostgreSQL для подготовки
sudo systemctl stop postgresql

# Настраиваем параметры репликации в postgresql.conf
sudo sed -i "s/#wal_level = replica/wal_level = replica/" /etc/postgresql/17/main/postgresql.conf
sudo sed -i "s/#max_wal_senders = 10/max_wal_senders = 20/" /etc/postgresql/17/main/postgresql.conf
sudo sed -i "s/#max_replication_slots = 10/max_replication_slots = 20/" /etc/postgresql/17/main/postgresql.conf
sudo sed -i "s/#hot_standby = on/hot_standby = on/" /etc/postgresql/17/main/postgresql.conf

# Добавляем синхронную репликацию
echo "synchronous_commit = remote_apply" | sudo tee -a /etc/postgresql/17/main/postgresql.conf
echo "synchronous_standby_names = 'ANY 1 (replica1, replica2)'" | sudo tee -a /etc/postgresql/17/main/postgresql.conf

# Настраиваем pg_hba.conf для репликации
sudo tee -a /etc/postgresql/17/main/pg_hba.conf > /dev/null << EOF
# Local connections
host all postgres 127.0.0.1/32 trust

# TYPE   DATABASE       USER    ADDRESS               METHOD
# Разрешить подключения от HAProxy/сервера приложений к основной базе и репликам для приложения
host    replicatest    global   192.168.184.129/32    scram-sha-256
host all all all scram-sha-256

EOF

# Перезапускаем PostgreSQL для применения настроек
sudo systemctl start postgresql

Этап 2: Настройка etcd кластера#

На узле 1 (192.168.184.151):

# Установка etcd
sudo apt install -y etcd-server etcd-client

# Создание директорий
sudo mkdir -p /etc/etcd /var/lib/etcd
sudo chown etcd:etcd /var/lib/etcd

# Создание конфигурации etcd
sudo tee /etc/etcd/etcd.conf > /dev/null << EOF
ETCD_NAME="etcd1"
ETCD_DATA_DIR="/var/lib/etcd"
ETCD_LISTEN_PEER_URLS="http://192.168.184.151:2380"
ETCD_LISTEN_CLIENT_URLS="http://192.168.184.151:2379,http://127.0.0.1:2379"
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://192.168.184.151:2380"
ETCD_ADVERTISE_CLIENT_URLS="http://192.168.184.151:2379"
ETCD_INITIAL_CLUSTER="etcd1=http://192.168.184.151:2380,etcd2=http://192.168.184.152:2380,etcd3=http://192.168.184.153:2380"
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster-patroni"
ETCD_INITIAL_CLUSTER_STATE="new"
EOF

На узле 2 (192.168.184.152):

sudo apt install -y etcd-server etcd-client
sudo mkdir -p /etc/etcd /var/lib/etcd
sudo chown etcd:etcd /var/lib/etcd

sudo tee /etc/etcd/etcd.conf > /dev/null << EOF
ETCD_NAME="etcd2"
ETCD_DATA_DIR="/var/lib/etcd"
ETCD_LISTEN_PEER_URLS="http://192.168.184.152:2380"
ETCD_LISTEN_CLIENT_URLS="http://192.168.184.152:2379,http://127.0.0.1:2379"
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://192.168.184.152:2380"
ETCD_ADVERTISE_CLIENT_URLS="http://192.168.184.152:2379"
ETCD_INITIAL_CLUSTER="etcd1=http://192.168.184.151:2380,etcd2=http://192.168.184.152:2380,etcd3=http://192.168.184.153:2380"
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster-patroni"
ETCD_INITIAL_CLUSTER_STATE="new"
EOF

На узле 3 (192.168.184.153):

sudo apt install -y etcd-server etcd-client
sudo mkdir -p /etc/etcd /var/lib/etcd  
sudo chown etcd:etcd /var/lib/etcd

sudo tee /etc/etcd/etcd.conf > /dev/null << EOF
ETCD_NAME="etcd3"
ETCD_DATA_DIR="/var/lib/etcd"
ETCD_LISTEN_PEER_URLS="http://192.168.184.153:2380"
ETCD_LISTEN_CLIENT_URLS="http://192.168.184.153:2379,http://127.0.0.1:2379"
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://192.168.184.153:2380"
ETCD_ADVERTISE_CLIENT_URLS="http://192.168.184.153:2379"
ETCD_INITIAL_CLUSTER="etcd1=http://192.168.184.151:2380,etcd2=http://192.168.184.152:2380,etcd3=http://192.168.184.153:2380"
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster-patroni"
ETCD_INITIAL_CLUSTER_STATE="new"
EOF

Запуск etcd на всех узлах:

# На всех трех узлах выполняем:
sudo systemctl enable etcd
sudo systemctl start etcd

# Проверяем статус кластера etcd
etcdctl member list
etcdctl endpoint health --cluster

Должен вывести:

ac2480c22a0201, started, etcd1, http://192.168.184.151:2380, http://192.168.184.151:2379, false
211aa8676d12183b, started, etcd2, http://192.168.184.152:2380, http://192.168.184.152:2379, false
3c7bdfe2b29d8461, started, etcd3, http://192.168.184.153:2380, http://192.168.184.153:2379, false
http://192.168.184.151:2379 is healthy: successfully committed proposal: took = 2.27669ms
http://192.168.184.153:2379 is healthy: successfully committed proposal: took = 4.62381ms
http://192.168.184.152:2379 is healthy: successfully committed proposal: took = 3.810392ms

Этап 3: Установка и настройка Patroni#

На всех узлах устанавливаем Patroni:

# Установка Python и Patroni
sudo apt install -y python3-pip python3-dev patroni

## Создание пользователя и директорий для Patroni
sudo useradd --system --home /var/lib/patroni patroni
sudo mkdir -p /var/lib/patroni /var/log/patroni /etc/patroni
sudo chown patroni:patroni /var/lib/patroni /var/log/patroni

Конфигурация Patroni. Заменить node-name на имя ноды, заменить node_ip на адрес ноды /etc/patroni/config.yml:

scope: postgres-cluster
namespace: /db/
name: node1

restapi:
  listen: 0.0.0.0:8008
  connect_address: 192.168.184.151:8008

etcd3:
  hosts: 192.168.184.151:2379,192.168.184.152:2379,192.168.184.153: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: 128MB
        max_wal_senders: 20
        max_replication_slots: 20
        max_connections: 100

  initdb:
  - encoding: UTF8
  - data-checksums

  pg_hba:
  - host replication replicator 127.0.0.1/32 scram-sha-256
  - host replication replicator 192.168.184.0/24 scram-sha-256
  - host all all 0.0.0.0/0 scram-sha-256

  users:
    admin:
      password: "adminpass"
      options:
        - createrole
        - createdb
    replicator:
      password: "StrongPassword123!"
      options:
        - replication

postgresql:
  listen: 0.0.0.0:5432
  connect_address: 192.168.184.151:5432
  data_dir: /var/lib/postgresql/17/main
  bin_dir: /usr/lib/postgresql/17/bin
  authentication:
    replication:
      username: replicator
      password: "StrongPassword123!"
    superuser:
      username: postgres
      password: "12345"
    global:
      username: global
      password: "globalpass"

tags:
  nofailover: false
  noloadbalance: false
  clonefrom: false
  nosync: false

Создание systemd службы для Patroni на всех узлах - /etc/systemd/system/patroni.service:

[Unit]
Description=Patroni PostgreSQL High Availability
After=syslog.target network.target

[Service]
Type=simple
User=postgres
Group=postgres
ExecStart=/usr/bin/patroni /etc/patroni/config.yml
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
TimeoutSec=30
Restart=no
WorkingDirectory=/var/lib/postgresql

[Install]
WantedBy=multi-user.target

Запуск Patroni на всех узлах:

# На всех трех узлах выполняем:
sudo systemctl daemon-reload
sudo systemctl enable patroni
# На узле 1 останавливаем стандартный PostgreSQL и запускаем Patroni
sudo systemctl stop postgresql
sudo systemctl start patroni
# Ждем 30 секунд для инициализации primary, затем на узлах 2 и 3:
sudo systemctl start patroni

# Проверяем статус
sudo systemctl status patroni

Проверка работы кластера:

# Выполняем на любом узле
patronictl -c /etc/patroni/config.yml list

# Проверяем подключение к базе данных replicatest
psql -h 192.168.184.151 -U global -d replicatest -c "SELECT current_user, current_database();"

Ожидаемый результат:

patronictl -c /etc/patroni/config.yml list
+ Cluster: postgres-cluster (7561473146679687463) ----+-----------+
| Member | Host            | Role    | State     | TL | Lag in MB |
+--------+-----------------+---------+-----------+----+-----------+
| node1  | 192.168.184.151 | Leader  | running   |  2 |           |
| node2  | 192.168.184.152 | Replica | streaming |  2 |         0 |
| node3  | 192.168.184.153 | Replica | streaming |  2 |         0 |
+--------+-----------------+---------+-----------+----+-----------+

При возникновении ошибок#

Можно удалить pg_hba.conf на мастер ноде patroni создаст его при запуске. На будущих репликах можно очистить данные postgresql.

sudo rm -rf /var/lib/postgresql/17/main
sudo mkdir -p /var/lib/postgresql/17/main
sudo chown -R postgres:postgres /var/lib/postgresql/17/
sudo chmod 700 /var/lib/postgresql/17/main

Также стоит проверить хранилище ключей etcd, очистить его перед повторным запуском

Этап 4: Настройка HAProxy#

Установка HAProxy:

sudo apt install -y haproxy

Конфигурация HAProxy /etc/haproxy/haproxy.cfg:

global
    log /dev/log local0
    log /dev/log local1 notice
    chroot /var/lib/haproxy
    stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
    stats timeout 30s
    user haproxy
    group haproxy
    daemon
    ssl-server-verify none

defaults
    log global
    mode tcp
    option tcplog
    option dontlognull
    timeout connect 5000
    timeout client 50000
    timeout server 50000
    errorfile 400 /etc/haproxy/errors/400.http
    errorfile 403 /etc/haproxy/errors/403.http
    errorfile 408 /etc/haproxy/errors/408.http
    errorfile 500 /etc/haproxy/errors/500.http
    errorfile 502 /etc/haproxy/errors/502.http
    errorfile 503 /etc/haproxy/errors/503.http
    errorfile 504 /etc/haproxy/errors/504.http

# Frontend для клиентских подключений (чтение и запись на primary)
frontend postgres_primary_rw
    bind *:5000
    default_backend postgresql_nodes  # Исправлено имя бэкенда

backend postgresql_nodes
    mode tcp
    # Проверка состояния серверов
    option httpchk GET /master
    # Является ли праймари, patromni на 8008 ответит 200 если праймари
    http-check expect status 200

    # Все сервера базы данных с уникальными именами
    server postgres1 192.168.184.151:5432 check port 8008
    server postgres2 192.168.184.152:5432 check port 8008  
    server postgres3 192.168.184.153:5432 check port 8008 

# Статистика HAProxy
listen stats
    bind *:7000
    mode http
    stats enable
    stats uri /
    stats refresh 5s
    stats auth admin:1234

Запуск HAProxy:

# Проверка конфигурации
sudo haproxy -c -f /etc/haproxy/haproxy.cfg

# Запуск службы
sudo systemctl enable haproxy
sudo systemctl restart haproxy

Проверка работы:

# Проверка подключения через HAProxy к primary (чтение/запись)
psql -h haproxy_host -p 5000 -U global -d replicatest -c "
SELECT 
    inet_server_addr() as connected_to,
    pg_is_in_recovery() as is_replica,
    current_database() as database;"

Проверка работы статистики:

Pasted

Как это работает: HAProxy каждую секунду проверяет кто из серверов сейчас является мастером, использую запросы к Patroni. И перенаправляет подключение к мастер серверу

Настройка GlobalServer#

Вставить в global3.config.xml в раздел <databases>

<database alias="replica_haproxy" driver="org.postgresql.Driver" schema="PUBLIC"
		url="jdbc:postgresql://haproxy_host:5000/replicatest"
		connectionType="proxyShared" authenticationType="btk">
		<users>
				<user name="global" password="globalpass"/>
		</users>
		<metaManager
				mode="Xml"
				defaultNamespace="ru.bitec.app.btk"
				sbtName="main"
		/>
		<eclipseLink
				persistenceUnitName="pgdev"
				autoCommit="false"
		/>
</database>

Подключение через DBeaver#

Подключение к Primary (чтение/запись)#

  1. Создайте новое подключение в DBeaver:

    • Тип БД: PostgreSQL.

    • Хост: IP-адрес HAProxy сервера.

    • Порт: 5000 (для чтения/записи).

    • База данных: replicatest (или ваша БД).

    • Пользователь: global.

    • Пароль: globalpass.

  2. Проверка подключения:

    • Нажмите «Test Connection».

    • Должен отобразиться текущий primary узел.

Проверка работы подключений#

В подключении к порту 5000 выполните:

-- Проверка, что это primary
SELECT 
    inet_server_addr() as connected_to,
    pg_is_in_recovery() as is_replica,
    current_user as current_user;

-- Тест записи (должен работать)
CREATE TABLE IF NOT EXISTS aaa_test_connection (id SERIAL, note TEXT);
INSERT INTO test_connection (note) VALUES ('Тест записи через порт 5000');

Настройка мониторинга в DBeaver#

  1. Включите отображение hostname в статусе подключения:

    • Правый клик на подключении → «Редактировать подключение».

    • Вкладка «PostgreSQL» → «Показать имя базы данных и hostname в дереве».

  2. Создайте дашборд для мониторинга:

    • Используйте следующие запросы для отслеживания состояния:

-- Мониторинг репликации (выполнять на primary подключении)
SELECT 
    application_name,
    client_addr,
    state,
    sync_state,
    write_lag,
    flush_lag,
    replay_lag
FROM pg_stat_replication;

-- Мониторинг активности (на любом подключении)
SELECT 
    datname,
    usename,
    application_name,
    client_addr,
    state,
    query_start,
    query
FROM pg_stat_activity 
WHERE state = 'active' 
AND datname IS NOT NULL;

Проверка работы кластера#

Проверка состояния Patroni кластера#

# Выполняем на любом узле
patronictl -c /etc/patroni/config.yml list

Ожидаемый результат:

+ Cluster: postgres-cluster (7561473146679687463) ----+-----------+
| Member | Host            | Role    | State     | TL | Lag in MB |
+--------+-----------------+---------+-----------+----+-----------+
| node1  | 192.168.184.151 | Leader  | running   |  7 |           |
| node2  | 192.168.184.152 | Replica | streaming |  7 |         0 |
| node3  | 192.168.184.153 | Replica | streaming |  7 |         0 |
+--------+-----------------+---------+-----------+----+-----------+

Проверка подключения через HAProxy#

# Подключение для чтения/записи (primary) - порт 5000
psql -h haproxy_host -p 5000 -U global -d postgres -c "
SELECT 
    inet_server_addr() as connected_to,
    pg_is_in_recovery() as is_replica,
    current_user as current_user;"

Проверка репликации#

# На primary узле проверяем статус репликации
psql -h 192.168.184.151 -U postgres -d postgres -c "
SELECT 
    application_name,
    client_addr,
    state,
    sync_state,
    write_lag,
    flush_lag,
    replay_lag
FROM pg_stat_replication;"

Проверка пользователей в кластере#

# Проверяем созданных пользователей
psql -h 192.168.184.151 -U postgres -d postgres -c "
SELECT 
    usename,
    usesuper,
    usecreatedb,
    userepl,
    passwd IS NOT NULL as has_password
FROM pg_user;"

Тестирование отказоустойчивости#

Тест 1: Автоматический фейловер при падении primary#

# Определяем текущий primary
patronictl -c /etc/patroni/config.yml list

# Имитируем падение primary (например, на узле 1)
sudo systemctl stop patroni

# Мониторинг автоматического переключения
watch "patronictl -c /etc/patroni/config.yml list"

# Проверяем, что приложения продолжают работать через HAProxy
psql -h haproxy_host -p 5000 -U global -d postgres -c "SELECT inet_server_addr();"

Что происходит: Patroni обнаруживает падение primary через etcd, проводит выборы нового лидера и переконфигурирует репликацию. Весь процесс занимает 10-30 секунд.

Тест 2: Плановое переключение (switchover)#

# Инициируем плановое переключение
patronictl -c /etc/patroni/config.yml switchover --leader node1 --candidate node2

# Мониторинг процесса
patronictl -c /etc/patroni/config.yml list

Преимущество: Нулевое время простоя для приложений, так как переключение происходит плавно.

Тест 3: Восстановление узла после сбоя#

# Запускаем ранее упавший узел
sudo systemctl start patroni

# Patroni автоматически переконфигурирует узел как реплику
patronictl -c /etc/patroni/config.yml list

Мониторинг и управление#

Ключевые команды Patroni#

# Просмотр истории переключений
patronictl -c /etc/patroni/config.yml history

# Просмотр конфигурации DCS
patronictl -c /etc/patroni/config.yml show-config

# Перезагрузка кластера
patronictl -c /etc/patroni/config.yml restart postgres-cluster

# Реинициализация реплики (если она рассинхронизирована)
patronictl -c /etc/patroni/config.yml reinit postgres-cluster node3

# Временная приостановка автоматического фейловера (для обслуживания)
patronictl -c /etc/patroni/config.yml pause
# После обслуживания:
patronictl -c /etc/patroni/config.yml resume

Мониторинг через HAProxy#

# Просмотр статистики HAProxy в браузере
# http://haproxy_host:7000 (логин: admin, пароль: 1234)

# Или через командную строку
echo "show stat" | sudo socat /run/haproxy/admin.sock stdio

# Проверка health status узлов
curl -s http://haproxy_host:7000 | grep -A 10 "postgres_primary"

Настройка алертинга#

#!/bin/bash
# monitor_patroni.sh - скрипт для мониторинга состояния кластера

CLUSTER_STATUS=$(patronictl -c /etc/patroni/config.yml list -f json)
LEADER_COUNT=$(echo $CLUSTER_STATUS | jq '[.[] | select(.Role == "Leader")] | length')

if [ "$LEADER_COUNT" -ne 1 ]; then
    echo "ALERT: No leader or multiple leaders in cluster!"
    # Отправка уведомления (email, slack, etc.)
fi

# Проверка лага репликации
echo $CLUSTER_STATUS | jq -r '.[] | select(.Role == "Replica") | "\(.Member) lag: \(."Lag in MB") MB"'

Резервное копирование#

Стратегия бэкапов в кластере Patroni#

#!/bin/bash
# backup_patroni.sh

# Определяем текущий primary через Patroni
PRIMARY_HOST=$(patronictl -c /etc/patroni/config.yml list -f json | 
    jq -r '.[] | select(.Role == "Leader") | .Host')

# Создаем точку монтирования для бэкапа
BACKUP_DIR="/backups/$(date +%Y%m%d_%H%M%S)"
mkdir -p $BACKUP_DIR

# Выполняем физический бэкап с primary
pg_basebackup -h $PRIMARY_HOST -U replicator -D $BACKUP_DIR -X stream -P

# Создаем логический бэкап ключевых баз
pg_dump -h $PRIMARY_HOST -U global -Fc global_DB_db > $BACKUP_DIR/global_DB_db.dump

# Очистка старых бэкапов (храним 7 последних)
find /backups -maxdepth 1 -type d -name "202*" | sort -r | tail -n +8 | xargs rm -rf

Диагностика проблем#

Распространенные проблемы и решения#

  1. Patroni не запускается

# Проверка логов
sudo journalctl -u patroni -f

# Проверка доступности etcd
etcdctl endpoint health

# Проверка конфигурации
patronictl -c /etc/patroni/config.yml show-config
  1. Реплика отстает или не синхронизируется

# Проверка статуса репликации
psql -c "SELECT application_name, state, sync_state, 
         pg_wal_lsn_diff(pg_current_wal_lsn(), replay_lsn) as lag_bytes 
         FROM pg_stat_replication;"

# Проверка сетевой connectivity между узлами
ping -c 3 192.168.184.151
  1. HAProxy не определяет primary

# Проверка health checks вручную
curl http://192.168.184.151:8008/master
curl http://192.168.184.152:8008/master  
curl http://192.168.184.153:8008/master

# Проверка конфигурации HAProxy
sudo haproxy -c -f /etc/haproxy/haproxy.cfg
  1. Split-brain ситуация

# Принудительная установка лидера
patronictl -c /etc/patroni/config.yml failover --leader node1 --candidate node2

# Или экстренное выключение проблемного узла
sudo systemctl stop patroni

Обновление и обслуживание#

Плановое обслуживание#

# 1. Приостанавливаем автоматический фейловер
patronictl -c /etc/patroni/config.yml pause

# 2. Выполняем обслуживание на репликах
# 3. Выполняем switchover для обслуживания primary
patronictl -c /etc/patroni/config.yml switchover --master node1 --candidate node2

# 4. Обслуживаем бывший primary
# 5. Возобновляем автоматический фейловер
patronictl -c /etc/patroni/config.yml resume

Поочередное обновление реплик, затем плановый switchover#

  1. Отключаем Patroni, обновляем реплику node2.

  2. Отключаем Patroni, обновляем реплику node3.

  3. Плановый switchover на обновленную реплику.

  4. Обновляем бывший primary (теперь реплика).

Преимущества решения#

По сравнению с ручной настройкой репликации

  1. Автоматизация: Полная автоматизация фейловера и восстановления.

  2. Надежность: Предотвращение split-brain через etcd.

  3. Мониторинг: Встроенные health checks и API для мониторинга.

  4. Гибкость: Простое добавление/удаление узлов кластера.

  5. Простота управления: Единые команды для управления всем кластером.

Производительность

  • Время фейловера: 10-30 секунд по сравнению с 5-10 минут при ручной настройке.

  • Минимальный downtime: Приложения не требуют изменений конфигурации.

  • Автоматическое восстановление: Упавшие узлы автоматически возвращаются в кластер.

Заключение

Данная конфигурация обеспечивает production-готовое решение для высокодоступного кластера PostgreSQL с следующими характеристиками:

  • Автоматический фейловер при падении primary узла.

  • Балансировка нагрузки между репликами для read-only запросов.

  • Единая точка входа через HAProxy.

  • Мониторинг и управление через Patroni API и etcd.

  • Минимальное время простоя при сбоях оборудования.

  • Простое масштабирование добавлением новых узлов.