﻿# Кластер PostgreSQL

> [HTML Version](configure-postgresql.html)

В статье описана установка PostgreSQL 13 для ОС Ubuntu Linux 20.04 и 22.04. Смотрите поддерживаемые версии PostgreSQL для корректной работы системы в статье [«Системные требования ELMA365 On-Premises»](elma365-enterprise-on-premises.md#postgresql). Также вы можете ознакомиться с руководством в [официальной документации PostgreSQL](https://www.postgresql.org/docs/13/high-availability.html).

Установка состоит из нескольких этапов:

1. [Подготовка нод (серверов)](#preparation-node).

2. [Подготовка кластера etcd](#preparation-etcd).

3. [Установка PostgreSQL](#install-postgresql).

4. [Настройка PostgreSQL](#setting-postgresql).

5. [Установка Patroni](#install-patroni).

6. [Настройка Patroni](#setting-patroni).

7. [Подготовка кластера PostgreSQL+Patroni](#preparation-postgresql-patroni).

8. [Подготовка PGBouncer (опционально)](#prepare-pgbouncer).

9. [Конфигурация HAProxy (блок postgres)](#haproxy-configuration).

10. [Подключение к PostgreSQL](#connecting-to-postgresql).

## Шаг 1. Подготовка нод (серверов)

Создайте три ноды (сервера) с последовательно пронумерованными именами хостов.

````
начало внимание

````
Минимальное количество серверов для организации кластера — три.

````
конец внимание

````
В этом примере используется три узла со следующими hostname и IP-адресами:

- **postgres-server1.your\_domain, 192.168.1.1**;

- **postgres-server2.your\_domain, 192.168.1.2**;

- **postgres-server3.your\_domain, 192.168.1.3**.

Создайте необходимые сопоставления имён хостов в DNS. Если такой возможности нет, внесите нужные записи в \[OBJECT\].

## Шаг 2. Подготовка кластера etcd

1. Установите \[OBJECT\] на все узлы:

````
sudo apt-get install etcd -y

2. ````
Остановите \[OBJECT\] на всех узлах:

````
sudo systemctl stop etcd

3. ````
Удалите каталог данных:

````
sudo rm -rf /var/lib/etcd/\*

4. ````
Переместите конфигурационный файл по умолчанию:

````
sudo mv /etc/default/etcd\{,.original\}

5. ````
Создайте и откройте для редактирования новый конфигурационный файл:

````
sudo nano /etc/default/etcd

6. ````
Добавьте пример конфигураций в файл для узла** postgres-server1.your\_domain**:

````
ETCD\_NAME="postgres-server1"  
ETCD\_DATA\_DIR="/var/lib/etcd/default"  
ETCD\_HEARTBEAT\_INTERVAL="1000"  
ETCD\_ELECTION\_TIMEOUT="5000"  
ETCD\_LISTEN\_PEER\_URLS="http://192.168.1.1:2380"  
ETCD\_LISTEN\_CLIENT\_URLS="http://192.168.1.1:2379,http://localhost:2379"  
ETCD\_INITIAL\_ADVERTISE\_PEER\_URLS="http://192.168.1.1:2380"  
ETCD\_INITIAL\_CLUSTER="postgres-server1=http://192.168.1.1:2380,postgres-server2=http://192.168.1.2:2380,postgres-server3=http://192.168.1.3:2380"  
ETCD\_INITIAL\_CLUSTER\_STATE="new"  
ETCD\_INITIAL\_CLUSTER\_TOKEN="etcd-postgres-cluster"  
ETCD\_ADVERTISE\_CLIENT\_URLS="http://192.168.1.1:2379"  
ETCD\_ENABLE\_V2="true"  
ETCD\_INITIAL\_ELECTION\_TICK\_ADVANCE="false"

````
Пример конфигураций с включением TLS для узла postgres-server1.your\_domain

````
ETCD\_NAME="postgres-server1"  
ETCD\_DATA\_DIR="/var/lib/etcd/default"  
ETCD\_HEARTBEAT\_INTERVAL="1000"  
ETCD\_ELECTION\_TIMEOUT="5000"  
ETCD\_LISTEN\_PEER\_URLS="https://192.168.1.1:2380"  
ETCD\_LISTEN\_CLIENT\_URLS="https://192.168.1.1:2379,https://localhost:2379"  
ETCD\_INITIAL\_ADVERTISE\_PEER\_URLS="https://postgres-server1.your\_domain:2380"  
ETCD\_INITIAL\_CLUSTER="postgres-server1=https://postgres-server1.your\_domain:2380,postgres-server2=https://postgres-server2.your\_domain:2380,postgres-server3=https://postgres-server3.your\_domain:2380"  
ETCD\_INITIAL\_CLUSTER\_STATE="new"  
ETCD\_INITIAL\_CLUSTER\_TOKEN="etcd-postgres-cluster"  
ETCD\_ADVERTISE\_CLIENT\_URLS="https://postgres-server1.your\_domain:2379"  
ETCD\_ENABLE\_V2="true"  
ETCD\_CERT\_FILE="/path/to/public.crt"  
ETCD\_KEY\_FILE="/path/to/private.key"  
ETCD\_CLIENT\_CERT\_AUTH="true"  
ETCD\_TRUSTED\_CA\_FILE="/path/to/certCA.pem"  
ETCD\_PEER\_CERT\_FILE="/path/to/public.crt"  
ETCD\_PEER\_KEY\_FILE="/path/to/private.key"  
ETCD\_PEER\_CLIENT\_CERT\_AUTH="true"  
ETCD\_PEER\_TRUSTED\_CA\_FILE="/path/to/certCA.pem"  
ETCD\_INITIAL\_ELECTION\_TICK\_ADVANCE="false"
````

7. ````
Добавьте пример конфигураций в файл для узла **postgres-server2.your\_domain**:

````
ETCD\_NAME="postgres-server2"  
ETCD\_DATA\_DIR="/var/lib/etcd/default"  
ETCD\_HEARTBEAT\_INTERVAL="1000"  
ETCD\_ELECTION\_TIMEOUT="5000"  
ETCD\_LISTEN\_PEER\_URLS="http://192.168.1.2:2380"  
ETCD\_LISTEN\_CLIENT\_URLS="http://192.168.1.2:2379,http://127.0.0.1:2379"  
ETCD\_INITIAL\_ADVERTISE\_PEER\_URLS="http://192.168.1.2:2380"  
ETCD\_INITIAL\_CLUSTER="postgres-server1=http://192.168.1.1:2380,postgres-server2=http://192.168.1.2:2380,postgres-server3=http://192.168.1.3:2380"  
ETCD\_INITIAL\_CLUSTER\_STATE="new"  
ETCD\_INITIAL\_CLUSTER\_TOKEN="etcd-postgres-cluster"  
ETCD\_ADVERTISE\_CLIENT\_URLS="http://192.168.1.2:2379"  
ETCD\_ENABLE\_V2="true"  
ETCD\_INITIAL\_ELECTION\_TICK\_ADVANCE="false"

````
Пример конфигураций с включением TLS для узла postgres-server2.your\_domain

````
ETCD\_NAME="postgres-server2"  
ETCD\_DATA\_DIR="/var/lib/etcd/default"  
ETCD\_HEARTBEAT\_INTERVAL="1000"  
ETCD\_ELECTION\_TIMEOUT="5000"  
ETCD\_LISTEN\_PEER\_URLS="https://192.168.1.2:2380"  
ETCD\_LISTEN\_CLIENT\_URLS="https://192.168.1.2:2379,https://localhost:2379"  
ETCD\_INITIAL\_ADVERTISE\_PEER\_URLS="https://postgres-server2.your\_domain:2380"  
ETCD\_INITIAL\_CLUSTER="postgres-server1=https://postgres-server1.your\_domain:2380,postgres-server2=https://postgres-server2.your\_domain:2380,postgres-server3=https://postgres-server3.your\_domain:2380"  
ETCD\_INITIAL\_CLUSTER\_STATE="new"  
ETCD\_INITIAL\_CLUSTER\_TOKEN="etcd-postgres-cluster"  
ETCD\_ADVERTISE\_CLIENT\_URLS="https://postgres-server2.your\_domain:2379"  
ETCD\_ENABLE\_V2="true"  
ETCD\_CERT\_FILE="/path/to/public.crt"  
ETCD\_KEY\_FILE="/path/to/private.key"  
ETCD\_CLIENT\_CERT\_AUTH="true"  
ETCD\_TRUSTED\_CA\_FILE="/path/to/certCA.pem"  
ETCD\_PEER\_CERT\_FILE="/path/to/public.crt"  
ETCD\_PEER\_KEY\_FILE="/path/to/private.key"  
ETCD\_PEER\_CLIENT\_CERT\_AUTH="true"  
ETCD\_PEER\_TRUSTED\_CA\_FILE="/path/to/certCA.pem"  
ETCD\_INITIAL\_ELECTION\_TICK\_ADVANCE="false"
````

8. ````
Добавьте пример конфигураций в файл для узла **postgres-server3.your\_domain**:

````
ETCD\_NAME="postgres-server3"  
ETCD\_DATA\_DIR="/var/lib/etcd/default"  
ETCD\_HEARTBEAT\_INTERVAL="1000"  
ETCD\_ELECTION\_TIMEOUT="5000"  
ETCD\_LISTEN\_PEER\_URLS="http://192.168.1.3:2380"  
ETCD\_LISTEN\_CLIENT\_URLS="http://192.168.1.3:2379,http://localhost:2379"  
ETCD\_INITIAL\_ADVERTISE\_PEER\_URLS="http://192.168.1.3:2380"  
ETCD\_INITIAL\_CLUSTER="postgres-server1=http://192.168.1.1:2380,postgres-server2=http://192.168.1.2:2380,postgres-server3=http://192.168.1.3:2380"  
ETCD\_INITIAL\_CLUSTER\_STATE="new"  
ETCD\_INITIAL\_CLUSTER\_TOKEN="etcd-postgres-cluster"  
ETCD\_ADVERTISE\_CLIENT\_URLS="http://192.168.1.3:2379"  
ETCD\_ENABLE\_V2="true"  
ETCD\_INITIAL\_ELECTION\_TICK\_ADVANCE="false"

````
Пример конфигураций с включением TLS для узла postgres-server3.your\_domain

````
ETCD\_NAME="postgres-server3"  
ETCD\_DATA\_DIR="/var/lib/etcd/default"  
ETCD\_HEARTBEAT\_INTERVAL="1000"  
ETCD\_ELECTION\_TIMEOUT="5000"  
ETCD\_LISTEN\_PEER\_URLS="https://192.168.1.3:2380"  
ETCD\_LISTEN\_CLIENT\_URLS="https://192.168.1.3:2379,https://localhost:2379"  
ETCD\_INITIAL\_ADVERTISE\_PEER\_URLS="https://postgres-server3.your\_domain:2380"  
ETCD\_INITIAL\_CLUSTER="postgres-server1=https://postgres-server1.your\_domain:2380,postgres-server2=https://postgres-server2.your\_domain:2380,postgres-server3=https://postgres-server3.your\_domain:2380"  
ETCD\_INITIAL\_CLUSTER\_STATE="new"  
ETCD\_INITIAL\_CLUSTER\_TOKEN="etcd-postgres-cluster"  
ETCD\_ADVERTISE\_CLIENT\_URLS="https://postgres-server3.your\_domain:2379"  
ETCD\_ENABLE\_V2="true"  
ETCD\_CERT\_FILE="/path/to/public.crt"  
ETCD\_KEY\_FILE="/path/to/private.key"  
ETCD\_CLIENT\_CERT\_AUTH="true"  
ETCD\_TRUSTED\_CA\_FILE="/path/to/certCA.pem"  
ETCD\_PEER\_CERT\_FILE="/path/to/public.crt"  
ETCD\_PEER\_KEY\_FILE="/path/to/private.key"  
ETCD\_PEER\_CLIENT\_CERT\_AUTH="true"  
ETCD\_PEER\_TRUSTED\_CA\_FILE="/path/to/certCA.pem"  
ETCD\_INITIAL\_ELECTION\_TICK\_ADVANCE="false"
````

````
Рассмотрим введённые параметры:

- \[OBJECT\] — имя этого узла кластера. Должно быть уникально в кластере;

- \[OBJECT\] — точка подключения для клиентов кластера;

- \[OBJECT\] — список URL-адресов, по которым его могут найти остальные узлы кластера;

- \[OBJECT\] — точка подключения для остальных узлов кластера;

- \[OBJECT\] — начальный список URL-адресов, по которым его могут найти остальные узлы кластера;

- \[OBJECT\] — токен кластера, должен совпадать на всех узлах кластера;

- \[OBJECT\] — список узлов кластера на момент запуска;

- \[OBJECT\] — может принимать два значения: \[OBJECT\] и \[OBJECT\];

- \[OBJECT\] — расположение каталога данных кластера;

- \[OBJECT\] — время в миллисекундах, которое проходит между последним принятым оповещением от лидера кластера, до попытки захватить роль лидера на ведомом узле;

- \[OBJECT\] — время в миллисекундах между рассылками лидером оповещений о том, что он всё ещё лидер;

- \[OBJECT\] — путь до файла сертификата сервера;

- \[OBJECT\] — путь до файла закрытого ключа;

- \[OBJECT\] — путь до файла корневого CA;

- \[OBJECT\] — может принимать два значения: \[OBJECT\] и \[OBJECT\];

- \[OBJECT\] — путь до файла сертификата сервера;

- \[OBJECT\] — путь до файла закрытого ключа;

- \[OBJECT\] — путь до файла корневого CA;

- \[OBJECT\] — может принимать два значения: \[OBJECT\] и \[OBJECT\].

9. Перезапустите \[OBJECT\] на всех узлах:

````
sudo systemctl restart etcd

10. ````
Проверьте состояние кластера.

Для кластера без TLS:

````
sudo etcdctl cluster-health

````
Для кластера c TLS:

````
sudo etcdctl -C https://postgres-server1.your\_domain:2379 --key-file /path/to/private.key --cert-file /path/to/public.crt --ca-file /path/to/certCA.pem cluster-health

## ````
Шаг 3. Установка PostgreSQL

````
начало внимание

````
С аппаратными требованиями, необходимыми для корректной работы ELMA365 на PostgreSQL, можно ознакомиться в статье [«Системные требования ELMA365 On-Premises»](elma365-enterprise-on-premises.md#postgresql).

````
конец внимание

1. ````
Для установки PostgreSQL добавьте официальный репозиторий \[OBJECT\]:

````
sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt \$(lsb\_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'  
wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -

2. ````
Обновите кеш пакетов, выполнив команду:

````
sudo apt update

3. ````
Установите PostgreSQL на все узлы:

````
sudo apt install postgresql-13 -y

## ````
Шаг 4. Настройка PostgreSQL

````
начало примечание

````
**Примечание**

Для пароля разрешается применять следующие символы:

- Заглавные латинские буквы: от A до Z;

- Строчные латинские буквы: от a до z;

- Цифры от 0 до 9;

- Символы:  -\_.

Зарезервированные (недопустимые) символы:

\! \* ' ( ) ; : @ \& = + \$ , / ? % # \[ \]

````
конец примечание

#### ````
Действия для узла postgres-server1.your\_domain:

1. Создайте новую роль \[OBJECT\] с паролем **SecretPassword**:

````
sudo -u postgres psql -c \\  
"CREATE ROLE elma365 WITH login password 'SecretPassword';"

2. ````
Создайте базу данных \[OBJECT\] с базовой локалью и назначьте выделенного пользователя **elma365 **её владельцем:

````
sudo -u postgres psql -c \\  
"CREATE DATABASE elma365 WITH OWNER elma365;"

````
Создание базы данных с локалью ru\_RU.UTF-8

  
Вы можете создать базу данных **elma365** с локалью **ru\_RU.UTF-8**. Это позволит улучшить работу механизмов сортировки и индексирования русскоязычных данных, а также ускорить выполнение поисковых и текстовых операций. Для этого:

1. Убедитесь, что локаль ru\_RU.UTF-8 доступна в системе:

````
locale -a | grep ru\_RU

````
  
При наличии локали отобразится её название.

2. Если в системе отсутствует локаль **ru\_RU.UTF-8**, установите её, выполнив команду:

````
sudo locale-gen ru\_RU.UTF-8 \&\& sudo update-locale

````
  
После установки перезагрузите сервис PostgreSQL для применения изменений:

````
sudo systemctl restart postgresql

3. ````
Создайте базу данных с локалью** ru\_RU.UTF-8**:

````
sudo -u postgres psql -c "CREATE DATABASE elma365 WITH OWNER = elma365  
LOCALE\_PROVIDER = icu ICU\_LOCALE = 'ru-RU' ENCODING = 'UTF8' LC\_COLLATE =  
'ru\_RU.UTF-8' LC\_CTYPE = 'ru\_RU.UTF-8' TEMPLATE = template0;"
````

3. ````
Добавьте необходимые расширения для базы данных \[OBJECT\]:

````
sudo -u postgres psql -d elma365 -c \\  
"CREATE EXTENSION \\"uuid-ossp\\"; CREATE EXTENSION pg\_trgm;"

4. ````
Создайте новую роль \[OBJECT\] с паролем **ReplicatorPassword** для работы с репликами. Должно совпадать с настройками **Patroni** из блока \[OBJECT\] и списком разрешённых хостов postgresql в файле \[OBJECT\]:

````
sudo -u postgres psql -c \\  
"CREATE USER replicator WITH REPLICATION ENCRYPTED PASSWORD 'ReplicatorPassword';"

5. ````
Установите пароль для пользователя **postgres**:

````
sudo -u postgres psql -c "ALTER USER postgres PASSWORD 'PostgresPassword';"

6. ````
Остановите PostgreSQL:

````
systemctl stop postgresql

#### ````
Действия для узла postgres-server2.your\_domain и postgres-server3.your\_domain:

1.  Остановите PostgreSQL:

````
systemctl stop postgresql

2. ````
Удалите каталог данных на нодах **postgres-server2.your\_domain** и **postgres-server3.your\_domain**:

````
rm -rf /var/lib/postgresql/13/main

## ````
Шаг 5. Установка Patroni

1. Установите Patroni и PIP на все узлы:

````
sudo apt-get install python3-pip python3-dev libpq-dev -y  
sudo apt-get install patroni -y

2. ````
Установите зависимости для работы Patroni на все узлы:

````
pip3 install psycopg2-binary  
pip3 install wheel  
pip3 install python-etcd

## ````
Шаг 6. Настройка Patroni

1. Создайте файл настроек:

````
sudo nano /etc/patroni/config.yml

2. ````
В созданный файл \[OBJECT\] нужно поместить пример начальной конфигурации, изменив ip-адреса на свои на каждом узле кластера. Обратите внимание на комментарии в данном файле.

Пример начальной конфигурации

````
scope: postgres-cluster # одинаковое значение на всех узлах  
name: postgresql-server1 # разное значение на всех узлах  
namespace: /service/ # одинаковое значение на всех узлах  
  
restapi:  
  listen: postgres-server1.your\_domain:8008 # адрес узла, на котором находится этот файл  
  connect\_address: postgres-server1.your\_domain:8008 # адрес узла, на котором находится этот файл  
  
etcd:  
  hosts: postgres-server1.your\_domain:2379,postgres-server2.your\_domain:2379,postgres-server3.your\_domain:2379 # список всех узлов, на которых установлен etcd  
  
bootstrap:  
  method: initdb  
  dcs:  
    ttl: 30  
    loop\_wait: 10  
    retry\_timeout: 10  
    maximum\_lag\_on\_failover: 1048576  
    master\_start\_timeout: 300  
    synchronous\_mode: false  
    synchronous\_mode\_strict: false  
    synchronous\_node\_count: 1  
    postgresql:  
      use\_pg\_rewind: true  
      use\_slots: true  
      parameters:  
        max\_connections: 2000  
        superuser\_reserved\_connections: 5  
        max\_locks\_per\_transaction: 64  
        max\_prepared\_transactions: 0  
        huge\_pages: try  
        shared\_buffers: 512MB  
        work\_mem: 128MB  
        maintenance\_work\_mem: 256MB  
        effective\_cache\_size: 4GB  
        checkpoint\_timeout: 15min  
        checkpoint\_completion\_target: 0.9  
        wal\_compression: on  
        min\_wal\_size: 2GB  
        max\_wal\_size: 4GB  
        wal\_buffers: 32MB  
        default\_statistics\_target: 1000  
        seq\_page\_cost: 1  
        random\_page\_cost: 4  
        effective\_io\_concurrency: 2  
        synchronous\_commit: on  
        autovacuum: on  
        autovacuum\_max\_workers: 5  
        autovacuum\_vacuum\_scale\_factor: 0.1  
        autovacuum\_analyze\_scale\_factor: 0.05  
        autovacuum\_vacuum\_cost\_limit: 200  
        autovacuum\_vacuum\_cost\_delay: 20  
        autovacuum\_naptime: 15s  
        max\_files\_per\_process: 4096  
        archive\_mode: on  
        archive\_timeout: 1800s  
        archive\_command: cd .  
        wal\_level: replica  
        wal\_keep\_segments: 130  
        max\_wal\_senders: 10  
        max\_replication\_slots: 10  
        hot\_standby: on  
        hot\_standby\_feedback: True  
        wal\_log\_hints: on  
        shared\_preload\_libraries: pg\_stat\_statements,auto\_explain  
        pg\_stat\_statements.max: 10000  
        pg\_stat\_statements.track: all  
        pg\_stat\_statements.save: off  
        auto\_explain.log\_min\_duration: 10s  
        auto\_explain.log\_analyze: true  
        auto\_explain.log\_buffers: true  
        auto\_explain.log\_timing: false  
        auto\_explain.log\_triggers: true  
        auto\_explain.log\_verbose: true  
        auto\_explain.log\_nested\_statements: true  
        standard\_conforming\_strings: true  
        track\_io\_timing: on  
        log\_lock\_waits: on  
        log\_temp\_files: 3  
        track\_activities: on  
        track\_counts: on  
        track\_functions: all  
        log\_checkpoints: on  
        logging\_collector: on  
        log\_truncate\_on\_rotation: on  
        log\_rotation\_age: 1d  
        log\_rotation\_size: 0  
        log\_line\_prefix: '%t \[%p-%l\] %r %q%u@%d '  
        log\_filename: 'postgresql-%a.log'  
        log\_directory: /var/log/postgresql  
  
  initdb: # List options to be passed on to initdb  
    - encoding: UTF8  
    - locale: en\_US.UTF-8  
    - data-checksums  
  
  pg\_hba: # должен содержать адреса ВСЕХ машин, используемых в кластере  
    - local all postgres peer  
    - local all all peer  
    - host all all 0.0.0.0/0 md5  
    - host replication replicator localhost trust  
    - host replication replicator 192.168.1.1/32 md5  
    - host replication replicator 192.168.1.2/32 md5  
    - host replication replicator 192.168.1.3/32 md5  
  
postgresql:  
  listen: 192.168.1.1,127.0.0.1:5432 # адрес узла, на котором находится этот файл  
  connect\_address: 192.168.1.1:5432 # адрес узла, на котором находится этот файл  
  use\_unix\_socket: true  
  data\_dir: /var/lib/postgresql/13/main # каталог данных  
  bin\_dir: /usr/lib/postgresql/13/bin  
  config\_dir: /etc/postgresql/13/main  
  pgpass: /var/lib/postgresql/.pgpass\_patroni  
  authentication:  
    replication:  
      username: replicator  
      password: ReplicatorPassword  
    superuser:  
      username: postgres  
      password: PostgresPassword  
  parameters:  
    unix\_socket\_directories: /var/run/postgresql  
  pg\_hba: # должен содержать адреса ВСЕХ машин, используемых в кластере  
    - local all postgres peer  
    - local all all peer  
    - host all all 0.0.0.0/0 md5  
    - host replication replicator localhost trust  
    - host replication replicator 192.168.1.1/32 md5  
    - host replication replicator 192.168.1.2/32 md5  
    - host replication replicator 192.168.1.3/32 md5  
  
  remove\_data\_directory\_on\_rewind\_failure: false  
  remove\_data\_directory\_on\_diverged\_timelines: false  
  
  create\_replica\_methods:  
    - basebackup  
  basebackup:  
    max-rate: '100M'  
    checkpoint: 'fast'  
  
watchdog:  
  mode: off # Allowed values: off, automatic, required  
  device: /dev/watchdog  
  safety\_margin: 5  
  
tags:  
  nofailover: false  
  noloadbalance: false  
  clonefrom: false  
  nosync: false
````

````
Пример начальной конфигурации для включения поддержки TLS в Patroni

  
Нужно поместить пример начальной конфигурации с TLS в файл \[OBJECT\]. Обратите внимание на комментарии в данном файле:

````
scope: postgres-cluster # одинаковое значение на всех узлах  
name: postgresql-server1 # разное значение на всех узлах  
namespace: /service/ # одинаковое значение на всех узлах  
  
restapi:  
  listen: postgres-server1.your\_domain:8008 # адрес узла, на котором находится этот файл  
  connect\_address: postgres-server1.your\_domain:8008 # адрес узла, на котором находится этот файл  
  cafile: /path/to/pgCA.pem  
  certfile: /path/to/pg.crt # путь до файла сертификата сервера  
  keyfile: /path/to/pg.key # путь до файла закрытого ключа  
  verify\_client: required # путь до файла корневого CA  
  
etcd:  
  protocol: https  
  cert: /path/to/public.crt # путь до файла сертификата сервера  
  key: /path/to/private.key # путь до файла закрытого ключа  
  cacert: /path/to/certCA.pem # путь до файла корневого CA  
  hosts: postgres-server1.your\_domain:2379,postgres-server2.your\_domain:2379,postgres-server3.your\_domain:2379 # список всех узлов, на которых установлен etcd  
  
ctl:  
  insecure: false # Allow connections to SSL sites without certs  
  certfile: /path/to/pg.crt # путь до файла сертификата сервера  
  keyfile: /path/to/pg.key # путь до файла закрытого ключа  
  cacert: /path/to/pgCA.pem # путь до файла корневого CA  
  
bootstrap:  
  method: initdb  
  dcs:  
    ttl: 30  
    loop\_wait: 10  
    retry\_timeout: 10  
    maximum\_lag\_on\_failover: 1048576  
    master\_start\_timeout: 300  
    synchronous\_mode: false  
    synchronous\_mode\_strict: false  
    synchronous\_node\_count: 1  
    postgresql:  
      use\_pg\_rewind: true  
      use\_slots: true  
      parameters:  
        max\_connections: 2000  
        superuser\_reserved\_connections: 5  
        max\_locks\_per\_transaction: 64  
        max\_prepared\_transactions: 0  
        huge\_pages: try  
        shared\_buffers: 512MB  
        work\_mem: 128MB  
        maintenance\_work\_mem: 256MB  
        effective\_cache\_size: 4GB  
        checkpoint\_timeout: 15min  
        checkpoint\_completion\_target: 0.9  
        wal\_compression: on  
        min\_wal\_size: 2GB  
        max\_wal\_size: 4GB  
        wal\_buffers: 32MB  
        default\_statistics\_target: 1000  
        seq\_page\_cost: 1  
        random\_page\_cost: 4  
        effective\_io\_concurrency: 2  
        synchronous\_commit: on  
        autovacuum: on  
        autovacuum\_max\_workers: 5  
        autovacuum\_vacuum\_scale\_factor: 0.1  
        autovacuum\_analyze\_scale\_factor: 0.05  
        autovacuum\_vacuum\_cost\_limit: 200  
        autovacuum\_vacuum\_cost\_delay: 20  
        autovacuum\_naptime: 15s  
        max\_files\_per\_process: 4096  
        archive\_mode: on  
        archive\_timeout: 1800s  
        archive\_command: cd .  
        wal\_level: replica  
        wal\_keep\_segments: 130  
        max\_wal\_senders: 10  
        max\_replication\_slots: 10  
        hot\_standby: on  
        hot\_standby\_feedback: True  
        wal\_log\_hints: on  
        shared\_preload\_libraries: pg\_stat\_statements,auto\_explain  
        pg\_stat\_statements.max: 10000  
        pg\_stat\_statements.track: all  
        pg\_stat\_statements.save: off  
        auto\_explain.log\_min\_duration: 10s  
        auto\_explain.log\_analyze: true  
        auto\_explain.log\_buffers: true  
        auto\_explain.log\_timing: false  
        auto\_explain.log\_triggers: true  
        auto\_explain.log\_verbose: true  
        auto\_explain.log\_nested\_statements: true  
        standard\_conforming\_strings: true  
        track\_io\_timing: on  
        log\_lock\_waits: on  
        log\_temp\_files: 3  
        track\_activities: on  
        track\_counts: on  
        track\_functions: all  
        log\_checkpoints: on  
        logging\_collector: on  
        log\_truncate\_on\_rotation: on  
        log\_rotation\_age: 1d  
        log\_rotation\_size: 0  
        log\_line\_prefix: '%t \[%p-%l\] %r %q%u@%d '  
        log\_filename: 'postgresql-%a.log'  
        log\_directory: /var/log/postgresql  
        ssl: on  
        ssl\_ca\_file: '/path/to/pgCA.pem'  
        ssl\_cert\_file: '/path/to/pg.crt'  
        ssl\_key\_file: '/path/to/pg.key'  
  
  initdb: # List options to be passed on to initdb  
    - encoding: UTF8  
    - locale: en\_US.UTF-8  
    - data-checksums  
  
  pg\_hba: # должен содержать адреса ВСЕХ машин, используемых в кластере  
    - local all postgres peer  
    - local all all peer  
    - hostssl all all 0.0.0.0/0 md5  
    - hostssl replication replicator localhost trust  
    - hostssl replication replicator 192.168.1.1/32 md5  
    - hostssl replication replicator 192.168.1.2/32 md5  
    - hostssl replication replicator 192.168.1.3/32 md5  
  
postgresql:  
  listen: 192.168.1.1,127.0.0.1:5432 # адрес узла, на котором находится этот файл  
  connect\_address: 192.168.1.1:5432 # адрес узла, на котором находится этот файл  
  use\_unix\_socket: true  
  data\_dir: /var/lib/postgresql/13/main # каталог данных  
  bin\_dir: /usr/lib/postgresql/13/bin  
  config\_dir: /etc/postgresql/13/main  
  pgpass: /var/lib/postgresql/.pgpass\_patroni  
  authentication:  
    replication:  
      username: replicator  
      password: ReplicatorPassword  
      sslcert: /path/to/pg.crt # путь до файла сертификата сервера  
      sslkey: /path/to/pg.key # путь до файла закрытого ключа  
      sslrootcert: /path/to/pgCA.pem # путь до файла корневого CA  
    superuser:  
      username: postgres  
      password: PostgresPassword  
      sslcert: /path/to/pg.crt # путь до файла сертификата сервера  
      sslkey: /path/to/pg.key # путь до файла закрытого ключа  
      sslrootcert: /path/to/pgCA.pem # путь до файла корневого CA  
  parameters:  
    unix\_socket\_directories: /var/run/postgresql  
  pg\_hba: # должен содержать адреса ВСЕХ машин, используемых в кластере  
    - local all postgres peer  
    - local all all peer  
    - hostssl all all 0.0.0.0/0 md5  
    - hostssl replication replicator localhost trust  
    - hostssl replication replicator 192.168.1.1/32 md5  
    - hostssl replication replicator 192.168.1.2/32 md5  
    - hostssl replication replicator 192.168.1.3/32 md5  
  
  remove\_data\_directory\_on\_rewind\_failure: false  
  remove\_data\_directory\_on\_diverged\_timelines: false  
  
  create\_replica\_methods:  
    - basebackup  
  basebackup:  
    max-rate: '100M'  
    checkpoint: 'fast'  
  
watchdog:  
  mode: off # Allowed values: off, automatic, required  
  device: /dev/watchdog  
  safety\_margin: 5  
  
tags:  
  nofailover: false  
  noloadbalance: false  
  clonefrom: false  
  nosync: false

````
  
Сделайте пользователя postgres владельцем файла закрытого ключа \[OBJECT\]:

````
Начало внимание

````
Файл закрытого ключа \[OBJECT\] указанный в секции \[OBJECT\] должен иметь разрешения u=rw (0600) или меньше, если он принадлежит пользователю базы данных postgres, или разрешения u=rw, g=r (0640) или меньше, если он принадлежит пользователю root.

````
Конец внимание

sudo chown postgres:postgres -R /path/to/pg.key  
sudo chmod 600 /path/to/pg.key

````
  
Подробнее о настройке TLS в Patroni читайте в [официальной документации Patroni](https://patroni.readthedocs.io/en/latest/yaml_configuration.html).

3. Сделайте пользователя **postgres** владельцем каталога настроек:

````
sudo chown postgres:postgres -R /etc/patroni  
sudo chmod 700 /etc/patroni

## ````
Шаг 7. Подготовка кластера PostgreSQL+Patroni

1. Запустите службу Patroni на узле **postgres-server1.your\_domain**, а затем на узлах **postgres-server2.your\_domain** и **postgres-server3.your\_domain**:

````
sudo systemctl enable --now patroni.service

2. ````
Проверьте состояние кластера:

````
patronictl -c /etc/patroni/config.yml list

## ````
Шаг 8. Подготовка PGBouncer (опционально)

PGBouncer предназначен для управления пулом соединений к PostgreSQL и позволяет минимизировать издержки, связанные с установлением новых подключений к PostgreSQL.

Про установку и настройку PGBouncer читайте в статье [«Установка PGBouncer»](pgbouncer-installation.md).

## Шаг 9. Конфигурация HAProxy (блок postgres)

Настройте «[Отказоустойчивый HAProxy](fail-safe-haproxy.md)» для приёма запросов к PostgreSQL и балансировку нагрузки между нодами кластера PostgreSQL. Подробнее об этом читайте в статье [«Конфигурация HAProxy для PostgreSQL»](haproxy-postgresql.md).

## Шаг 10. Подключение к PostgreSQL

Строка для подключения к кластеру PostgreSQL через Haproxy‑сервер:

````
psqlUrl: postgresql://elma365:SecretPassword@haproxy-server.your\_domain:5000/elma365?sslmode=prefer

````
Строка для подключения к кластеру PostgreSQL только для чтения через Haproxy‑сервер:

````
psqlUrl: postgresql://elma365:SecretPassword@haproxy-server.your\_domain:5001/elma365?sslmode=prefer

````
Строка для подключения к кластеру PostgreSQL с поддержкой реплик:

````
psqlUrl: postgresql://elma365:SecretPassword@postgresql-server1.your\_domain:5432,postgresql-server2.your\_domain:5432,postgresql-server3.your\_domain:5432/elma365?sslmode=prefer\&target\_session\_attrs=primary

````
Строка для подключения к кластеру PostgreSQL только для чтения с поддержкой реплик:

````
roPsqlUrl: postgresql://elma365:SecretPassword@postgresql-server1.your\_domain:5432,postgresql-server2.your\_domain:5432,postgresql-server3.your\_domain:5432/elma365?sslmode=prefer\&target\_session\_attrs=prefer-standby

````
Если настроено внешнее хранилище секретов, например Vault, для подключения к реплике PostgreSQL только для чтения [необходимо задать переменные окружения](install-vault.md#secrets) \[OBJECT\] и \[OBJECT\].

## Подготовка базы данных в PostgreSQL к восстановлению

Если вам потребовалось восстановить базу данных из резервной копии, сначала подготовьте БД к восстановлению. Подробнее об этом читайте в статье [«PostgreSQL»](postgresql.md#prepare-to-recovery).