Установка и настройка кластера PostgreSQL с репликацией автоматических переключений
Кластер PostgreSQL с репликацией автоматических переключений используется для обеспечения высокой доступности и отказоустойчивости базы данных PostgreSQL. Такое решение предназначено для минимизации простоев и обеспечения непрерывной работы системы даже при возникновении сбоев или отказов в оборудовании или программном обеспечении.
Описание
В данной инструкции описываются:
- настройки кластера Postgres;
- обработка событий падения нод с помощью службы repmgr;
- настройка pbgouncer и автоматическая замена файла настроек;
- смена IP-адреса при падении одного из балансировщика pgbouncer .
Рабочие директории:
Имя | Директория | Описание |
---|---|---|
Postgresql 12 | /var/lib/pgsql/12/data/ | Рабочая директория Postgres |
Replication settings | /var/lib/pgsql/12/data/postgresql.replication.conf | Настройки репликации: в postgres.conf необходимо добавить include '/var/lib/pgsql/12/data/postgresql.replication.conf' |
Repmgr settings | /opt/repmgr/repmgr.conf | Настройки репликации, а также поведение при отключении нод |
Настройка
Установка и настройка repmgr и postgres
Для установки и настройки repmgr и postgres необходимо:
Добавить репозиторий postgres на всех нодах:
sudo yum -y install https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm
Установить дополнительные пакеты:
sudo yum -y install epel-release yum-utils sudo yum-config-manager --enable pgdg12
На все ноды кластера установить следующие компоненты:
sudo yum install postgresql12 postgresql12-server repmgr_12 sudo /usr/pgsql-12/bin/postgresql-12-setup initdb
Создать директорию и файл для логов утилиты repmgr и дать права пользователю postgres на всех нодах:
mkdir /var/log/postgresql/ nano /var/log/postgresql/repmgrd.log -> Сохраняем пустой файл. chown postgres:postgres -R /var/log/postgresql
Отредактировать pg_hba.conf на обоих нодах по пути /var/lib/pgsql/12/data/pg_hba.conf:
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 all trust # IPv6 local connections: host all all ::1/128 trust # Allow replication connections from localhost, by a user with the # replication privilege. local replication all peer host replication all 0.0.0.0/4 trust host replication all c7node1 trust host replication all c7node2 trust
Отредактировать файл postgres.conf по пути /var/lib/pgsql/12/data/postgres.conf:
postgresql.conflisten_addresses = '*' include 'postgresql.replication.conf'
Создать файл /var/lib/pgsql/12/data/postgresql.replication.conf на node1:
postgresql.replication.confwal_level = replica max_wal_senders = 10 max_replication_slots = 10 hot_standby = on wal_log_hints = on archive_mode = on archive_command = '/bin/true'
На одном из серверов создать базу данных:
sudo -u postgres psql CREATE user repmgr password 'repmgr'; CREATE DATABASE repmgr OWNER repmgr; ALTER USER repmgr WITH SUPERUSER; ALTER USER repmgr SET search_path TO repmgr, "$user", public; \q
Создать файл repmgr.conf в директории /opt/repmgr/ на обоих серверах. Выдать права пользователю postgres на всю папку. В параметре node_name и в conninfo указать hostname каждого сервера.
mkdir /opt/repmgr nano /opt/repmgr/repmgr.conf
Server1
repmgr.confnode_id=1 priority=100 monitor_interval_secs = 2 connection_check_type = 'ping' reconnect_attempts = 4 reconnect_interval = 5 node_name='c7node1' conninfo='host=c7node1 user=repmgr dbname=repmgr connect_timeout=2' data_directory='/var/lib/pgsql/12/data/' log_level='INFO' use_replication_slots=true monitoring_history=yes pg_bindir='/usr/pgsql-12/bin/' 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' #service_promote_command = 'pg_ctl -w -D /var/lib/pgsql/12/data/ promote' promote_check_timeout = 15 failover=automatic promote_command='/usr/pgsql-12/bin/repmgr standby promote -f /opt/repmgr/repmgr.conf --log-to-file' follow_command='/usr/pgsql-12/bin/repmgr standby follow -f /opt/repmgr/repmgr.conf --log-to-file --upstream-node-id=%n' repmgrd_service_start_command='sudo /bin/systemctl start repmgr-12' repmgrd_service_stop_command='sudo /bin/systemctl stop repmgr-12' log_file='/var/log/postgresql/repmgrd.log'
Server2
repmgr.confnode_id=2 priority=80 node_name='c7node2' monitor_interval_secs = 2 connection_check_type = 'ping' reconnect_attempts = 4 reconnect_interval = 5 conninfo='host=c7node2 user=repmgr dbname=repmgr connect_timeout=2' data_directory='/var/lib/pgsql/12/data/' log_level='INFO' use_replication_slots=true monitoring_history=yes pg_bindir='/usr/pgsql-12/bin/' 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' #service_promote_command = 'sudo /usr/bin/pg_ctlcluster 10 main promote' #promote_check_timeout = 15 failover=automatic promote_command='/usr/pgsql-12/bin/repmgr standby promote -f /opt/repmgr/repmgr.conf --log-to-file' follow_command='/usr/pgsql-12/bin/repmgr standby follow -f /opt/repmgr/repmgr.conf --log-to-file --upstream-node-id=%n' repmgrd_service_start_command='sudo /bin/systemctl start repmgr-12' repmgrd_service_stop_command='sudo /bin/systemctl stop repmgr-12' log_file='/var/log/postgresql/repmgrd.log'
Выдача прав postgres на папку /opt/repmgr:
chown postgres:postgres -R /opt/repmgr
Далее действия выполняются под пользователем postgres.Выполнить регистрацию Server1 в качестве Master в репликационной системе с помощью repmgr:
/usr/pgsql-12/bin/repmgr -f /opt/repmgr/repmgr.conf primary register
Выполнить регистрацию Server2 в качестве Slave:
Предварительно выключить службу postgresql-12, если она запущена.
rm -Rf /var/lib/pgsql/12/data/ /usr/pgsql-12/bin/repmgr -h c7node1 -U repmgr -d repmgr -f /opt/repmgr/repmgr.conf standby clone --dry-run /usr/pgsql-12/bin/repmgr -h c7node1 -U repmgr -d repmgr -f /opt/repmgr/repmgr.conf standby clone systemctl start postgresql-12 /usr/pgsql-12/bin/repmgr -f /opt/repmgr/repmgr.conf standby register
Проверить состояние кластера:
/usr/pgsql-12/bin/repmgr -f /opt/repmgr/repmgr.conf cluster show
Добавить пользователя postgres в sudoers:
Defaults:postgres !requiretty %postgres ALL=(ALL)NOPASSWD:/bin/systemctl start postgresql-12,/bin/systemctl stop postgresql-12,/bin/systemctl restart postgresql-12,/bin/systemctl reload postgresql-12,/bin/systemctl start repmgr-12,/bin/systemctl stop repmgr-12
Проверить работу переключения нод.
Принудительно отключить службу postgres на Server1:sudo systemctl stop postgresql-12
На node2 под пользователем postgres выполнить команду и проверить, переведена ли текущая реплика (node2) в режим Master (Primary):
/usr/pgsql-12/bin/repmgr standby promote -f /opt/repmgr/repmgr.conf
Перейти обратно на Server1.
Под пользователем postgres произвести подключение ноды к кластеру, перевести текущую реплику в режим Slave ( StandBy):repmgr -f /opt/repmgr/repmgr.conf node rejoin --force-rewind -d 'host=c7node2 dbname=repmgr user=repmgr'
Запустить службу postgres на Server1:
sudo systemctl start postgresql-12
Настройка SSH между серверами
Действия выполняются под пользователем postgres.
Для настройки SSH между серверами необходимо:
Сгенерировать ключ на обоих серверах:
ssh-keygen -t rsa
Вывести содержимое файла id_rsa.pub с серверов:
cat /var/lib/pgsql/.ssh/id_rsa.pub
На обоих серверах создать файл под пользователем postgres и дублировать содержимое из id_rsa.pub:
nano /var/lib/pgsql/.ssh/authorized_keys
Пример содержимого файла:
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDeutr7h4ZfplM+mRjJY0iB6y1vwtpFgh6LoJSs50sDzzSbvIe61NOOb3dO+wQybBMNNnm8eGfTKOUniEn0PTGGbLt/s2mQous43zu0YiYaGlXk+IPJZzHU6lyWVp4/mcVKOEKKOjZnGeVP8tVMmWNMlZ26EEMPFOLt73ExyL585+NJzulFDCoZqWJETx9cQc4jRC7kzZpYe5N2Mvb3pWW7FBd5/0gZ2vUHlnvCka083IMwdKgvGXCBUNFqrxHR+5jljmBrg6t2lCP5bsrCl3Iya3mwi56zAusBdkUpxwuiehpn5eg0tY3olW+Qdtf7zygqFCwPFvaXDadldGNAyqw3 postgres@c7node1 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDNSIuc3DaEfFb9w7hSI97ANqtYf2QncWPpVV9Ycsemgxz2SleqhFiiCAM+NLRhnl92uwRlgEDPvUrIz+EVtwOAabqr/Iy2BtQ1cjLQYUnRTXUezkaKelpY0lcB4HEXxiXzYnh+qsihFx14LCFjGkEnqfC5AmLlua4bQlskRgeEpJdnjDDndQqGu5O/cWIMKd9e/5m+qDEiAklnVFji5rSjgVz1MsK70oZQ4Y5YOaVetnkPpM6IraiMDVjIIcUtbwzfbZnPoGkx7qjphmXzrLc6/oKSeMHpQv3BF+8Ci8i910rFyy1AgZz/yBX+NmX3//ZSk0N2hPdZ1pPuTZz8DSI/ postgres@c7node2
Repmgr Service
Служба repmgr предназначена для автоматического переключения нод в кластере в режиме failover cluster.
Для настройки службы repmgr необходимо:
Под пользователем root добавить службу в автоматический запуск на обоих серверах:
systemctl enable repmgr-12
Поменять настройки службы в части подстановки конфигурационного файла repmgr.conf в настройке Environment=REPMGRDCONF или указав полный путь до файла в ExecStart:
nano /usr/lib/systemd/system/repmgr-12.service
# It's not recommended to modify this file in-place, because it will be # overwritten during package upgrades. If you want to customize, the # best way is to create a file "/etc/systemd/system/repmgr.service", # containing # .include /lib/systemd/system/repmgr.service # ...make your changes here... # For more info about custom unit files, see # http://fedoraproject.org/wiki/Systemd#How_do_I_customize_a_unit_file.2F_add_a_custom_unit_file.3F [Unit] Description=A replication manager, and failover management tool for PostgreSQL After=syslog.target After=network.target After=postgresql-12.service [Service] Type=forking User=postgres Group=postgres # PID file PIDFile=/run/repmgr/repmgrd-12.pid # Location of repmgr conf file: Environment=REPMGRDCONF=/etc/repmgr/12/repmgr.conf Environment=PIDFILE=/run/repmgr/repmgrd-12.pid # Where to send early-startup messages from the server # This is normally controlled by the global default set by systemd # StandardOutput=syslog ExecStart=/usr/pgsql-12/bin/repmgrd -f /opt/repmgr/repmgr.conf -p ${PIDFILE} -d --verbose ExecStop=/usr/bin/kill -TERM $MAINPID ExecReload=/usr/bin/kill -HUP $MAINPID # Give a reasonable amount of time for the server to start up/shut down TimeoutSec=300 [Install] WantedBy=multi-user.target
Выполнить команду на обоих серверах
systemctl daemon-reload
Создать директорию, назначить владельца postgres:
cd /run mkdir repmgr chown postgres:postgres repmgr
Добавить в файл /var/lib/pgsql/12/data/postgresql.conf следующую строку и перезапустить службу postgres:
shared_preload_libraries = 'repmgr'
service postgresql-12 restart
Под пользователем postgres проверить, все ли готово к запуску службы. Если уже существует запущенный процесс DETAIL: repmgrd PID is 23197, удалить его, например, kill 23197
/usr/pgsql-12/bin/repmgr -f /opt/repmgr/repmgr.conf daemon start --dry-run
Настройка балансировки запросов через pgbouncer
Балансировка запросов через pgbouncer – процесс распределения запросов к базе данных PostgreSQL между несколькими экземплярами базы данных для улучшения производительности и повышения отказоустойчивости системы.
Описание
В данной инструкции описывается установка pgbouncer и схема развертывания в отказоустойчивом варианте. При выходе из строя одного из сервера с pgbouncer другой сервер будет принимать его IP-адрес и конфигурационный файл.
Настройка
Для настройки балансировки запросов через pgbouncer необходимо:
Установить pcs pacemaker corosync на всех серверах:
yum install pcs pacemaker corosync
Задать пароль для пользователя hacluster на обоих серверах:
passwd hacluster
Запустить и добавить в автозагрузку службу pcsd на обоих серверах:
systemctl enable --now pcsd
Проверить состояние серверов и произвести предварительную регистрацию на сервере №1:
sudo pcs cluster auth c7node1 c7node2
Создать кластер на сервере №1:
sudo pcs cluster setup --name mycluster c7node1 c7node2 --force
Запустить кластер на сервере №1:
sudo pcs cluster start
Установить pgbouncer на обоих серверах:
yum install pgbouncer
Задать дополнительные параметры:
sudo pcs property set stonith-enabled=false sudo pcs property set no-quorum-policy=ignore
Сделать кластер доступным:
sudo pcs cluster enable --all
Добавить службы в автозагрузку:
sudo systemctl enable pcsd && sudo systemctl enable corosync && sudo systemctl enable pacemaker sudo systemctl start pcsd && sudo systemctl start corosync && sudo systemctl start pacemaker
Добавить\изменить настройку в файле /etc/pgbouncer/pgbouncer.ini на Node1 и Node2:
listen_addr = * listen_port = 6432 auth_type = trust auth_file = /etc/pgbouncer/userlist.txt #idp2 - пользователь для созданной вручную БД idp2 ( например для приложения FAM) admin_users = postgres, repmgr, idp stats_users = stats, postgres, repmgr, idp pool_mode = session max_client_conn = 5000 %include /etc/pgbouncer/pgbouncer.database.ini
Создать файл nano /etc/pgbouncer/pgbouncer.database.ini на Node1 и Node2:
Node1[databases] #БД приложения, хост текущей мастер ноды idp2= host=c7node1
Node2
[databases] #БД приложения, хост текущей мастер ноды idp2= host=c7node2
Создать файл nano /etc/pgbouncer/userlist.txt , заполнить пользователями БД:
"idp" "idp" "postgres" "postgres"
Создать директорию scripts:
mkdir /opt/scripts
Создать скрипт для автоматической подстановки нового конфига с настройками подключения к БД и назначить пользователя "postgres" владельцем nano /opt/scripts/pgbouncer_promote.sh:
#!/usr/bin/env bash set -e set -u function try() { [[ $- = *e* ]]; SAVED_OPT_E=$? set +e } function throw() { exit $1 } function catch() { export ex_code=$? (( $SAVED_OPT_E )) && set +e return $ex_code } function throwErrors() { set -e } function ignoreErrors() { set +e } ######################################## PGBOUNCER_DATABASE_INI_NEW="/tmp/pgbouncer.database.ini" #ip-адрес или dns-имя серверов в кластере Postgres PGBOUNCER_HOSTS="10.10.180.56 10.10.180.59" #БД приложения DATABASES="idp" # Pause pgbouncer for h in ${PGBOUNCER_HOSTS} do for d in ${DATABASES} do try (psql -U postgres -h ${h} -p 6432 pgbouncer -tc "pause ${d}") done done # Promote server /usr/pgsql-12/bin/repmgr -f /opt/repmgr/repmgr.conf standby promote # Generate new config file for pgbouncer echo -e "[databases]\n" > ${PGBOUNCER_DATABASE_INI_NEW} for d in ${DATABASES} do echo -e "${d}= host=$(hostname -f)\n" >> ${PGBOUNCER_DATABASE_INI_NEW} done # Copy new config file, reload and resume pgbouncer for h in ${PGBOUNCER_HOSTS} do for d in ${DATABASES} do try (rsync -a ${PGBOUNCER_DATABASE_INI_NEW} ${h}:/etc/pgbouncer/pgbouncer.database.ini) try (psql -U postgres -h ${h} -p 6432 pgbouncer -tc "reload") try (psql -U postgres -h ${h} -p 6432 pgbouncer -tc "resume ${d}") done done rm ${PGBOUNCER_DATABASE_INI_NEW}
sudo chown postgres:postgres -R /opt/scripts