Patroni – опенсорсный инструмент, с которым можно подключить аварийное управление для кластеров Постгресе. Т.е можно автоматически переключать работу на резервный сервер в случае сбоя основного.

Patroni может интегрироваться с различными системами распределенной конфигурации, включая etcd, ZooKeeper, Consul и Kubernetes.

Установка

Для установки нужен питон выше 3.4 версии и естественно pip. Patroni может быть запущен на любой ОС, поддерживающей Python:

pip install patroni[etcd]

Команда установит Patroni с поддержкой etcd. Если например нужно ZooKeeper или Consul, ты просто [etcd] заменяется на [zookeeper] или [consul] соответственно.

Patroni требует наличия DCS для хранения конфигурации и состояния кластера, например для настройки etcd необходимо указать URL узлов etcd в конф. файле Patroni:

etcd:
  hosts: localhost:2379

Для ZooKeeper конфигурация будет выглядеть следующим образом:

zookeeper:
  hosts: localhost:2181

А для Consul конфигурация примет вид:

consul:
  host: localhost:8500

После настройки DCS нужно создать конфигурационный файл для Patroni. Конфигурационный файл обычно называется patroni.yml и содержит все настройки для запуска кластера PostgreSQL с Patroni.

Пример минимальной конфигурации:

scope: postgres
namespace: /db/
name: postgresql0

restapi:
  listen: 0.0.0.0:8008
  connect_address: localhost:8008

etcd:
  hosts: localhost:2379

bootstrap:
  dcs:
    ttl: 30
    loop_wait: 10
    retry_timeout: 10
    maximum_lag_on_failover: 1048576
  initdb:
  - encoding: UTF8
  - data-checksums
  pg_hba:
  - host replication replicator 127.0.0.1/32 md5
  - host all all 0.0.0.0/0 md5
  users:
    admin:
      password: admin
      options:
        - createrole
        - createdb

postgresql:
  listen: 0.0.0.0:5432
  connect_address: localhost:5432
  data_dir: /data/patroni
  pgpass: /tmp/pgpass
  authentication:
    replication:
      username: replicator
      password: rep-pass
    superuser:
      username: postgres
      password: secretpassword
  parameters:
    unix_socket_directories: '.'

После настройки конфигурационного файла можно запускать:

patroni /path/to/patroni.yml

Patroni автоматически инициализирует кластер PostgreSQL, регистрирует его в DCS и запускает HTTP API

Подробнее про конфигурацию Patroni

Конфигурация Patroni включает в себя множество параметров:

  • scope: имя кластера, используется как префикс для всех данных в DCS

  • namespace: префикс для ключей в DCS, позволяет разделять кластеры в общем хранилище

  • name: уникальное имя текущего узла в кластере.

Особые конфы для dcs:

  • etcd: конфигурация для etcd включает hosts, protocol, ca_file, cert_file, и key_file для безопасного соединения.

  • zookeeper: для ZooKeeper указываются hosts, session_timeout, и reconnect_timeout.

  • consul: для Consul настраиваются host, token, consistency, и scheme.

Конфигурация PostgreSQL включает параметры для подключения к бд, а также настройки репликации и восстановления:

  • connect_address: адрес, на котором PostgreSQL принимает подключения.

  • data_dir: директория с данными PostgreSQL.

  • pgpass: путь к файлу с паролями.

  • recovery_conf: параметры для файла recovery.conf

Настройки репликации включают параметры для управления репликацией и выбором лидера.

  • maximum_lag_on_failover: макс. допустимое отставание реплики при failover.

  • retry_timeout: t ожидания перед повторной попыткой операции.

Patroni может использовать watchdog для обеспечения более надежного failover:

  • mode: режим работы watchdog (off, automatic, required).

  • device: устройство watchdog.

  • safety_margin: t в секундах, которое оставляется на случай сбоя.

Еще один пример конф:

scope: my_cluster
namespace: /db/
name: node1

restapi:
  listen: 0.0.0.0:8008
  connect_address: 192.168.1.1:8008

etcd:
  hosts: localhost:2379

bootstrap:
  dcs:
    ttl: 30
    loop_wait: 10
    retry_timeout: 10
    maximum_lag_on_failover: 1048576
  initdb:
  - encoding: UTF8
  - data-checksums
  pg_hba:
  - host replication replicator 127.0.0.1/32 md5
  - host all all 0.0.0.0/0 md5

postgresql:
  listen: 0.0.0.0:5432
  connect_address: 192.168.1.1:5432
  data_dir: /var/lib/postgresql/data
  pgpass: /tmp/pgpass
  authentication:
    replication:
      username: replicator
      password: secret
    superuser:
      username: postgres
      password: secret

Patroni REST API

Patroni REST API предоставляет информацию о текущем состоянии кластера, позволяя выполнять различные операции, как получение статуса узла, переключение ролей между узлами, перезагрузка конфигурации и т.д. API следует принципам REST, используя стандартные HTTP методы, такие как GET и POST, для взаимодействия с ресурсами.

Самый базовый запрос – это получение статуса кластера. Это делается через простой GET запрос к корню API. В ответе приходит JSON, содержащий информацию о состоянии кластера, включая роль узла, версию PostgreSQL, текущую задержку репликации и т.п

import requests

response = requests.get('http://patroni-api-endpoint:8008/')
status_info = response.json()

print(status_info)

Можно инициировать switchover и failover операции. Для выполнения switchover, можно использовать POST запрос к /switchover endpoint, указывая целевой узел для переключения роли лидера:

response = requests.post(
    'http://patroni-api-endpoint:8008/switchover',
    json={
        "leader": "current_leader_name",
        "candidate": "target_replica_name"
    }
)

print(response.json())

Для failover процесса, запрос будет аналогичным, но отправляться на /failover endpoint.

Изменение конфигурации кластера на лету – еще одна замечательная возможность, можно отправить POST запрос к /reload endpoint для применения изменений в конфигурации без необходимости перезапуска узлов:

response = requests.post('http://patroni-api-endpoint:8008/reload')
print(response.status_code)

Также endpoints для мониторинга, такие как /history для получения истории failover операций, /config для просмотра текущей конфигурации кластера и /cluster для получения информации о всех узлах кластера.

Bootstrap реплик

Bootstrap реплик в Patron может быть выполнен с использованием различных методов, включая базовый backup с мастера, использование уже существующего backup (например, созданного с помощью pg_basebackup или инструментов вроде Barman, WAL-E, WAL-G), или клонирование с другой реплики.

Конфигурация Patroni должна включать определенные параметры для настройки процесса bootstrap. Пример базовой конфигурации для patroni.yml:

bootstrap:
  method: pg_basebackup
  pg_basebackup:
    command: pg_basebackup -h master_host -D /var/lib/postgresql/data/pgdata -U replicator -vP -W
    retries: 5
    retry_timeout: 10

Файл определяет метод bootstrap, команду для создания базового backup, параметры initdb для инициализации новой базы данных, настройки pg_hba для контроля доступа и учетку юзера.

Patroni поддерживает несколько методов bootstrap, каждый из которых имеет свои фичи:

  • pg_basebackup: станд. инструмент PostgreSQL для создания базового backup. Просто и надежно, но не оч быстро

  • WAL-E/WAL-G: использование этих инструментов позволяет быстро создавать реплики, восстанавливая данные из backup, хранящихся в облачном хранилище.

  • Barman: популярный инструмент для backup и восстановления PostgreSQL, который может быть интегрирован с Patroni для инициализации реплик.

  • Clone from replica: возможность клонировать существующую реплику

Для использования WAL-E в качестве метода bootstrap:

bootstrap:
  method: wal_e
  wal_e:
    command: wal-e backup-fetch /var/lib/postgresql/data/pgdata LATEST
    envdir: /etc/wal-e.d/env
    recovery_conf:
      restore_command: wal-e wal-fetch "%f" "%p"

Конфиг определяет использование WAL-E для восстановления последнего backup и настройку restore_command для последующего восстановления WAL файлов.


В завершение хочу напомнить о том, что у моих друзей из OTUS есть ряд курсов по инфраструктуре, где преподают практикующие эксперты отрасли. Подробности в каталоге.