+

 Patroni — это шаблон для решений PostgreSQL высокой доступности (HA) с использованием Python. Узлы Patroni/PostgreSQL отделены от узлов DCS (за исключением случаев, когда Patroni самостоятельно реализует RAFT), поэтому требования к минимальному количеству узлов отсутствуют. Запуск кластера, состоящего из одного основного и одного резервного, вполне подойдет. Позже вы сможете добавить дополнительные резервные узлы

Patroni - часть 1: Установка Patroni

Patroni - часть 1: Параметры для инициализации (Bootstrap configuration)

Patroni - часть 1: Инициализация и запуск кластера

Установка Patroni

Предварительная установка необходимых пакетов python

$ dnf install https://download.postgresql.org/pub/repos/yum/reporpms/EL-8-x86_64/pgdg-redhat-repo-latest.noarch.rp m

$ dnf install --enablerepo pgdg-common python3-psycopg2

В данной инструкции мы будем использовать DCS от HashiCorp Consul. Ознакомиться со всем списком поддерживаемых DCS можно по ссылке https://patroni.readthedocs.io/en/latest/installation.html#extras 

$ dnf install --enablerepo pgdg-common ​patroni patroni-consul
$  pip3 install  python-consul

Альтернативная установка с помощью pip

pip3  install  python3-psycopg2 patroni[​python3-consul]

С установкой DCS от HashiCorp - Consul, можно ознакомиться из моей статьи по следующей ссылке
https://www.prostep.com.ua/Consul_part1.html#2_1

touch /etc/patroni/patroni.yml

Сгенерируем образец файла конфигурации

$ patroni --generate-sample-config /etc/patroni/patroni.yml

Необходимо поправить файла конфигурации, а именно следующие строки

scope: '<name>' 
postgresql:
     bin_dir: '/usr/pgsql-*/bin' 
     data_dir: '/var/lib/pgsql/*/data'
consul:
     host: 127.0.0.1:8500
     scheme: <http> or <https>
     register_service: true
     token: '<token>'
tags:
     clonefrom: false 
     nofailover: false 

         Параметры конфигурации:
    global:
name - имя хоста. Должно быть уникальным для кластера.
namespace - 
путь в хранилище конфигурации, где Patroni будет хранить информацию о кластере. Значение по умолчанию: «/service»
scope - 
имя кластера
    logs:
level - устанавливает общий уровень ведения журнала. Значение по умолчанию — INFO
Traceback_level - 
устанавливает уровень, на котором будут видны обратные трассировки. Значение по умолчанию — ОШИБКА. Установите значение DEBUG, если вы хотите видеть обратные трассировки только в том случае, если вы включили log.level=DEBUG .
format - 
устанавливает строку форматирования журнала. Значение по умолчанию: %(asctime)s %(levelname)s: %(message)s 
dateformat - 
устанавливает строку форматирования даты и времени.
max_queue_size - 
Patroni использует двухэтапное ведение журнала. Записи журнала записываются в очередь в памяти, и существует отдельный поток, который извлекает их из очереди и записывает в stderr или файл. Максимальный размер внутренней очереди по умолчанию ограничен 1000 записями, чего достаточно для хранения логов за последние 1 час 20 минут.
dir - 
каталог для записи журналов приложения. Каталог должен существовать и быть доступен для записи пользователю, выполняющему Patroni. Если вы установите это значение, приложение по умолчанию сохранит 4 журнала по 25 МБ. Вы можете настроить эти значения хранения с помощью file_num и file_size (см. ниже).
file_num - 
количество журналов приложений, которые необходимо сохранить.
file_size - 
Размер файла Patoni.log (в байтах), который запускает прокрутку журнала.
loggers - 
этот раздел позволяет переопределить уровень ведения журнала для каждого модуля Python.   
        patroni.postmaster: WARNING
        urllib3: DEBUG
    consul:
host -  хост:порт для локального агента Consul.
scheme - 
(необязательно) http или https, по умолчанию http.
register_service - 
(необязательно) регистрировать или нет службу с именем, определенным параметром области, и главным тегом, основным, репликой или резервным лидером в зависимости от роли узла. По умолчанию установлено значение false.
token - 
(необязательно) токен ACL.
Разрешения для токена ACL:
     service_prefix "${scope}" {
                policy = "write"
     }
     key_prefix "${namespace}/${scope}" {
                policy = "write"
     }
     session_prefix "" {
                policy = "write"
     }
    postgresq:
connect_address - IP-адрес + порт, через который Postgres доступен из других узлов и приложений
data_dir - 
расположение каталога данных Postgres, существующего или инициализируемого Patroni
bin_dir - 
(необязательно) Путь к двоичным файлам PostgreSQL (pg_ctl, initdb, pg_controldata, pg_basebackup, postgres, pg_isready, pg_rewind). Если она не указана или представляет собой пустую строку, для поиска исполняемых файлов будет использоваться переменная среды PATH.
listen - 
IP-адрес + порт, который прослушивает Postgres; должен быть доступен с других узлов кластера, если вы используете потоковую репликацию. Допускается использование нескольких адресов, разделенных запятыми, при условии, что компонент порта добавляется после последнего через двоеточие, т. е. . Patroni будет использовать первый адрес из этого списка для установки локального подключения к узлу PostgreSQL. listen: 127.0.0.1,127.0.0.2:5432
parameters - 
список параметров конфигурации для Postgres. Многие из них необходимы для работы репликации.
pg_hba -  список строк, которые Patroni будет использовать для генерации pg_hba.conf. Patroni игнорирует этот параметр, если hba_file для параметра PostgreSQL установлено значение, отличное от значения по умолчанию. Вместе с динамической настройкой этот параметр упрощает управление файлами pg_hba.conf
      - host all all 0.0.0.0/0 md5
      - host replication replicator 127.0.0.1/32 md5: для репликации требуется такая строка.
    restapi:
connect_address - IP-адрес (или имя хоста) и порт для доступа к REST API Patroni . Все члены кластера должны иметь возможность подключаться к этому адресу, поэтому, если установка Patroni не предназначена для демонстрации внутри локального хоста, этот адрес не должен быть адресом, отличным от «localhost» или адресом обратной связи (например: «localhost» или «127.0.0.1»). Он может служить конечной точкой для проверок работоспособности HTTP, а также для пользовательских запросов (напрямую или через REST API), а также для проверок работоспособности, выполняемых участниками кластера. во время выборов лидера (например, чтобы определить, работает ли лидер еще или существует ли узел, позиция которого в WAL опережает узел, выполняющий запрос и т. д.) connect_address помещается в ключ участника в DCS, что позволяет преобразовать имя участника в адрес для подключения к его REST API.
listen - IP-адрес (или имя хоста) и порт, который Patroni будет прослушивать для REST API, чтобы обеспечить те же проверки работоспособности и обмен сообщениями кластера между участвующими узлами, как описано выше. для предоставления информации о проверке работоспособности HAProxy (или любого другого балансировщика нагрузки, способного выполнять проверки HTTP «OPTION» или «GET»).
    tags:
clonefrom  - true или false. Если установлено true другие узлы, предпочтительнее используют этот узел для начальной загрузки. Если существует несколько узлов с clonefrom установленным тегом, true узел для загрузки будет выбран случайным образом. Значение по умолчанию false.
noloadbalance - true или false. Если установлено значение true узла, будет возвращен код состояния HTTP 503 для проверки работоспособности REST API и, следовательно, он будет исключен из балансировки нагрузки. По умолчанию GET /replica false.
replicationfrom - IP-адрес/имя хоста другой реплики. Используется для поддержки каскадной репликации.
nosync - true или false. Если установлено значение, true узел никогда не будет выбран в качестве синхронной реплики
nofailover - true или false. Контролирует, разрешено ли этому узлу участвовать в гонке за лидерами и стать лидером. По умолчанию это false означает, что этот узел _может_ участвовать в гонках за лидерами.
failover_priority - целое число, управляет приоритетом, который должен иметь этот узел во время переключения при отказе. Узлы с более высоким приоритетом будут иметь преимущество перед узлами с более низким приоритетом, если они получили/воспроизвели одинаковое количество WAL. Однако узлы с более высокими значениями LSN приема/воспроизведения являются предпочтительными независимо от их приоритета. Если значение failover_priority равно 0 или отрицательное — такому узлу не разрешено участвовать в гонке за лидерами и стать лидером (аналогично) - nofailover: true

ПРЕДУПРЕЖДЕНИЕ. ​Укажите только один из nofailover или failover_priority. Предоставление аналогично и даст узлу приоритет 1. nofailover: true failover_priority: 0 nofailover: false 

Параметры для инициализации 
(Bootstrap configuration)

ПРИМЕЧАНИЕ. ​​После того как Patroni впервые инициализирует кластер и настройки будут сохранены в DCS, все будущие изменения в разделе bootstrap.dcs конфигурации YAML не вступят в силу! Если вы хотите изменить их, используйте либо patronictl edit-config , либо Patroni REST API . 

bootstrap:
 dcs (Глобальная динамическая конфигурация кластера- этот раздел будет записан в /<namespace>/<scope>/config  хранилища конфигурации после инициализации нового кластера. 
      initdb - (необязательно) список параметров, которые будут переданы в initdb
                        encoding: UTF8 - кодировка по умолчанию для новых баз данных
                        locale: UTF8 - локаль по умолчанию для новых баз данных
      Dynamic Configuration Settings
loop_wait -  количество секунд, в течение которых цикл будет находиться в режиме ожидания. Значение по умолчанию: 10, минимально возможное значение: 1.
ttl - TTL для получения блокировки лидера (в секундах). Думайте об этом как о промежутке времени до запуска процесса автоматического переключения при сбое. Значение по умолчанию: 30, минимально возможное значение: 20.
retry_timeout -  таймаут для повторных попыток операций DCS и PostgreSQL (в секундах). Проблемы с DCS или сетью, более короткие, чем эта, не заставят Патрони понизить в должности лидера. Значение по умолчанию: 10, минимально возможное значение: 3.

ПРЕДУПРЕЖДЕНИЕ: ​​​при изменении значений Loop_wait, retry_timeout или ttl вы должны следовать правилу:
                                              loop_wait + 2 * retry_timeout <= ttl

maximum_lag_on_failover - максимальное количество байтов, которое может отставать ведомый, чтобы иметь возможность участвовать в выборах лидера.
    postgresql:
use_pg_rewind - использовать или нет pg_rewind. По умолчанию установлено значение false .
use_slots - использовать или нет слоты репликации. По умолчанию значение true в PostgreSQL 9.4+.
parameters- список параметров конфигурации для Postgres
pg_hba -  список строк, которые Patroni будет использовать для генерации pg_hba.conf. Patroni игнорирует этот параметр, если hba_file для параметра PostgreSQL установлено значение, отличное от значения по умолчанию.

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

scope: <scope>
name: <name>

log:
   dir: /var/log/patroni
   format: '%(asctime)s %(levelname)s: %(message)s'
   level: INFO
   max_queue_size: 1000
   traceback_level: ERROR

restapi:
   connect_address: <ip>:8008
   listen: <ip>:8008

consul:
   host: 127.0.0.1:8500
   scheme: https
   register_service: true
   token: '<token>'

bootstrap:
   dcs:
      loop_wait: 10
      retry_timeout: 10
   ttl: 30
   maximum_lag_on_failover: 1048576
   postgresql:
      parameters:
         hot_standby: 'on'
         max_connections: 100
         max_locks_per_transaction: 64
         max_prepared_transactions: 0
         max_replication_slots: 10
         max_wal_senders: 10
         max_worker_processes: 8
         track_commit_timestamp: 'off'
         wal_keep_segments: 8
         wal_level: replica
         wal_log_hints: 'on'
      use_pg_rewind: true
      use_slots: true
   initdb:
      - encoding: UTF8
      - lc-messages: C
      - data-checksums

postgresql:
   authentication:
      replication:
         password: 'passwodrdtest'
         username: replicator
      superuser:
         password: 'testpassword'
         username: postgres
   bin_dir: '/usr/pgsql-**/bin'
   connect_address: <ip>:5432
   data_dir: '/var/lib/pgsql/**/data'
   listen: <ip>:5432
   parameters:
      unix_socket_directories: '/var/run/postgresql'
      password_encryption: scram-sha-256
   pg_hba:
      - host all all all scram-sha-256
      - host replication replicator all scram-sha-256

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

Инициализация и запуск кластера Patroni

$ systemctl start patroni

   После успешного запуска мы увидем журнал следующего вида:

WARNING: Could not register service: unknown role type uninitialized
INFO: bootstrap in progress
The files belonging to this database system will be owned by user "postgres".
This user must also own the server process.
The database cluster will be initialized with this locale configuration:
provider: libc
LC_COLLATE: C
LC_CTYPE: C.UTF-8
LC_MESSAGES: C
LC_MONETARY: C
LC_NUMERIC: C
LC_TIME: C
The default database encoding has accordingly been set to "UTF8".
The default text search configuration will be set to "english".
Data page checksums are disabled.
creating directory /var/lib/pgsql/*/data ... ok
creating subdirectories ... ok
selecting dynamic shared memory implementation ... posix
selecting default max_connections ... 100
selecting default shared_buffers ... 128MB
selecting default time zone ... Europe/Kiev
creating configuration files ... ok
running bootstrap script ... ok
performing post-bootstrap initialization ... ok
syncing data to disk ... ok
initdb: warning: enabling "trust" authentication for local connections
initdb: hint: You can change this by editing pg_hba.conf or using the option -A, or --auth-local and --auth-host, the next time you run initdb.
Success. You can now start the database server using:
/usr/pgsql-*/bin/pg_ctl -D /var/lib/pgsql/*/data -l logfile start
INFO: postmaster pid=3900890
<ip_listen>:5432 - no response
LOG: redirecting log output to logging collector process
HINT: Future log output will appear in directory "log".
<ip_listen>:5432 - accepting connections
<ip_listen>:5432 - accepting connections
INFO: establishing a new patroni heartbeat connection to postgres
INFO: Register service pgsql, params {'service_id': 'pgsql/​<noda_name>', 'address': '<ip_listen>', 'port': 5432, 'check': {'http': 'http://​<ip_listen>:8008/master', 'interval': '5s', 'DeregisterCriticalServiceAfter': '150.0s'}, 'tags': ['master', 'primary'], 'enable_tag_override': True}
INFO: running post_bootstrap
WARNING: Could not activate Linux watchdog device: Can't open watchdog device: [Errno 2] No such file or directory: '/dev/watchdog'
INFO: initialized a new cluster
INFO: establishing a new patroni restapi connection to postgres
INFO: no action. I am (<noda_name>), the leader with the lock

   Проверим версию patroni и postgresql

$ patronictl version ​<cluster_name> ​<noda_name>
patronictl version *.*.*
<noda_name>: Patroni *.*.* PostgreSQL **.*

   Проверим состояние кластера patroni

$ patronictl list
+ Cluster: <cluster_name> (<​database_system_identifier>) ----+-----------+
| Member                  | Host                        | Role            | State             | TL     | Lag in MB        |
+-------------+-------------+--------+---------+----+-----------+
| <noda_name>    | <ip_listen>         | Leader       | running       | 1         |                              |
+-------------+-------------+--------+---------+----+-----------+

   Добавление членов кластера осуществляется аналогичным образом, заменив в конфигурации несколько параметров указывающие на ip адресс.