Skip to Content

Настройка кластера PostgreSQL на основе repmgr на CentOS 8

Для организации отказоустойчивого кластера PostgreSQL используется синхронная репликация master-standby, настроенная при помощи утилиты repmgr, и HAProxy. HAProxy используется для скрытия от клиента IP mastera, который изменится после автоматического failover. Для примера рассмотрим настройку кластера из 3-х нод.

Штатная работа кластера:

alt

Выход из строя (недоступность) master:

alt

Автоматический failover и реструктуризация кластера:

alt

Штатная работа кластера с новым master:

alt

Чтение и запись производится клиентом через HAProxy только в master *. Для определения, является ли нода master, HAProxy по порту 5445 вызывает http-сервисы, развернутые на всех нодах кластера. Если нода является master, сервис вернет http-статус 200, иначе 503.

* - Со standby возможно только чтение, но этот сценарий в данной статье не рассматривается.

Репликация на основе repmgr12

https://www.youtube.com/watch?v=LvDHdgQqaQw

Установим PostgreSQL (локально из пакетов или из репозитория в интернет, см. «Руководство по установке TimescaleDB под CentOS 8») и repmgr12 на всех нодах:

sudo dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-8-x86_64/pgdg-redhat-repo-latest.noarch.rpm sudo dnf -qy module disable postgresql sudo dnf install -y postgresql12-server repmgr12 postgresql12 postgresql12-contrib postgresql12-libs sudo /usr/pgsql-12/bin/postgresql-12-setup initdb sudo systemctl enable postgresql-12 sudo systemctl start postgresql-12

На всех нодах настроим переменную окружения PATH для удобства работы с pgsql:

sudo vim /var/lib/pgsql/.bash_profile PATH=$PATH:$HOME/bin:/usr/pgsql-12/bin export PATH

На всех нодах добавляем repmgr12 в автозапуск:

# sudo systemctl enable repmgr12

Добавляем настройки repmgr в postgresql.conf (достаточно для ноды 1):

sudo vim /var/lib/pgsql/12/data/repmgr.conf shared_preload_libraries = 'repmgr' max_wal_senders = 10 max_replication_slots = 15 wal_level = 'replica' hot_standby = on archive_mode = on archive_command = '/bin/true' sudo echo -e "include_if_exists 'repmgr.conf'" >> /var/lib/pgsql/12/data/postgresql.conf sudo tail /var/lib/pgsql/12/data/postgresql.conf

Добавляем пользователей для репликации в pg_hba.conf (достаточно для ноды 1):

sudo vim /var/lib/pgsql/12/data/pg_hba.conf # TYPE DATABASE USER ADDRESS METHOD # "local" is for Unix domain socket connections only local all all trust # IPv4 local connections: host all all 0.0.0.0/0 trust # IPv6 local connections: host all all ::1/128 ident # Allow replication connections from localhost, by a user with the # replication privilege. local replication repmgr trust host replication repmgr 0.0.0.0/0 trust host replication repmgr ::1/128 trust local repmgr repmgr trust host repmgr repmgr 0.0.0.0/0 trust

Назначаем владельца и права на конфигурационные файлы (достаточно для ноды 1):

sudo chown postgres:postgres /var/lib/pgsql/12/data/{pg_hba.conf,repmgr.conf} sudo chmod 600 /var/lib/pgsql/12/data/{pg_hba.conf,repmgr.conf}

Перезапускаем postgresql12 на ноде 1:

sudo systemctl restart postgresql-12 sudo systemctl status postgresql-12

Теперь настраиваем repmgr:

Выполняем настройку схемы по умолчанию (достаточно для ноды 1):

sudo su - postgres createuser -s repmgr createdb repmgr -O repmgr psql postgres=# \c repmgr postgres=# ALTER USER repmgr SET search_path TO repmgr, "$user", public; postgres=# \q

Дальнейшая настройка repmgr происходит для каждой ноды. Полезно сначала сохранить оригинальный конфигурационный файл:

sudo mv /etc/repmgr/12/repmgr.conf{,.b} sudo vim /etc/repmgr/12/repmgr.conf

Для ноды 1:

vim /etc/repmgr/12/repmgr.conf node_id=1 node_name='node1' conninfo='host=192.168.0.29 dbname=repmgr user=repmgr connect_timeout=4' data_directory='/var/lib/pgsql/12/data/' use_replication_slots=yes log_file='/var/log/repmgr/repmgr.log' pg_bindir='/usr/pgsql-12/bin/' ssh_options='-q -o ConnectTimeout=10 -o "StrictHostKeyChecking no"' failover=automatic priority=100 reconnect_attempts=6 reconnect_interval=10 promote_command='/usr/pgsql-12/bin/repmgr standby promote -f /etc/repmgr/12/repmgr.conf' follow_command='/usr/pgsql-12/bin/repmgr standby follow -f /etc/repmgr/12/repmgr.conf -W --upstream-node-id=%n' service_start_command='sudo systemctl start postgresql-12' service_stop_command='sudo systemctl stop postgresql-12' service_restart_command='sudo systemctl restart postgresql-12' service_reload_command='sudo systemctl reload postgresql-12'

Регистрируем ноду 1 как master:

sudo su - postgres repmgr primary register repmgr cluster show

Для ноды 2:

vim /etc/repmgr/12/repmgr.conf node_id=2 node_name='node2' conninfo='host=192.168.0.9 dbname=repmgr user=repmgr connect_timeout=4' data_directory='/var/lib/pgsql/12/data/' use_replication_slots=yes log_file='/var/log/repmgr/repmgr.log' pg_bindir='/usr/pgsql-12/bin/' ssh_options='-q -o ConnectTimeout=10 -o "StrictHostKeyChecking no"' failover=automatic priority=90 reconnect_attempts=6 reconnect_interval=10 promote_command='/usr/pgsql-12/bin/repmgr standby promote -f /etc/repmgr/12/repmgr.conf' follow_command='/usr/pgsql-12/bin/repmgr standby follow -f /etc/repmgr/12/repmgr.conf -W --upstream-node-id=%n' service_start_command='sudo systemctl start postgresql-12' service_stop_command='sudo systemctl stop postgresql-12' service_restart_command='sudo systemctl restart postgresql-12' service_reload_command='sudo systemctl reload postgresql-12'

Регистрируем ноду 2 как standby:

sudo su - postgres repmgr standby register repmgr cluster show

Для ноды 3:

vim /etc/repmgr/12/repmgr.conf node_id=3 node_name='node3' conninfo='host=192.168.0.7 dbname=repmgr user=repmgr connect_timeout=4' data_directory='/var/lib/pgsql/12/data/' use_replication_slots=yes log_file='/var/log/repmgr/repmgr.log' pg_bindir='/usr/pgsql-12/bin/' ssh_options='-q -o ConnectTimeout=10 -o "StrictHostKeyChecking no"' failover=automatic priority=80 reconnect_attempts=6 reconnect_interval=10 promote_command='/usr/pgsql-12/bin/repmgr standby promote -f /etc/repmgr/12/repmgr.conf' follow_command='/usr/pgsql-12/bin/repmgr standby follow -f /etc/repmgr/12/repmgr.conf -W --upstream-node-id=%n' service_start_command='sudo systemctl start postgresql-12' service_stop_command='sudo systemctl stop postgresql-12' service_restart_command='sudo systemctl restart postgresql-12' service_reload_command='sudo systemctl reload postgresql-12'

Регистрируем ноду 3 как standby:

sudo su - postgres repmgr standby register repmgr cluster show

Дальше на всех узлах создаем скрипты и службы для определения, является ли нода master.

Редактируем файл sudoers:

sudo visudo Defaults:postgres !requiretty postgres ALL = NOPASSWD: /bin/systemctl stop postgresql-12, \ /bin/systemctl start postgresql-12, \ /bin/systemctl restart postgresql-12, \ /bin/systemctl reload postgresql-12, \ /bin/systemctl status postgresql-12

Устанавливаем socat (чтобы запускать скрипты в службах):

sudo dnf install socat

Копируем скрипт pg_ms.sh в /usr/local/bin и делаем его исполняемым:

sudo vim /usr/local/bin/pg_ms.sh sudo chmod +x /usr/local/bin/pg_ms.sh

Создаем службу, которая будет по http-запросу выполнять скрипт pg_ms.sh:

sudo vim /etc/systemd/system/pg_ms.service [Unit] Description=PostgreSQL master check [Service] Type=simple User=postgres Group=postgres ExecStart=/usr/bin/socat -t20 TCP-LISTEN:5445,reuseaddr,fork EXEC:/usr/local/bin/pg_ms.sh Restart=on-failure [Install] WantedBy=multy-user.target

Перезагружаем юниты, добавляем созданную службу в автозагрузку, запускаем:

sudo systemctl daemon-reload sudo systemctl enable pg_ms sudo systemctl start pg_ms sudo systemctl status pg_ms

Проверяем отдачу службы для всех нод:

sudo curl -i 192.168.0.29:5445 sudo curl -i 192.168.0.7:5445 sudo curl -i 192.168.0.9:5445

Добавляем правила в firewal:

sudo firewall-cmd --zone=public --permanent --add-port 5445/tcp sudo firewall-cmd --zone=public --permanent --add-port 5432/tcp sudo firewall-cmd --reload

HAProxy

Устанавливаем HAProxy с официального сайта.

sudo wget http://www.haproxy.org/download/2.5/src/haproxy-2.5.5.tar.gz -O ~/haproxy.tar.gz sudo tar xzvf ~/haproxy.tar.gz -C ~/ cd ~/haproxy-2.5.5 sudo yum groupinstall "Development tools" sudo make TARGET=linux-glibc USE_PCRE=1 USE_OPENSSL=1 USE_ZLIB=1 sudo make install sudo mkdir -p /etc/haproxy sudo mkdir -p /var/lib/haproxy sudo touch /var/lib/haproxy/stats sudo ln -s /usr/local/sbin/haproxy /usr/sbin/haproxy sudo cp ~/haproxy-2.5.5/examples/haproxy.init /etc/init.d/haproxy sudo chmod 755 /etc/init.d/haproxy sudo systemctl daemon-reload sudo chkconfig haproxy on sudo useradd -r haproxy

Настраиваем конфигурацию haproxy:

sudo vim /etc/haproxy/haproxy.cfg defaults mode tcp frontend pgmaster_front bind *:5432 default_backend pgmaster_back backend pgmaster_back option httpchk GET http-check expect status 200 server pgmaster1 192.168.0.29:5432 check port 5445 server pgmaster2 192.168.0.7:5432 check port 5445 server pgmaster3 192.168.0.9:5432 check port 5445

  Перезагружаем haproxy:

sudo systemctl restart haproxy sudo systemctl status haproxy