Перейти к содержанию

PostgreSQL Patroni Cluster

Рассмотрим настройку отказоустойчивого PostgreSQL кластера Patroni. В качестве балансировщика нагрузки будем использовать HAProxy и Keepalived.

ℹ️ Схема архитектуры кластера: 3 ноды PostgreSQL (primary + 2 replica) с автоматическим failover через Patroni, distributed consensus через etcd, виртуальный IP через Keepalived, балансировка через HAProxy.

Описание компонентов

PostgreSQL

PostgreSQL — это объектно-реляционная система управления базами данных (СУБД) с открытым исходным кодом. Она используется для хранения и управления данными и поддерживает стандарты SQL.

Patroni

Patroni предоставляет шаблон для настройки кластера PostgreSQL с высокой доступностью. Это инструмент для управления кластерами, который можно использовать для автоматизации развертывания и обслуживания кластеров PostgreSQL. Patroni написан на Python и использует etcd, Consul или ZooKeeper для хранения конфигураций, обеспечивая высокую доступность. В данной настройке используется etcd. Patroni также может управлять конфигурациями для репликации баз данных, резервного копирования и восстановления. Настройки Patroni управляются с помощью файла YAML.

HAProxy

HAProxy — это бесплатное программное обеспечение с открытым исходным кодом, которое предоставляет балансировщик нагрузки и прокси-сервер с высокой доступностью для приложений, работающих на основе TCP и HTTP, распределяя запросы между несколькими серверами. HAProxy отслеживает изменения в мастер/слейв-узлах и подключается к соответствующему мастер-узлу по запросу клиентов.

Keepalived

Keepalived — это программный комплекс, обеспечивающий высокую доступность и балансировку нагрузки.

ETCD

ETCD используется как распределенное хранилище конфигураций (DCS), где хранится состояние кластера PostgreSQL. При любом изменении состояния узлов PostgreSQL Patroni обновляет соответствующие данные в хранилище ключей-значений ETCD. ETCD использует эту информацию для выбора узла-лидера и поддержания работоспособности кластера. Для обеспечения высокой доступности рекомендуется развернуть три сервера ETCD отдельно от серверов базы данных.

Рассмотрим настройку кластера, состоящего из 3 нод etcd, 2 нод haproxy и 2 нод postgres:

10.0.0.1 etcd-1

10.0.0.2 etcd-2

10.0.0.3 etcd-3

10.0.0.11 patroni-1

10.0.0.12 patroni-2

10.0.0.21 haproxy-1

10.0.0.22 haproxy-2

10.0.0.20 keepalived virtual ip

Установка и настройка ETCD кластера

1. На каждой ноде кластера выполните установку etcd

sudo apt-get update

sudo apt-get install -y etcd-server etcd-client

2. Проверьте версию etcd сервера после установки

etcd --version

3. Проверьте статус сервиса etcd. Если активен (running) — остановите его:

sudo systemctl status etcd

sudo systemctl stop etcd

4.  Настройте конфигурацию кластера. Отредактируйте файл /etc/default/etcd на каждой ноде etcd кластера

sudo vim /etc/default/etcd

etcd-1

[member]

ETCD_NAME="etcd-1"

ETCD_DATA_DIR="/var/lib/etcd/default"

ETCD_LISTEN_PEER_URLS="http://10.0.0.1:2380"

ETCD_LISTEN_CLIENT_URLS="http://10.0.0.1:2379,http://127.0.0.1:2379"

ETCD_HEARTBEAT_INTERVAL="1000"

ETCD_ELECTION_TIMEOUT="5000"

ETCD_INITIAL_ELECTION_TICK_ADVANCE="false"

ETCD_ENABLE_V2="true"

[cluster]

ETCD_INITIAL_ADVERTISE_PEER_URLS="http://10.0.0.1:2380"

ETCD_INITIAL_CLUSTER="etcd-node-1=http://10.0.0.1:2380,etcd-node-2=http://10.0.0.2:2380,etcd-node-3=http://10.0.0.3:2380"

ETCD_INITIAL_CLUSTER_STATE="new"

ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"

ETCD_ADVERTISE_CLIENT_URLS="http://10.0.0.1:2379"

etcd-2

[member]

ETCD_NAME="etcd-2"

ETCD_DATA_DIR="/var/lib/etcd/default"

ETCD_LISTEN_PEER_URLS="http://10.0.0.2:2380"

ETCD_LISTEN_CLIENT_URLS="http://10.0.0.2:2379,http://127.0.0.1:2379"

ETCD_HEARTBEAT_INTERVAL="1000"

ETCD_ELECTION_TIMEOUT="5000"

ETCD_INITIAL_ELECTION_TICK_ADVANCE="false"

ETCD_ENABLE_V2="true"

[cluster]

ETCD_INITIAL_ADVERTISE_PEER_URLS="http://10.0.0.2:2380"

ETCD_INITIAL_CLUSTER="etcd-node-1=http://10.0.0.1:2380,etcd-node-2=http://10.0.0.2:2380,etcd-node-3=http://10.0.0.3:2380"

ETCD_INITIAL_CLUSTER_STATE="new"

ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"

ETCD_ADVERTISE_CLIENT_URLS="http://10.0.0.2:2379"

etcd-3

[member]

ETCD_NAME="etcd-3"

ETCD_DATA_DIR="/var/lib/etcd/default"

ETCD_LISTEN_PEER_URLS="http://10.0.0.3:2380"

ETCD_LISTEN_CLIENT_URLS="http://10.0.0.3:2379,http://127.0.0.1:2379"

ETCD_HEARTBEAT_INTERVAL="1000"

ETCD_ELECTION_TIMEOUT="5000"

ETCD_INITIAL_ELECTION_TICK_ADVANCE="false"

ETCD_ENABLE_V2="true"

[cluster]

ETCD_INITIAL_ADVERTISE_PEER_URLS="http://10.0.0.3:2380"

ETCD_INITIAL_CLUSTER="etcd-node-1=http://10.0.0.1:2380,etcd-node-2=http://10.0.0.2:2380,etcd-node-3=http://10.0.0.3:2380"

ETCD_INITIAL_CLUSTER_STATE="new"

ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"

ETCD_ADVERTISE_CLIENT_URLS="http://10.0.0.3:2379"

Описание параметров:

Параметр Описание
ETCD_NAME Имя узла. Значение должно быть уникальным
ETCD_DATA_DIR Путь к каталогу данных
ETCD_HEARTBEAT_INTERVAL Время (в миллисекундах), между рассылками лидером оповещений о том, что он всё ещё лидер. По умолчанию: "100"
ETCD_ELECTION_TIMEOUT Время (в миллисекундах), которое проходит между последним принятым оповещением от лидера кластера, до попытки захватить роль лидера на ведомом узле. Рекомендуется задавать его в несколько раз большим, чем ETCD_HEARTBEAT_INTERVAL . По умолчанию: "1000".
ETCD_LISTEN_PEER_URLS Список URL-адресов для прослушивания трафика между узлами. Этот параметр указывает etcd принимать входящие запросы от других узлов по заданным комбинациям scheme://IP . Схема может быть http или https. В качестве альтернативы можно использовать unix:// или unixs:// для Unixсокетов. Если указано 0.0.0.0 как IP-адрес, etcd будет прослушивать данный порт на всех интерфейсах. Если указан конкретный IP-адрес и порт, etcd будет прослушивать данный порт и интерфейс. Можно указать несколько URL-адресов, чтобы настроить прослушивание на нескольких адресах и портах. Etcd будет отвечать на запросы с любого из указанных адресов и портов.
ETCD_LISTEN_CLIENT_URLS Список URL-адресов для прослушивания клиентского трафика. Этот параметр указывает etcd принимать входящие запросы от клиентов по заданным комбинациям scheme://IP
ETCD_INITIAL_ADVERTISE_PEER_URLS Начальный список URL-адресов. Эти адреса используются для обмена данными etcd по всему кластеру. По крайней мере один из них должен быть доступен для всех членов кластера. Эти URL-адреса могут содержать доменные имена
ETCD_INITIAL_CLUSTER Список узлов кластера на момент запуска
ETCD_INITIAL_CLUSTER_STATE Начальное состояние кластера («new» или «existing»). Установите значение new для всех членов, присутствующих во время начальной статической или DNS-загрузки. Если этот параметр установлен в existing , etcd попытается присоединиться к существующему кластеру. Если установлено неверное значение, etcd попытается запуститься, но завершится с ошибкой.
ETCD_INITIAL_CLUSTER_TOKEN Токен кластера. Должен совпадать на всех узлах кластера
ETCD_ADVERTISE_CLIENT_URLS Список равноправных URL-адресов, по которым его могут найти остальные узлы кластера. Можно использовать содержать доменные имена

5. Запустите службу etcd и проверьте её статус

sudo systemctl enable etcd

sudo systemctl start etcd

sudo systemctl status etcd

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

etcdctl --write-out=table endpoint status --cluster

etcdctl --write-out=table endpoint health --cluster

Установка PostgreSQL 18

1. Подключите репозитории PostgreSQL

curl -fsSL https://www.postgresql.org/media/keys/ACCC4CF8.asc|sudo gpg --dearmor -o

/etc/apt/trusted.gpg.d/postgresql.gpg

sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" >

/etc/apt/sources.list.d/pgdg.list'

2. Установите PostgreSQL 18

sudo apt-get update

sudo apt install -y postgresql-18 \

               postgresql-server-dev-18 \

               postgresql-client-18

sudo apt install -y postgresql-18-rum \

               postgresql-18-pg-hint-plan \

               postgresql-18-pg-qualstats \

               postgresql-18-pgvector

3. Остановите и отключите службу PostgreSQL

sudo systemctl stop postgresql.service

sudo systemctl disable postgresql.service

Установка расширений PostgreSQL

Для использования баз данных Первая Форма в PostgreSQL должны быть настроены следующие расширения:

  • plpgsql

  • rum

  • pgcrypto

  • pg_buffercache

  • btree_gin

  • pg_stat_statements

  • pg_trgm

  • pg_qualstats

  • pg_hint_plan

  • vector

  • pg_background

1. Установите необходимые для работы расширений пакеты

sudo apt-get update

sudo apt-get install -y apt-transport-https ca-certificates curl freetds-common freetds-dev g++ gcc git gnupg gnupg2 gpg libcurl4-openssl-dev libsybdb5 lsb-release make software-properties-common wget

2.  Скачайте исходники модуля pg_background, скомпилируйте и установите

cd /tmp

 

wget --user USERNAME --ask-password https://download.1forma.ru/raw-1f-app/pg-extensions/pg_background.zip

 

unzip pg_background.zip

 

rm pg_background.zip

 

sudo apt install -y build-essential libkrb5-dev

 

cd pg_background-master/

 

make

 

sudo make install

 

cd ..

rm -rf pg_background-master

Настройка локали

1. Установите локаль ru_RU.utf8

sudo apt-get update

sudo apt-get install -y language-pack-ru

sudo update-locale LANG=ru_RU.UTF-8

2. Проверьте командой locale. Должны получить: LANG=ru_RU.UTF-8

3. Настройте формат даты и времени. Создайте файл /etc/freetds/locales.conf со следующим наполнением:

sudo vim /etc/freetds/locales.conf

 

[default]

date format = %b %e %Y %I:%M:%S.%z%p

4. Проверьте формат, выполнив команду date. Должны получить дату в следующем формате: Вт 09 мая 2023 22:16:05 UTC

Установка и настройка Patroni

1. Установите необходимые пакеты

sudo apt-get update

sudo apt-get install -y python3 python3-etcd python3-etcd3

sudo apt-get install -y patroni

2. Создайте  каталог для данных postgres

sudo mkdir /pgdata

sudo chown -R postgres:postgres /pgdata

sudo chmod -R 700 /pgdata

3. Настройте конфигурацию кластера Patroni. Создайте и внесите настройки в файл /etc/patroni/config.yml

sudo vim /etc/patroni/config.yml

patroni-1

scope: patroni-cluster

name: patroni-1

namespace: /service

 

restapi:

 listen: 10.0.0.11:8008

 connect_address: 10.0.0.11:8008

 

etcd3:

 hosts: 10.0.0.1:2379,10.0.0.2:2379,10.0.0.3:2379

 

bootstrap:

 method: initdb

 dcs:

   ttl: 30

   loop_wait: 10

   retry_timeout: 10

   maximum_lag_on_failover: 1048576

 initdb:

   - data-checksums

 postgresql:

   use_pg_rewind: true

   use_slots: true

   parameters:

     superuser_reserved_connections: 5

     max_connections: 100

     shared_buffers: 512MB

     effective_cache_size: 4GB

     work_mem: 128MB

     maintenance_work_mem: 256MB

     random_page_cost: 4

     effective_io_concurrency: 2

     huge_pages: try

     checkpoint_timeout: 15min

     wal_level: replica

     wal_compression: on

     max_wal_senders: 10

     synchronous_commit: on

     max_replication_slots: 10

     min_wal_size: 1GB

     max_wal_size: 4GB

     checkpoint_completion_target: 0.9

     wal_buffers: 16MB

     wal_keep_size: 2GB

     default_statistics_target: 1000

     log_timezone: 'Europe/Moscow'

     timezone: 'Europe/Moscow'

     lc_messages: 'en_US.UTF-8'

     lc_monetary: 'en_US.UTF-8'

     lc_numeric: 'en_US.UTF-8'

     lc_time: 'en_US.UTF-8'

     io_method: 'io_uring'

     shared_preload_libraries: 'pg_stat_statements,pg_hint_plan,pg_qualstats'

     jit: off

 

 pg_hba:

   - local all postgres peer

   - host all all 0.0.0.0/0 md5

   - host replication replicator 127.0.0.1/32 md5

   - host replication replicator 10.0.0.11/32 md5

   - host replication replicator 10.0.0.12/32 md5

 

postgresql:

 listen: 10.0.0.11,127.0.0.1:5432

 connect_address: 10.0.0.11:5432

 data_dir: /pgdata/18-main

 config_dir: /pgdata/18-main

 bin_dir: /usr/lib/postgresql/18/bin

 pgpass: /pgdata/.pgpass_patroni

 authentication:

   superuser:

     username: postgres

     password: postgres-password

   replication:

     username: replicator

     password: replicator-password

 remove_data_directory_on_rewind_failure: false

 remove_data_directory_on_diverged_timelines: false

 use_unix_socket: true

 parameters:

   unix_socket_directories: /var/run/postgresql

 

watchdog:

 mode: off

 device: /dev/watchdog

 safety_margin: 5

 

tags:

 nofailover: false

 noloadbalance: false

 clonefrom: false

 nosync: false

patroni-2

scope: patroni-cluster

name: patroni-2

namespace: /service

 

restapi:

 listen: 10.0.0.12:8008

 connect_address: 10.0.0.12:8008

 

etcd3:

 hosts: 10.0.0.1:2379,10.0.0.2:2379,10.0.0.3:2379

 

bootstrap:

 method: initdb

 dcs:

   ttl: 30

   loop_wait: 10

   retry_timeout: 10

   maximum_lag_on_failover: 1048576

 initdb:

   - data-checksums

 postgresql:

   use_pg_rewind: true

   use_slots: true

   parameters:

     superuser_reserved_connections: 5

     max_connections: 100

     shared_buffers: 512MB

     effective_cache_size: 4GB

     work_mem: 128MB

     maintenance_work_mem: 256MB

     random_page_cost: 4

     effective_io_concurrency: 2

     huge_pages: try

     checkpoint_timeout: 15min

     wal_level: replica

     wal_compression: on

     max_wal_senders: 10

     synchronous_commit: on

     max_replication_slots: 10

     min_wal_size: 1GB

     max_wal_size: 4GB

     checkpoint_completion_target: 0.9

     wal_buffers: 16MB

     wal_keep_size: 2GB

     default_statistics_target: 1000

     log_timezone: 'Europe/Moscow'

     timezone: 'Europe/Moscow'

     lc_messages: 'en_US.UTF-8'

     lc_monetary: 'en_US.UTF-8'

     lc_numeric: 'en_US.UTF-8'

     lc_time: 'en_US.UTF-8'

     io_method: 'io_uring'

     shared_preload_libraries: 'pg_stat_statements,pg_hint_plan,pg_qualstats'

     jit: off

 

 pg_hba:

   - local all postgres peer

   - host all all 0.0.0.0/0 md5

   - host replication replicator 127.0.0.1/32 md5

   - host replication replicator 10.0.0.11/32 md5

   - host replication replicator 10.0.0.12/32 md5

 

postgresql:

 listen: 10.0.0.12,127.0.0.1:5432

 connect_address: 10.0.0.12:5432

 data_dir: /pgdata/18-main

 config_dir: /pgdata/18-main

 bin_dir: /usr/lib/postgresql/18/bin

 pgpass: /pgdata/.pgpass_patroni

 authentication:

   superuser:

     username: postgres

     password: postgres-password

   replication:

     username: replicator

     password: replicator-password

 remove_data_directory_on_rewind_failure: false

 remove_data_directory_on_diverged_timelines: false

 use_unix_socket: true

 parameters:

   unix_socket_directories: /var/run/postgresql

 

watchdog:

 mode: off

 device: /dev/watchdog

 safety_margin: 5

 

tags:

 nofailover: false

 noloadbalance: false

 clonefrom: false

 nosync: false

Описание параметров:

Параметр Описание
scope Название кластера
namespace Путь в хранилище конфигурации, где Patroni будет хранить информацию о кластере. Значение по умолчанию: «/service»
name Имя хоста. Должно быть уникальным для кластера
restapi
listen IP-адрес (или имя хоста) и порт, который Patroni будет прослушивать для REST API
connect_address IP-адрес (или имя хоста) и порт для доступа к REST API Patroni. Все члены кластера должны иметь возможность подключаться к этому адресу
bootstrap
method Специальный скрипт, который будет использоваться для начальной загрузки этого кластера
initdb (необязательно) Список параметров, которые будут переданы в initdb
dcs Глобальная динамическая конфигурация кластера
pg_hba Список строк, которые Patroni будет использовать для создания pg_hba.conf
postgresql.use_pg_rewind Использовать pg_rewind. Обратите внимание, что либо кластер должен быть инициализирован с использованием контрольных сумм страниц данных (опция --data-checksums для initdb) и/или для параметра wal_log_hints должно быть установлено значение on, либо pg_rewind не будет работать
postgresql.use_slots Использовать replication slots
postgresql.parameters Список настроек конфигурации для Postgres. Мы рекомендуем воспользоваться "калькулятором" конфигурации Postgres для тонкой настройки конфигурации для вашего сервера (vCPU, RAM, max connections и т.д.)
etcd или etcd3 Настройка подключения к etcd кластеру. Для версии кластера etcd v3 используйте etcd3
postgresql
listen IP-адрес + порт, который слушает Postgres; должен быть доступен с других узлов кластера, если вы используете потоковую репликацию. Допускается использование нескольких адресов, разделенных запятыми, при условии, что компонент порта добавляется после последнего через двоеточие, т. е. прослушивание: 127.0.0.1 , 127.0.0.2:5432 . Patroni будет использовать первый адрес из этого списка для установки локального подключения к узлу PostgreSQL.
connect_address IP-адрес + порт, через который Postgres доступен из других нод и приложений.
authentication.superuser Суперпользователь, задается во время инициализации (initdb) и позже используется Patroni для подключения к postgres.
authentication.replication Пользователь репликации; будет создан во время инициализации. Реплики будут использовать этого пользователя для доступа к источнику репликации посредством потоковой репликации.
data_dir Расположение каталога данных Postgres, существующего или инициализируемого Patroni
config_dir Расположение каталога конфигурации Postgres по умолчанию — каталог данных. Должен быть доступен для записи Patroni.
pgpass Путь к файлу паролей .pgpass. Patroni создает этот файл перед выполнением pg_basebackup, сценария post_init и при некоторых других обстоятельствах. Местоположение должно быть доступно для записи Patroni.
remove_data_directory_on_rewind_failure Если этот параметр включен, Patroni удалит каталог данных PostgreSQL и заново создаст реплику. В противном случае он попытается следовать за новым лидером. Значение по умолчанию — false.
remove_data_directory_on_diverged_timelines Patroni удалит каталог данных PostgreSQL и заново создаст реплику, если заметит, что сроки расходятся и бывший основной сервер не может начать потоковую передачу с нового основного сервера. Эта опция полезна, когда pg_rewind невозможно использовать. При выполнении проверки расхождения сроков в PostgreSQL v10 и более ранних версиях Patroni попытается подключиться с учетными данными репликации к базе данных «postgres». Следовательно, такой доступ должен быть разрешен в файле pg_hba.conf. Значение по умолчанию —false.
use_unix_socket Указывает, что Patroni предпочтет использовать сокеты unix для подключения к кластеру. Значение по умолчанию — false. Если определен unix_socket_directories, Patroni будет использовать первое подходящее значение для подключения к кластеру. Если подключение не удастся, то Patroni вернется к использованию tcp, . Если unix_socket_directories не указан в postgresql.parameters, Patroni будет использовать значение по умолчанию, и опустит хост в параметрах соединения.
parameters Список настроек конфигурации для Postgres

4. Включите и запустите службу patroni, проверьте статус

sudo systemctl enable patroni

sudo systemctl start patroni

sudo systemctl status patroni

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

patronictl -c /etc/patroni/config.yml list

Настройка HAProxy

1. Установите HAProxy

sudo apt-get update

sudo apt-get install -y haproxy

2. Отредактируйте конфигурацию /etc/haproxy/haproxy.cfg

sudo vim /etc/haproxy/haproxy.cfg

global

   maxconn 100

   log 127.0.0.1 local2

 

defaults

   log global

   mode tcp

   retries 2

   timeout client 30m

   timeout connect 4s

   timeout server 30m

   timeout check 5s

 

listen stats

   mode http

   bind *:7000

   stats enable

   stats uri /

 

listen production

   bind *:5432

   option httpchk OPTIONS/master

   http-check expect status 200

   default-server inter 3s fall 3 rise 2 on-marked-down shutdown-sessions

   server patroni-01 10.0.0.11:5432 maxconn 100 check port 8008

   server patroni-02 10.0.0.12:5432 maxconn 100 check port 8008

 

listen standby

   bind *:5433

   option httpchk OPTIONS/replica

   http-check expect status 200

   default-server inter 3s fall 3 rise 2 on-marked-down shutdown-sessions

   server patroni-01 10.0.0.11:5432 maxconn 100 check port 8008

   server patroni-02 10.0.0.12:5432 maxconn 100 check port 8008

3. Проверьте конфигурацию и перезапустите службу HAProxy

sudo haproxy -f /etc/haproxy/haproxy.cfg -c

sudo systemctl restart haproxy

sudo systemctl status haproxy

sudo systemctl enable haproxy

Настройка KeepAlived

1. Установите Keepalived

sudo apt-get update

sudo apt-get install -y keepalived

2. Выделите/определите виртуальный ip, который будет использоваться keepalived. В нашем примере это 192.168.162.10 и интерфейс, на котором он будет настроен - ens160

ip a

inet 10.0.0.21/24 metric 100 brd 10.0.0.255 scope global dynamic ens160

3. Создайте конфигурацию `/etc/keepalived/keepalived.conf

sudo vim /etc/keepalived/keepalived.conf

haproxy-1

vrrp_instance pg-keepalived {

state MASTER

interface ens160

virtual_router_id 1

priority 11

virtual_ipaddress {

10.0.0.20/29 dev ens160 label ens160:1

}

}

haproxy-2

vrrp_instance pg-keepalived {

state SLAVE

interface ens160

virtual_router_id 1

priority 10

virtual_ipaddress {

10.0.0.20/29 dev ens160 label ens160:1

}

}

 

Описание параметров:

Параметр Описание
vrrp_instance Имя кластера
state Роль сервера, master или slave
interface Имя сетевого интерфейса
virtual_router_id Идентификатор «виртуального роутера», должен быть одинаковым на всех серверахбалансировщиках
priority Приоритет балансировщиков, чем выше цифра тем больше приоритет, самый высокий следует выставлять для master сервера
virtual_ipaddress Виртуальный IP

4. Включите и запустите службу keepalived, проверьте статус

sudo systemctl enable keepalived

sudo systemctl start keepalived

sudo systemctl status keepalived

5. На master ноде проверьте, что появился новый (виртуальный) IP адрес в сетевом интерфейсе

ip a

inet 10.0.0.20/29 scope global ens160:1

Данный IP используйте для поключения к postgresql.

Настройка пользователей и баз данных в PSQL

1. Авторизуйтесь в PSQL, подключившись пользователем Postgres, которого мы создали ранее, используйте ваш PG клиент, мы будем использовать PSQL. В качестве точки подключения используйте виртуальный ip или ip мастер ноды postgres

psql -h 10.0.0.20 -p 5432 -U postgres -d postgres

2. Активируйте расширения

-- Загрузка pg_hint_plan

LOAD 'pg_hint_plan';

 

-- Создание расширений

CREATE EXTENSION IF NOT EXISTS plpgsql SCHEMA pg_catalog;

CREATE EXTENSION IF NOT EXISTS rum SCHEMA public;

CREATE EXTENSION IF NOT EXISTS pgcrypto SCHEMA public;

CREATE EXTENSION IF NOT EXISTS pg_buffercache SCHEMA public;

CREATE EXTENSION IF NOT EXISTS btree_gin SCHEMA public;

CREATE EXTENSION IF NOT EXISTS pg_stat_statements SCHEMA public;

CREATE EXTENSION IF NOT EXISTS pg_trgm SCHEMA public;

CREATE EXTENSION IF NOT EXISTS pg_qualstats SCHEMA public;

CREATE EXTENSION IF NOT EXISTS vector SCHEMA public;

CREATE EXTENSION IF NOT EXISTS pg_background SCHEMA public;

3. Создайте пользователей:

create user dbo with superuser createdb createrole inherit login password 'password';

create user d10taskuser with inherit login password 'password';

create user migrationsdaemon with inherit login password 'password';

create user rebus with inherit login password 'password';

create user implementer with inherit login password 'password';

 

CREATE ROLE role_D10TaskReader WITH INHERIT;

CREATE USER D10TaskReader WITH INHERIT LOGIN PASSWORD 'pass6';

GRANT role_D10TaskReader TO D10TaskReader;

ALTER USER D10TaskReader SET search_path = "dbo", "public";

4. Создайте базы данных d10task и d10task_taskfiles

create database d10task

template template0

owner dbo

encoding 'utf8'

lc_collate 'ru_RU.utf8'

lc_ctype 'ru_RU.utf8';

 

create database d10task_taskfiles

template template0

owner dbo

encoding 'utf8'

lc_collate 'ru_RU.utf8'

lc_ctype 'ru_RU.utf8';

5. Создайте схемы в базе taskfilesdb

\c d10task_taskfiles

 

create schema if not exists dbo authorization dbo;

create table dbo.UploadFiles

(

id int not null generated by default as identity,

FileContent bytea,

Ext varchar,

UserID int,

FileName varchar,

Compressed bool constraint DF_UploadFiles_Compressed default false,

constraint PK_UploadFiles primary key (id)

);
 
alter user d10taskuser set search_path = "dbo";

 

grant select, insert, update, delete, truncate on all tables in schema dbo to d10taskuser;

grant usage, select on all sequences in schema dbo to d10taskuser;

grant execute on all functions in schema dbo to d10taskuser;

alter default privileges in schema dbo grant select, insert, update, delete, truncate on tables to d10taskuser;

alter default privileges in schema dbo grant usage, select on sequences to d10taskuser;

alter default privileges in schema dbo grant execute on functions to d10taskuser;

alter default privileges in schema dbo grant usage on types to d10taskuser;

grant usage on schema dbo to d10taskuser;

6. Создайте (получите) дамп базы данных "Первой Формы" (d10task). Выполните рестор в созданную базу d10task

pg_restore -h 10.0.0.20 -p 5432 -U postgres -d d10task ./d10task-template.dump

7. Настройте схемы для пользователей в новой восстановленной базе

psql -h 10.0.0.20 -p 5432 -U postgres -d d10task

 

-- Загрузка pg_hint_plan

LOAD 'pg_hint_plan';

 

-- Создание расширений

CREATE EXTENSION IF NOT EXISTS plpgsql SCHEMA pg_catalog;

CREATE EXTENSION IF NOT EXISTS rum SCHEMA public;

CREATE EXTENSION IF NOT EXISTS pgcrypto SCHEMA public;

CREATE EXTENSION IF NOT EXISTS pg_buffercache SCHEMA public;

CREATE EXTENSION IF NOT EXISTS btree_gin SCHEMA public;

CREATE EXTENSION IF NOT EXISTS pg_stat_statements SCHEMA public;

CREATE EXTENSION IF NOT EXISTS pg_trgm SCHEMA public;

CREATE EXTENSION IF NOT EXISTS pg_qualstats SCHEMA public;

CREATE EXTENSION IF NOT EXISTS vector SCHEMA public;

CREATE EXTENSION IF NOT EXISTS pg_background SCHEMA public;

 

alter role D10TaskUser set search_path = "dbo", "public";

alter role dbo set search_path = "dbo", "public";

alter user MigrationsDaemon set search_path = "dbo", "public";

alter user rebus set search_path = "rebus", "public";

 

grant usage on schema dbo to d10taskuser;

grant dbo, rebus to MigrationsDaemon;

 

grant all on all tables in schema dbo, sys to dbo, MigrationsDaemon;

grant all on all sequences in schema dbo, sys to dbo, MigrationsDaemon;

grant all on all functions in schema dbo, sys to dbo, MigrationsDaemon;

grant all on schema dbo, sys to dbo, MigrationsDaemon;

alter default privileges in schema dbo, sys, SignalR grant all on tables to dbo, MigrationsDaemon;

alter default privileges in schema dbo, sys, SignalR grant all on sequences to dbo, MigrationsDaemon;

alter default privileges in schema dbo, sys, SignalR grant all on functions to dbo, MigrationsDaemon;

alter default privileges in schema dbo, sys, SignalR grant all on types to dbo, MigrationsDaemon;

 

 

grant usage on schema dbo, sys, SignalR to role_D10TaskReader;

grant select on all tables in schema dbo, sys, SignalR to role_D10TaskReader;

grant usage, select on all sequences in schema dbo, sys, SignalR to role_D10TaskReader;

grant execute on all functions in schema dbo, sys, SignalR to role_D10TaskReader;

alter default privileges in schema dbo, sys, SignalR  grant select  on tables to role_D10TaskReader;

alter default privileges in schema dbo, sys, SignalR  grant execute on functions to role_D10TaskReader;

alter default privileges in schema dbo, sys, SignalR  grant usage, select on sequences to role_D10TaskReader;

grant all on all tables in schema custom to role_D10TaskReader;

grant all on all sequences in schema custom to role_D10TaskReader;

grant all on all functions in schema custom to role_D10TaskReader;

alter default privileges in schema custom grant all on tables to role_D10TaskReader;

alter default privileges in schema custom grant all on sequences to role_D10TaskReader;

alter default privileges in schema custom grant all on functions to role_D10TaskReader;

alter default privileges in schema custom grant all on types to role_D10TaskReader;

grant all on schema custom to role_D10TaskReader;

grant all on all tables in schema rebus to role_D10TaskReader;

grant all on all sequences in schema rebus to role_D10TaskReader;

grant all on all functions in schema rebus to role_D10TaskReader;

alter default privileges in schema rebus grant all on tables to role_D10TaskReader;

alter default privileges in schema rebus grant all on sequences to role_D10TaskReader;

alter default privileges in schema rebus grant all on functions to role_D10TaskReader;

alter default privileges in schema rebus grant all on types to role_D10TaskReader;

grant all on schema rebus to role_D10TaskReader;

grant usage on language plpgsql, sql to role_D10TaskReader;

 

 

GRANT USAGE ON SCHEMA dbadmin TO d10taskuser;

GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA dbadmin TO d10taskuser;

GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA dbadmin TO d10taskuser;

GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA dbadmin TO d10taskuser;

 

GRANT EXECUTE ON FUNCTION pg_background_launch(text, int4) TO dbo;

GRANT EXECUTE ON FUNCTION pg_background_result(int4) TO dbo;

GRANT EXECUTE ON FUNCTION pg_background_detach(int4) TO dbo;

Устранение неполадок

Проблема: Ошибка "Too many open files" при io_uring

Симптомы:

FATAL:  could not setup io_uring queue: Too many open files

HINT:  Consider increasing "ulimit -n" to at least 2542.

Решение: На двух серверах PG необходимо внести изменения в ограничения файлов

# 1. Редактирование systemd unit файла

sudo vim /lib/systemd/system/patroni.service

Добавить в секцию [Service]:

[Service]

...

# Limits

LimitNOFILE=65535

# 2. Перезагрузка конфигурации systemd

sudo systemctl daemon-reload

# 3. Перезапуск PostgreSQL

sudo systemctl restart patroni.service

# 4. Проверка статуса

sudo systemctl status patroni

Заключение

На этом настройка отказоустойчивого кластера завершена. Используйте virtual ip в настройках подключения приложения "Первой Формы".

Допускается совмещение ролей на серверах. Например, в случае использования трёх и более нод Postgres, вы можете разместить etcd на этих же нодах.