0

Построение отказоустойчивого кластера PostgreSQL. Настройка внешней синхронизации на PostgreSQL для механизма копий баз данных.

https://its.1c.ru/db/metod8dev/content/5971/hdoc

Введение

Целью данной статьи является описание способов построения отказоустойчивого кластера PostgreSQL, для систем на базе 1С:Предприятие, подобного решению “MS SQL Server Always On Availability Groups” от Microsoft. Построение такого отказоустойчивого кластера затруднено тем, что в PostgreSQL не предоставляет механизмов автоматического переключения на резервный сервер. Ниже будет описано, каким образом можно реализовать автоматическое переключение на резервный сервер в случае сбоя ведущего сервера PostgreSQL.

Используемые программные продукты

Patroni – шаблон для построения отказоустойчивых кластеров на базе PostgreSQL. Обеспечивает автоматическое переключение на резервный сервер при сбое ведущего сервера. Patroni управляет экземпляром базы данных PostgreSQL и использует внешние системы (ZooKeeper, etcd, Consul или Kubernetes) для хранения общей для всех узлов кластера информации, такой как список узлов кластера и положение ведущего сервера.

etcd – согласованное распределенное хранилище пар ключ-значение, обеспечивающее надежный способ хранения данных, к которым могут обращаться распределенная система или кластер машин.

HAProxy – прокси сервер TCP и HTTP трафика. Позволяет создать единую точку подключения к PostgreSQL, не зависящую от распределения ролей в кластерах PostgreSQL.

Развёртывание стенда

Описание стенда

Для демонстрации работы кластера будет использоваться четыре машины под управлением CentOS 7:

ИмяIP-адресОписание
Core.example10.0.0.11симуляция инфраструктуры
DBOne.example10.0.0.21первый сервер PostgreSQL
DBTwo.example10.0.0.22второй сервер PostgreSQL
DBThree.example10.0.0.23третий сервер PostgreSQL

Предполагается, что:

  • Машины уже созданы и на них установлена операционная система
  • Операционная система обновлена
  • Машины находятся в одной сети
  • Машины могут обнаруживать друг друга по DNS именам (core.example, dbone.example, dbtwo.example, dbthree.example).

Дополнительные настройки

Приведём имя машины к её имени в DNS и проверим результат. Для этого выполняем следующие команды:

  • на core.example
sudo hostnamectl set-hostname core.example --static > hostname core.example
  • на dbone.example
sudo hostnamectl set-hostname dbone.example --static > hostname dbone.example
  • на dbtwo.example
sudo hostnamectl set-hostname dbtwo.example --static > hostname dbtwo.example
  • на dbthree.example
sudo hostnamectl set-hostname dbthree.example --static > hostname dbthree.example

Подготовка дистрибутивов

Следует скачать следующие дистрибутивы:

Сервер 1С:Предприятия для RPM-based Linux-систем (https://releases.1c.ru/project/Platform83), использовалась версия 8.3.16.1224

СУБД PostgreSQL для Linux x86 (64-bit) одним архивом (RPM) (https://releases.1c.ru/project/AddCompPostgre), использовалась версия 11.5_12.1C

Установка дистрибутивов

Core.example

На этот сервер следует установить и запустить сервер 1С:Предприятие. Подробную инструкцию по установке можно найти по ссылке: https://its.1c.ru/db/metod8dev#content:5953:hdoc

DBOne.example, DBTwo.example, DBThree.example

На этом этапе настройки этих машин не отличаются. На обоих необходимо установить PostgreSQL с модификациями фирмы 1С.

  1. Установим PostgreSQL версии 11.5_12.1С. Для этого в каталоге с распакованным дистрибутивом PostgreSQL 11.5_12.1C выполняем:
  2. > sudo yum install -y postgresql11-1c-*.rpm Кластер инициализировать не нужно. Это будет выполнено при установке Patroni.
  3. Запрещаем автоматический запуск PostgreSQL при старте операционной системы.
  4. > sudo systemctl disable postgresql-11 Removed symlink /etc/systemd/system/multi-user.target.wants/postgresql-11.service.
  5. Остановкой и запуском PostgreSQL будет управлять Patroni и автоматический запуск будет только мешать Patroni.

Развёртывание отказоустойчивого кластера PostgreSQL + Patroni + etcd + HAProxy

Ниже описано создание кластера etcd и добавление нового узла в кластер. Затем будет построен кластер Patroni, использующий etcd для хранения своей конфигурации. После будет настроен HAProxy, который будет отслеживать смену ведущего сервера и скрывать это событие от 1С:Предприятие.

etcd

Кластер etcd будет развёрнут на всех машинах стенда.

Создание кластера etcd

Создадим первый узел кластера. На core.example выполняем следующие действия:

  1. Устанавливаем etcd из пакетаКопировать в буфер обмена> sudo yum install -y etcd
  2. Откладываем в сторону настройки по умолчаниюКопировать в буфер обмена> sudo mv /etc/etcd/etcd.conf /etc/etcd/etcd.conf.def
  3. Используя текстовый редактор создаём новый файл настроек /etc/etcd/etcd.conf и помещаем в него следующие настройки:Копировать в буфер обмена#[Member] ETCD_DATA_DIR=”/var/lib/etcd” ETCD_LISTEN_PEER_URLS=”http://0.0.0.0:2380″ ETCD_LISTEN_CLIENT_URLS=”http://0.0.0.0:2379″ ETCD_NAME=”core” ETCD_HEARTBEAT_INTERVAL=”1000″ ETCD_ELECTION_TIMEOUT=”5000″ #[Clustering] ETCD_INITIAL_ADVERTISE_PEER_URLS=”http://core.example:2380″ ETCD_ADVERTISE_CLIENT_URLS=”http://core.example:2379″ ETCD_INITIAL_CLUSTER=”core=http://core.example:2380″ ETCD_INITIAL_CLUSTER_TOKEN=”etcd-example” ETCD_INITIAL_CLUSTER_STATE=”new” Рассмотрим введённые параметры:
    ETCD_DATA_DIR – указывает расположение каталога данных кластера
    ETCD_LISTEN_PEER_URLS – задаёт схему и точку подключения для остальных узлов кластера, по шаблону scheme://IP:port. Схема может быть http, https. Альтернатива, unix:// или unixs:// для юникс сокетов. Если в качестве IP адреса указано 0.0.0.0, то указанный порт будет прослушиваться на всех интерфейсах.
    ETCD_LISTEN_CLIENT_URLS – задаёт схему и точку подключения для клиентов кластера. В остальном совпадает с ETCD_LISTEN_PEER_URLS.
    ETCD_NAME – человекочитаемое имя этого узла кластера. Должно быть уникально в кластере. Для первого узла может быть любым. Для последующих должно совпадать с именем, указанным при добавлении узла.
    ETCD_HEARTBEAT_INTERVAL – время в миллисекудах, между рассылками лидером оповещений о том, что он всё ещё лидер. Рекомендуется задавать с учётом сетевой задержки между узлами кластера.
    ETCD_ELECTION_TIMEOUT – время в миллисекундах, которое проходит между последним принятым оповещением от лидера кластера, до попытки захватить роль лидера на ведомом узле. Рекомендуется задавать его в несколько раз большим, чем ETCD_HEARTBEAT_INTERVAL. Более подробно о этих параметрах можно прочесть в документации.
    ETCD_INITIAL_ADVERTISE_PEER_URLS – Список равноправных URL-адресов, по которым его могут найти остальные узлы кластера. Эти адреса используются для передачи данных по кластеру. По крайней мере, один из этих адресов должен быть маршрутизируемым для всех членов кластера. Могут содержать доменные имена. Используется только при первом запуске нового узла кластера.
    ETCD_ADVERTISE_CLIENT_URLS – Список равноправных URL-адресов, по которым его могут найти остальные узлы кластера. Эти адреса используются для передачи данных по кластеру. По крайней мере, один из этих адресов должен быть маршрутизируемым для всех членов кластера. Могут содержать доменные имена.
    ETCD_INITIAL_CLUSTER – Список узлов кластера на момент запуска. Используется только при первом запуске нового узла кластера.
    ETCD_INITIAL_CLUSTER_TOKEN – Токен кластера. Должен совпадать на всех узлах кластера. Используется только при первом запуске нового узла кластера.
    ETCD_INITIAL_CLUSTER_STATE – может принимать два значения “new” и “existing”. Значение “new” используется при первом запуске первого узла в кластере. При значении “existing”, узел при старте будет пытаться установить связь с остальными узлами кластера.
  4. Запускаем демон etcdКопировать в буфер обмена> sudo systemctl start etcd.service
  5. Проверяем результат
    • Демон должен быть запущен и находиться в состоянии “active”Копировать в буфер обмена> sudo systemctl status etcd.service ? etcd.service – Etcd Server Loaded: loaded (/usr/lib/systemd/system/etcd.service; disabled; vendor preset: disabled) Active: active (running) since Wed 2020-03-04 07:39:43 UTC; 18s ago Main PID: 16423 (etcd) CGroup: /system.slice/etcd.service ??16423 /usr/bin/etcd –name=core –data-dir=/var/lib/etcd –listen-client-urls=http://0.0.0.0:2379 Mar 04 07:39:43 core.example etcd[16423]: 18cd9dc4a590c73e became leader at term 6 Mar 04 07:39:43 core.example etcd[16423]: raft.node: 18cd9dc4a590c73e elected leader 18cd9dc4a590c73e at term 6 Mar 04 07:39:43 core.example etcd[16423]: setting up the initial cluster version to 3.3 Mar 04 07:39:43 core.example etcd[16423]: published {Name:core ClientURLs:[http://core.example:…eb8af0 Mar 04 07:39:43 core.example etcd[16423]: ready to serve client requests Mar 04 07:39:43 core.example etcd[16423]: serving insecure client requests on [::]:2379, this is strongly discouraged! Mar 04 07:39:43 core.example systemd[1]: Started Etcd Server. Если запуск завершился с ошибкой, следует проверить сообщения в системном журналеКопировать в буфер обмена> journalctl -xel
    • Кластер должен состоять из одного узлаКопировать в буфер обмена> etcdctl cluster-health member 6390c5e1e694effa is healthy: got healthy result from http://core.example:2379 cluster is healthy
  6. Если всё хорошо, то добавляем etcd в автозапускКопировать в буфер обмена> sudo systemctl enable etcd.service Created symlink from /etc/systemd/system/multi-user.target.wants/etcd.service to /usr/lib/systemd/system/etcd.service.

При запуске etcd пытается найти все узлы, перечисленные в параметре “ETCD_INITIAL_CLUSTER”. Если какой-то из узлов не будет найден – запуск завершится сбоем. Если что-то пошло не так, удалите содержимое каталога из параметра “ETCD_DATA_DIR”.

Добавление нового узла etcd

Добавление нового узла в кластер etcd происходит в два этапа. На первом этапе кластер предупреждается о появлении нового узла. На втором запускается сам новый узел.
Следующие действия необходимо последовательно выполнить на всех оставшихся серверах стенда. Для примера будет использоваться dbtwo.example

  1. На core.example выполняем оповещение кластера о появлении нового узлаКопировать в буфер обмена> etcdctl member add dbtwo http://dbtwo.example:2380 Added member named dbtwo with ID 871ff309aeb9cd1 to cluster ETCD_NAME=”dbtwo” ETCD_INITIAL_CLUSTER=”dbtwo=http://dbtwo.example:2380,core=http://core.example:2380″ ETCD_INITIAL_CLUSTER_STATE=”existing”
  2. Устанавливаем etcd на новый узел и откладываем настройки по умолчаниюКопировать в буфер обмена> sudo yum install -y etcd > sudo mv /etc/etcd/etcd.conf /etc/etcd/etcd.conf.def
  3. Создаём файл /etc/etcd/etcd.conf со следующим содержимым:Копировать в буфер обмена#[Member] ETCD_DATA_DIR=”/var/lib/etcd” ETCD_LISTEN_PEER_URLS=”http://0.0.0.0:2380″ ETCD_LISTEN_CLIENT_URLS=”http://0.0.0.0:2379″ ETCD_NAME=”dbtwo” ETCD_HEARTBEAT_INTERVAL=”1000″ ETCD_ELECTION_TIMEOUT=”5000″ #[Clustering] ETCD_INITIAL_ADVERTISE_PEER_URLS=”http://dbtwo.example:2380″ ETCD_ADVERTISE_CLIENT_URLS=”http://dbtwo.example:2379″ ETCD_INITIAL_CLUSTER=”core=http://core.example:2380,dbtwo=http://dbtwo.example:2380″ ETCD_INITIAL_CLUSTER_TOKEN=”etcd-example” ETCD_INITIAL_CLUSTER_STATE=”existing” Не забывайте менять значение параметра “ETCD_NAME”. Параметр “ETCD_INITIAL_CLUSTER” важен для первого запуска, если в нём будут указаны несуществующие сервера или допущены другие ошибки – запуск завершится сбоем.
  4. Запускаем демон etcd на dbtwo.exampleКопировать в буфер обмена> sudo systemctl start etcd.service
  5. Проверяем результат
    • демон должен быть запущен и находится в состоянии “active”Копировать в буфер обмена> sudo systemctl status etcd.service
    • в списке узлов кластера новый узел должен быть в состоянии “healthy”Копировать в буфер обмена> etcdctl cluster-health member 871ff309aeb9cd1 is healthy: got healthy result from http://core.example:2379 member 99789c1c8817dff1 is healthy: got healthy result from http://dbtwo.example:2379 cluster is healthy > etcdctl member list 871ff309aeb9cd1: name=dbtwo peerURLs=http://dbtwo.example:2380 clientURLs=http:dbtwo.example:2379 isLeader=true 99789c1c8817dff1: name=core peerURLs=http://core.example:2380 clientURLs=http://core.example:2379 isLeader=false
  6. Если всё хорошо, тогда добавляем etcd в автозапускКопировать в буфер обмена> sudo systemctl enable etcd.service Created symlink from /etc/systemd/system/multi-user.target.wants/etcd.service to /usr/lib/systemd/system/etcd.service.

Завершение установки etcd

После установки и успешного запуска etcd на всех серверах, следует привести содержание файла /etc/etcd/etcd.conf в окончательное состояние. Для этого необходимо изменить следующие параметры в этом файле на всех серверах.

  • параметр “ETCD_INITIAL_CLUSTER” должен быть одинаковым на всех узлахКопировать в буфер обменаETCD_INITIAL_CLUSTER=”core=http://core.example:2380,dbone=http://dbonew.example:2380,dbtwo=http://dbtwo.example:2380,dbthree=http://dbthree.example:2380″
  • параметр “ETCD_INITIAL_CLUSTER_STATE” следует установить в значение “existing”Копировать в буфер обменаETCD_INITIAL_CLUSTER_STATE=”existing”

Создание пользователя в etcd

Добавим авторизацию по логину и паролю при обращениях на клиентский интерфейс etcd.

  1. Создаём пользователя “root”Копировать в буфер обмена> etcdctl user add root New password: User root created Это первый пользователь и поэтому ему автоматически назначается роль “root”.Копировать в буфер обмена> etcdctl user get root User: root Roles: root
  2. Включаем проверку логина и пароляКопировать в буфер обмена> etcdctl auth enable Authentication Enabled
  3. Проверяем, что изменения вступили в силуКопировать в буфер обмена> etcdctl user get root Insufficient credentials > etcdctl –username root user get root Password: User: root Roles: root

Patroni

Установка Patroni

Следующие действия выполняются на всех серверах PostgreSQL (dbone.example, dbtwo.example и dbthree.exemple).

  1. Устанавливаем PythonКопировать в буфер обмена> sudo yum install -y python3 > sudo python3 -m pip install –upgrade pip проверяем результат:Копировать в буфер обмена> python3 –version Python 3.6.8
  2. Устанавливаем зависимостиКопировать в буфер обмена> sudo yum install -y gcc python3-devel > sudo python3 -m pip install psycopg2-binary
  3. Устанавливаем PatroniКопировать в буфер обмена> sudo python3 -m pip install patroni[etcd]
  4. Проверям установкуКопировать в буфер обмена> patroni –version patroni 1.6.4

Первый узел Patroni

Следующие действия выполняются на dbone.example

  1. Создаём каталог настроек PatroniКопировать в буфер обмена> sudo mkdir /etc/patroni > sudo chown postgres:postgres /etc/patroni > sudo chmod 700 /etc/patroni
  2. Создаём файл настроек /etc/patroni/patroni.yml со следующим содержимымКопировать в буфер обменаname: dbone namespace: /db/ scope: postgres restapi: listen: 0.0.0.0:8008 connect_address: dbone.example:8008 authentication: username: patroni password: patroni etcd: hosts: localhost:2379 username: root password: rootpassword bootstrap: dcs: ttl: 30 loop_wait: 10 retry_timeout: 10 maximum_lag_on_failover: 1048576 master_start_timeout: 300 postgresql: use_pg_rewind: true use_slots: true parameters: wal_level: replica hot_standby: “on” wal_keep_segments: 8 max_wal_senders: 5 max_replication_slots: 5 checkpoint_timeout: 30 initdb: – auth-host: md5 – auth-local: peer – encoding: UTF8 – data-checksums – locale: ru_RU.UTF-8 pg_hba: – host replication replicator samenet md5 – host replication all 127.0.0.1/32 md5 – host replication all ::1/128 md5 users: usr1cv8: password: usr1cv8 options: – superuser postgresql: listen: 0.0.0.0:5432 connect_address: dbone.example:5432 config_dir: /var/lib/pgsql/11/data bin_dir: /usr/pgsql-11/bin/ data_dir: /var/lib/pgsql/11/data pgpass: /tmp/pgpass authentication: superuser: username: postgres password: V6OxPStvMPh0V7Q982DG replication: username: replicator password: PdR2lIAdwNdcSP4erAXc rewind: username: rewind_user password: WfcuDtEzEbLCHBaYQXX3 parameters: unix_socket_directories: ‘/var/run/postgresql/’ tags: nofailover: false noloadbalance: false clonefrom: false nosync: false В приведённом примере настроек, есть ряд параметров, влияющих на выполнение переключения на резервный сервер.
    • maximum_lag_on_failover – максимальное количество байт, на которые может отставать резервный сервер от ведущего, участвующий в выборах нового лидера.
    • master_start_timeout – задержка в секундах, между обнаружением аварийной ситуации и началом отработки переключения на резервный сервер. По умолчанию 300 секунд. Если задано 0, то переключение начнётся немедленно. При использовании асинхронной репликации (как в приведённом примере) это может привести к потере последних транзакций. Максимальное время переключения на реплику равно “loop_wait” + “master_start_timeout” + “loop_wait”. Если “master_start_timeout” установленно в 0, то это время становится равно значению параметра “loop_wait”.
      Подробнее о возможных вариантах репликации можно прочитать в документации
  3. Создаём сервис для запуска демона Patroni
    • Создаём unit файл /etc/systemd/system/patroni.serviceКопировать в буфер обмена[Unit] Description=Runners to orchestrate a high-availability PostgreSQL After=syslog.target network.target [Service] Type=simple User=postgres Group=postgres ExecStart=/usr/local/bin/patroni /etc/patroni/patroni.yml ExecReload=/bin/kill -s HUP $MAINPID KillMode=process TimeoutSec=30 Restart=no [Install] WantedBy=multi-user.target В приведённых настройках запуска особенно важны два параметра
      • TimeoutSec – время в секундах, которое система будет ожидать при запуске и остановке сервиса, перед тем как произвести попытку его внештатного завершения.
      • Restart – может принимать значения: no, on-success, on-failure, on-abnormal, on-watchdog, on-abort, или always. Определяет политику перезапуска сервиса в случае, если он завершает работу не по команде от systemd.
    • Обновляем системные настройкиКопировать в буфер обмена> sudo systemctl daemon-reload
  4. Запускаем демон PatroniКопировать в буфер обмена> sudo systemctl start patroni.service
  5. Проверяем успешность запуска
    • Статус службы должен быть “active”Копировать в буфер обмена> sudo systemctl status patroni.service ? patroni.service – Runners to orchestrate a high-availability PostgreSQL Loaded: loaded (/etc/systemd/system/patroni.service; disabled; vendor preset: disabled) Active: active (running) since Wed 2020-03-04 09:22:32 UTC; 7s ago Main PID: 19572 (patroni) CGroup: /system.slice/patroni.service ??19572 /usr/bin/python3 /usr/local/bin/patroni /etc/patroni/patroni.yml ??19581 /usr/pgsql-11/bin/pg_ctl initdb -D /var/lib/pgsql/11/data -o –encoding=UTF8 –data-checksums –locale=ru_RU.UTF-8 –use… ??19583 /usr/pgsql-11/bin/initdb -D /var/lib/pgsql/11/data –encoding=UTF8 –data-checksums –locale=ru_RU.UTF-8 –username=post… Mar 04 09:22:33 dbone.example patroni[19572]: Data page checksums are enabled. Mar 04 09:22:33 dbone.example patroni[19572]: fixing permissions on existing directory /var/lib/pgsql/11/data … ok Mar 04 09:22:33 dbone.example patroni[19572]: creating subdirectories … ok Mar 04 09:22:33 dbone.example patroni[19572]: selecting default max_connections … 100 Mar 04 09:22:33 dbone.example patroni[19572]: selecting default shared_buffers … 128MB Mar 04 09:22:33 dbone.example patroni[19572]: selecting default timezone … UTC Mar 04 09:22:33 dbone.example patroni[19572]: selecting dynamic shared memory implementation … posix Mar 04 09:22:33 dbone.example patroni[19572]: creating configuration files … ok Mar 04 09:22:33 dbone.example patroni[19572]: running bootstrap script … ok Mar 04 09:22:34 dbone.example patroni[19572]: performing post-bootstrap initialization … ok
    • В каталоге указанном в параметре “data_dir” из секции “postgresql” (/var/lib/pgsql/11/data) должна появиться структура каталогов кластера PostgreSQLКопировать в буфер обмена> sudo ls -l /var/lib/pgsql/11/data drwx——. 5 postgres postgres 38 Mar 4 09:28 base drwx——. 2 postgres postgres 4096 Mar 4 09:28 global drwx——. 2 postgres postgres 6 Mar 4 09:28 pg_commit_ts drwx——. 2 postgres postgres 6 Mar 4 09:28 pg_dynshmem -rw——-. 1 postgres postgres 4581 Mar 4 09:28 pg_hba.conf -rw——-. 1 postgres postgres 1636 Mar 4 09:28 pg_ident.conf drwx——. 4 postgres postgres 65 Mar 4 09:28 pg_logical drwx——. 4 postgres postgres 34 Mar 4 09:28 pg_multixact drwx——. 2 postgres postgres 17 Mar 4 09:28 pg_notify drwx——. 2 postgres postgres 6 Mar 4 09:28 pg_replslot drwx——. 2 postgres postgres 6 Mar 4 09:28 pg_serial drwx——. 2 postgres postgres 6 Mar 4 09:28 pg_snapshots drwx——. 2 postgres postgres 6 Mar 4 09:28 pg_stat drwx——. 2 postgres postgres 6 Mar 4 09:28 pg_stat_tmp drwx——. 2 postgres postgres 17 Mar 4 09:28 pg_subtrans drwx——. 2 postgres postgres 6 Mar 4 09:28 pg_tblspc drwx——. 2 postgres postgres 6 Mar 4 09:28 pg_twophase -rw——-. 1 postgres postgres 3 Mar 4 09:28 PG_VERSION drwx——. 3 postgres postgres 58 Mar 4 09:28 pg_wal drwx——. 2 postgres postgres 17 Mar 4 09:28 pg_xact -rw——-. 1 postgres postgres 88 Mar 4 09:28 postgresql.auto.conf -rw——-. 1 postgres postgres 24084 Mar 4 09:28 postgresql.conf
    • PostgreSQL должен быть запущен и слушать порт 5432Копировать в буфер обмена> ss -ltn | grep 5432 LISTEN 0 128 0.0.0.0:5432 0.0.0.0:*
    • Должна быть возможность подключения к кластеру PostgreSQL под пользователем usr1cv8Копировать в буфер обмена> psql -U usr1cv8 -d postgres
  6. Если все хорошо, добавляем patroni.service в автозапускКопировать в буфер обмена> sudo systemctl enable patroni.service Created symlink from /etc/systemd/system/multi-user.target.wants/patroni.service to /etc/systemd/system/patroni.service.

Настройка patronictl

Создание файла с настройками по умолчанию позволит не указывать настройки подключения для patronictl.

  1. Создаём файл ~/.config/patroni/patronictl.yaml со следующим содержимым:Копировать в буфер обменаdcs_api: etcd://localhost:2379 namespace: /db/ scope: postgres authentication: username: patroni password: patroni
  2. Проверяем результат выполненных настроекКопировать в буфер обмена> patronictl list +———-+————+—————+——–+———+—-+———–+—————–+ | Cluster | Member | Host | Role | State | TL | Lag in MB | Pending restart | +———-+————+—————+——–+———+—-+———–+—————–+ | postgres | dbone | dbone.example | Leader | running | 1 | 0.0 | | +———-+————+—————+——–+———+—-+———–+—————–+

Добавление нового узла Patroni

Для добавления нового узла в кластер Patroni, выполняются действия из раздела “Первый узел Patroni”. Различия будут заключаться только в файле /etc/patroni/patroni.yml – все изменения заключаются в замене “dbone” на имя текущего сервера. Поэтому для dbtwo.example содержимое будет следующим:Копировать в буфер обменаname: dbtwo namespace: /db/ scope: postgres restapi: listen: 0.0.0.0:8008 connect_address: dbtwo.example:8008 authentication: username: patroni password: patroni etcd: hosts: localhost:2379 username: root password: rootpassword bootstrap: dcs: ttl: 30 loop_wait: 10 retry_timeout: 10 maximum_lag_on_failover: 1048576 master_start_timeout: 300 postgresql: use_pg_rewind: true use_slots: true parameters: wal_level: replica hot_standby: “on” wal_keep_segments: 8 max_wal_senders: 5 max_replication_slots: 5 checkpoint_timeout: 30 initdb: – auth-host: md5 – auth-local: peer – encoding: UTF8 – data-checksums – locale: ru_RU.UTF-8 pg_hba: – host replication replicator samenet md5 – host replication all 127.0.0.1/32 md5 – host replication all ::1/128 md5 users: usr1cv8: password: usr1cv8 options: – superuser postgresql: listen: 0.0.0.0:5432 connect_address: dbtwo.example:5432 config_dir: /var/lib/pgsql/11/data bin_dir: /usr/pgsql-11/bin/ data_dir: /var/lib/pgsql/11/data pgpass: /tmp/pgpass authentication: superuser: username: postgres password: V6OxPStvMPh0V7Q982DG replication: username: replicator password: PdR2lIAdwNdcSP4erAXc rewind: username: rewind_user password: WfcuDtEzEbLCHBaYQXX3 parameters: unix_socket_directories: ‘/var/run/postgresql/’ tags: nofailover: false noloadbalance: false clonefrom: false nosync: false

После запуска Patroni на резервном сервере происходит следующее:

  • Patroni подключается к кластеру на dbone.example
  • Создаётся новый кластер PostgreSQL и заполняется данными с dbone.example
  • Новый кластер PostgreSQL переводится в “slave mode”

В результате в кластере Patroni должно быть три узла:Копировать в буфер обмена> patronictl list +———-+————+—————+——–+———+—-+———–+—————–+ | Cluster | Member | Host | Role | State | TL | Lag in MB | Pending restart | +———-+————+—————+——–+———+—-+———–+—————–+ | postgres | dbone | 10.0.0.21 | Leader | running | 1 | | | | postgres | dbtwo | 10.0.0.22 | | running | 1 | 0.0 | | | postgres | dbthree | 10.0.0.23 | | running | 1 | 0.0 | | +———-+————+—————+——–+———+—-+———–+—————–+

HAProxy

Установка HAProxy

В настройках информационной базы, в кластере 1С:Предприятие, необходимо указывать имя сервера СУБД. В нашем случае им может быть один из серверов PostgreSQL. Так как указать все имена сразу мы не можем, а роли серверов (ведущий сервер и резервный сервер) могут поменяться в любой момент, следует создать точку подключения к PostgreSQL. В качестве точки подключения будет выступать HAProxy установленный на core.example. В задачe HAProxy будет входить слежение за ролями серверов PostgreSQL и, в случае их изменения, оперативное перенаправление запросов от 1С:Предприятие к СУБД на новый ведущий сервер.

Следующие действия выполняются на core.example

  1. Устанавливаем HPAroxy из пакета и откладываем в сторону настройки по умолчаниюКопировать в буфер обмена> sudo yum install -y haproxy > sudo mv /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.conf.def
  2. Создаём файл /etc/haproxy/haproxy.cfg со следующим содержимымКопировать в буфер обменаglobal maxconn 100 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 postgres bind *:5432 option httpchk http-check expect status 200 default-server inter 3s fastinter 1s fall 2 rise 2 on-marked-down shutdown-sessions server dbone dbone.example:5432 maxconn 100 check port 8008 server dbtwo dbtwo.example:5432 maxconn 100 check port 8008 server dbthree dbthree.example:5432 maxconn 100 check port 8008
  3. Запускаем демон haproxy
    Если SELinux не выключался, то перед запуском необходимо внести изменения в настройки SELinux, разрешающие HAProxy обращаться на внешние адреса.Копировать в буфер обмена> sudo setsebool -P haproxy_connect_any=1 > sudo systemctl start haproxy.service
  4. Проверяем результат запускаКопировать в буфер обмена> sudo systemctl status haproxy.service ? haproxy.service – HAProxy Load Balancer Loaded: loaded (/usr/lib/systemd/system/haproxy.service; disabled; vendor preset: disabled) Active: active (running) since Wed 2020-03-04 10:59:47 UTC; 2s ago Main PID: 17617 (haproxy-systemd) CGroup: /system.slice/haproxy.service ??17617 /usr/sbin/haproxy-systemd-wrapper -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid ??17618 /usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid -Ds ??17619 /usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid -Ds Mar 04 10:59:47 core.example systemd[1]: Started HAProxy Load Balancer. Mar 04 10:59:47 core.example systemd[1]: Starting HAProxy Load Balancer… Mar 04 10:59:47 core.example haproxy-systemd-wrapper[17617]: haproxy-systemd-wrapper: executing /usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid -Ds Поверяем в интерфейсе haproxy (http://core.example:7000/), что узлы кластера Patroni найдены и их роли определены корректно. Ведущий сервер будет отмечен как “UP”, резервные как “DOWN”.
  5. Если запуск успешен, добавляем демон в автозагрузкуКопировать в буфер обмена> sudo systemctl enable haproxy.service Created symlink from /etc/systemd/system/multi-user.target.wants/haproxy.service to /usr/lib/systemd/system/haproxy.service.

Изменение настроек PostgreSQL через Patroni

Так как PostgreSQL теперь управляется Patroni, то и настройки PostgreSQL задаются через конфигурационный файл Paroni. Рекомендуется поддерживать данные настройки одинаковыми на всех узлах. Для задания настроек PostgreSQL используется параметр “parameters” в секции “postgresql” файла /etc/patroni/patroni.yml Сейчас он выглядит следующим образом:Копировать в буфер обменаparameters: unix_socket_directories: ‘/var/run/postgresql/’

Следующие действия выполняются на серверах PostgreSQL.

  1. Приводим “parameters” к следующему видуКопировать в буфер обменаparameters: unix_socket_directories: ‘/var/run/postgresql/’ shared_buffers: ‘1024MB’ temp_buffers: ‘256MB’ work_mem: ’64MB’ standard_conforming_strings: off escape_string_warning: off shared_preload_libraries: ‘online_analyze, plantuner’ plantuner.fix_empty_table: on online_analize.enable: on online_analize.table_type: ‘temporary’ online_analize.local_tracking: on online_analize.verbose: off maintenance_work_mem: ‘256MB’ max_locks_per_transaction: 256 lc_messages: ‘en_US.UTF-8’ log_line_prefix: ‘%m [%p] %q%u@%d ‘ Значения параметров приведены только в качестве примера задания значений для этих параметров. Для определения значений парметров следует обратится к следующим статьям Настройки PostgreSQL для работы с 1С:Предприятием и Настройки PostgreSQL для работы с 1С:Предприятием. Часть 2
  2. Применяем настройкиКопировать в буфер обмена> patronictl reload postgres dbone > patronictl restart postgres dbone > patronictl reload postgres dbtwo > patronictl restart postgres dbtwo > patronictl reload postgres dbthree > patronictl restart postgres dbthree
  3. Проверяем изменения настроекКопировать в буфер обмена> psql -U usr1cv8 -d postgres postgres> SHOW ALL;

Проверка переключения на резервный сервер PostgreSQL

Проведём несколько проверок отказоустойчивости кластера.

Подготовка

Создаём информационную базу в кластере 1С:Предприятие. Параметры создания информационной базы:Копировать в буфер обменаИмя: test Сервер баз данных: localhost Тип СУБД: PostgreSQL База данных: test Пользователь сервера БД: usr1cv8 Пароль пользователя сервера БД: usr1cv8

Загружаем в базу произвольную конфигурацию.
После окончания загрузки проверяем, что данные переданы на резервный серверКопировать в буфер обмена> patronictl list +———-+————+—————+——–+———+—-+———–+—————–+ | Cluster | Member | Host | Role | State | TL | Lag in MB | Pending restart | +———-+————+—————+——–+———+—-+———–+—————–+ | postgres | dbone | 10.0.0.21 | Leader | running | 10 | | | | postgres | dbtwo | 10.0.0.22 | | running | 1 | 0.0 | | | postgres | dbthree | 10.0.0.23 | | running | 1 | 0.0 | | +———-+————+—————+——–+———+—-+———–+—————–+

в колонке “Lag in MB” должно быть 0.0

Тесты

Для выполнения тестов, откроем информационную базу “Test” в режиме 1С:Предприятие.

Плановое переключение ведущего сервера

  1. На dbone.example выполняем команду смены ведущего сервераКопировать в буфер обмена> patronictl failover
  2. Проверяем переключениеКопировать в буфер обмена> patronictl list +———-+————+—————+——–+———+—-+———–+—————–+ | Cluster | Member | Host | Role | State | TL | Lag in MB | Pending restart | +———-+————+—————+——–+———+—-+———–+—————–+ | postgres | dbone | 10.0.0.21 | | running | 10 | 0.0 | | | postgres | dbtwo | 10.0.0.22 | Leader | running | 1 | | | | postgres | dbthree | 10.0.0.23 | | running | 10 | 0.0 | | +———-+————+—————+——–+———+—-+———–+—————–+
  3. Проверяем работу в информационной базе – 1С:Предприятие изменений в инфраструктуре заменить не должно

Сбой ведущего сервера

  1. На dbtwo.example выполняем команду для перезагрузкиКопировать в буфер обмена> shutdown -r
  2. На dbone.example проверяем переключениеКопировать в буфер обмена> patronictl list +———-+————+—————+——–+———+—-+———–+—————–+ | Cluster | Member | Host | Role | State | TL | Lag in MB | Pending restart | +———-+————+—————+——–+———+—-+———–+—————–+ | postgres | dbone | 10.0.0.21 | Leader | running | 10 | | | | postgres | dbtwo | 10.0.0.22 | | running | 1 | 0.0 | | | postgres | dbthree | 10.0.0.23 | | running | 1 | 0.0 | | +———-+————+—————+——–+———+—-+———–+—————–+

Проверяем работу в информационной базе – 1С:Предприятие изменений в инфраструктуре заменить не должно

Резервное копирование

Ниже приведён пример создания резервной копии кластера PostgreSQL, теми средствами, что идут в его поставке. Резервная копия может быть снята не только на ведущем сервере, но и на резервном сервере.

  1. Создаём резервную копиюКопировать в буфер обмена> pg_basebackup -D ~/postgres.bak -Ft -z -P -U usr1cv8
  2. Проверяем, что копия созданаКопировать в буфер обмена> ls ~/postgres.bak base.tar.gz pg_wal.tar.gz

Восстановление после сбоев

Ниже приведена последовательность действий для проверки восстановления резервной копии на демонстрационном стенде. Поэтому, в реальной ситуации, раздел “Удаление данных” должен быть пересмотрен с учётом реальных обстоятельств сбоя. Раздел “Восстановление” предполагает, что описанное решение по созданию отказоустойчивого кластера Patroni полностью выполнено и его лишь надо наполнить данными.

Удаление данных

  1. Проверяем текущие роли узлов кластера PatroniКопировать в буфер обмена> patronictl list
  2. Останавливаем Patroni и PostgreSQL на резервных серверахКопировать в буфер обмена> sudo systemctl stop patroni > sudo systemctl stop postgresql-11
  3. Останавливаем Patroni и PostgreSQL на ведущем сервереКопировать в буфер обмена> sudo systemctl stop patroni > sudo systemctl stop postgresql-11
  4. Удаляем кластер PatroniКопировать в буфер обмена> patronictl remove postgres
  5. На всех серверах PostgreSQL удаляем каталоги кластераКопировать в буфер обмена> sudo rm -rf /var/lib/pgsql/11/data

Восстановление

  1. Восстанавливаем каталог кластера PostgreSQL на новом ведущем сервере
    Следующие действия выполняются на dbone.exampleКопировать в буфер обмена> sudo mkdir /var/lib/pgsql/11/data > sudo chown postgres:postgres /var/lib/pgsql/11/data > sudo chmod 700 /var/lib/pgsql/11/data > sudo tar xzf base.tar.gz -C /var/lib/pgsql/11/data > sudo tar xzf pg_wal.tar.gz -C /var/lib/pgsql/11/data/pg_wal > sudo rm /var/lib/pgsql/11/data/recovery.conf > sudo rm /var/lib/pgsql/11/data/recovery.done > sudo systemctl start patroni
  2. Переносим файл резервной копии на новый резерный сервер
    Следующие действия выполняются на dbone.exampleКопировать в буфер обмена> scp -r ~/postgres.bak dbtwo.example:postgres.bak > scp -r ~/postgres.bak dbthree.example:postgres.bak
  3. Восстанавливаем каталог кластера PostgreSQL на резервном сервере. На dbtwo.example и dbthree.example, повторяем действия выполненные на dbone.example
  4. Проверяем результатКопировать в буфер обмена> patronictl list +———-+————+—————+——–+———+—-+———–+—————–+ | Cluster | Member | Host | Role | State | TL | Lag in MB | Pending restart | +———-+————+—————+——–+———+—-+———–+—————–+ | postgres | dbone | 10.0.0.21 | Leader | running | 1 | | | | postgres | dbtwo | 10.0.0.22 | | running | 1 | 0.0 | | | postgres | dbthree | 10.0.0.23 | | running | 1 | 0.0 | | +———-+————+—————+——–+———+—-+———–+—————–+

Использование резервного сервера PostgreSQL для механизма копий базы данных

Механизм копий баз данных имеет особенность в использовании внешнего типа репликации данных при размещении данных в PostgreSQL. Особенность связана с тем, что резервный сервер PostgreSQL доступен только на чтение, включая временные таблицы. Такое ограничение приводит к тому, что запросы к СУБД, с созданием временных таблиц, выполняемые 1С:Предприятие, будут завершаться с ошибкой.
Для снятия этого ограничения требуется развёртывание дополнительного кластера PostgreSQL, доступного для записи данных. Ниже будет описан пример развёртывания такого сервера.

Создание дополнительного кластера PostgreSQL

Для создания дополнительного кластера PostgreSQL можно добавить новый сервер и установить на него PostgreSQL. В этом случае порядок действий не отличается от обычной установки PostgreSQL.
В случае, если добавление нового сервера нежелательно, дополнительный кластер PostgreSQL можно разместить на одном из существующих серверов PostgreSQL. Ниже показан пример развёртывания дополнительного кластера на уже существующем сервере.
Следующие действия выполняются на dbthree.example
Данные кластера будут расположены в каталоге /var/lib/pgsql/11/proxy

  1. Инициализируем кластерКопировать в буфер обмена> export LANG=”ru_RU.UTF-8″ > sudo -u postgres /usr/pgsql-11/bin/initdb -D /var/lib/pgsql/11/proxy –auth-local=peer –auth-host=md5 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 locales COLLATE: ru_RU.UTF-8 CTYPE: ru_RU.UTF-8 MESSAGES: ru_RU.UTF-8 MONETARY: en_GB.UTF-8 NUMERIC: en_GB.UTF-8 TIME: en_GB.UTF-8 The default database encoding has accordingly been set to “UTF8”. The default text search configuration will be set to “russian”. Data page checksums are disabled. creating directory /var/lib/pgsql/11/proxy … ok creating subdirectories … ok selecting default max_connections … 100 selecting default shared_buffers … 128MB selecting default timezone … Europe/Moscow selecting dynamic shared memory implementation … posix creating configuration files … ok running bootstrap script … ok performing post-bootstrap initialization … ok syncing data to disk … ok Success. You can now start the database server using: /usr/pgsql-11/bin/pg_ctl -D /var/lib/pgsql/11/proxy -l logfile start
  2. Создаём unit файл /etc/systemd/system/postgresql-11-proxy.serviceКопировать в буфер обмена[Unit] Description=PostgreSQL 11 database proxy server After=syslog.target After=network.target [Service] Type=notify User=postgres Group=postgres Environment=PGDATA=/var/lib/pgsql/11/proxy/ OOMScoreAdjust=-1000 ExecStartPre=/usr/pgsql-11/bin/postgresql-11-check-db-dir ${PGDATA} ExecStart=/usr/pgsql-11/bin/postmaster -D ${PGDATA} ExecReload=/bin/kill -HUP $MAINPID KillMode=mixed KillSignal=SIGINT TimeoutSec=300 [Install] WantedBy=multi-user.target
  3. В файле /var/lib/pgsql/11/proxy/postgre.sql задаём порт, на котором будут приниматься подключения от клиентовКопировать в буфер обмена#—————————————————————————— # CONNECTIONS AND AUTHENTICATION #—————————————————————————— # – Connection Settings – listen_addresses = ‘*’ # what IP address(es) to listen on; # comma-separated list of addresses; # defaults to ‘localhost’; use ‘*’ for all # (change requires restart) port = 5433
  4. Обновляем системные настройки и запускаем второй демон PostgreSQLКопировать в буфер обмена> sudo systemctl daemon-reload > sudo systemctl start postgresql-11-proxy.service
  5. Проверяем успешность запускаКопировать в буфер обмена> ss -ltn | grep 5433 LISTEN 0 128 0.0.0.0:5433 0.0.0.0:*
  6. Если запуск успешен, добавляем демон в автозапускКопировать в буфер обмена> sudo systemctl enable postgresql-11-proxy.service

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

  1. Создаём пользователя для 1С:Предприятие
    • входим пользователем postgres
    Копировать в буфер обмена> sudo -u postgres psql -p 5433
    • создаём нового пользователя
    Копировать в буфер обменаposgres> CREATE USER usr1cv8 WITH SUPERUSER LOGIN ENCRYPTED PASSWORD ‘usr1cv8’;
  2. Создаём информационную базу в кластере 1С:ПредприятиеКопировать в буфер обменаИмя: test Сервер баз данных: dbthree.example port=5433 Тип СУБД: PostgreSQL База данных: test Пользователь сервера БД: usr1cv8 Пароль пользователя сервера БД: usr1cv8 Создание информационной базы необходимо для корректного создания базы данных в кластере PostgreSQL. При создании базы данных 1С:Предприятие выполняет тонкие настройки в создаваемой базе данных, которые могут зависеть от версии платформы 1С:Предприятие.

Настройка промежуточной базы данных

  1. Входим пользователем postgres в созданную базу данныхКопировать в буфер обмена> sudo -u postgres psql -p 5433 -d test
  2. Удаляем все таблицыКопировать в буфер обменаselect ‘DROP TABLE ‘ || string_agg(tablename, ‘, ‘) || ‘;’ from pg_tables where schemaname = ‘public’ \gexec
  3. Создаём в базе расширение postgres_fdwКопировать в буфер обменаCREATE EXTENSION postgres_fdw;
  4. Создаём сервер, указывая параметры для подключения к резервному серверуКопировать в буфер обменаCREATE SERVER standby_server FOREIGN DATA WRAPPER postgres_fdw OPTIONS (host ”, dbname ‘test’, port ‘5432’);
  5. Создаём отображение для пользователей промежуточного сервераКопировать в буфер обменаCREATE USER MAPPING FOR postgres SERVER standby_server OPTIONS (user ‘usr1cv8’, password ‘usr1cv8’); CREATE USER MAPPING FOR usr1cv8 SERVER standby_server OPTIONS (user ‘usr1cv8’, password ‘usr1cv8’);
  6. Импортируем таблицы внешней базыКопировать в буфер обменаIMPORT FOREIGN SCHEMA public FROM SERVER standby_server INTO public;

В настройках подключения к копии базы данных следует указывать промежуточную базу:Копировать в буфер обменаСервер: dbthree.example port=5433 База данных: test

В варианте использования резервного сервера для копии базы данных, имеет смысл запретить Patroni выбирать этот сервер в качестве ведущего. Для этого следует изменить секцию “tags” patroni.yml По умолчанию, секция “tags” содержит следующие параметры:Копировать в буфер обменаtags: nofailover: false noloadbalance: false clonefrom: false nosync: false

  • nofailover – значение “true” запрещает выбирать этот узел в качестве ведущего
  • clonefrom – значение “true” рекомендует выбирать этот узел для создания резервной копии при развёртывании нового узла Patroni. Если значение “true” установлено у нескольких узлов, будет случайным образом выбран один из них
  • noloadbalance – устанавливает HTTP код возврата 503 для запроса GET /replica REST API
  • nosync – значение true запрещает выбирать этот узел для синхронной репликации

В результате выполнения указанных настроек внешняя синхронизация для механизма копий баз данных при использовании СУБД MS SQL Server, а также выполнение запросов на копии, должны работать корректно.

Реструктуризация информационной базы

В случае изменения структуры метаданных информационной базы в структуру базы данных вносятся соответствующие изменения. Эти изменения необходимо перенести в промежуточную базу данных. Для этого следует удалить импортированные таблицы и импортировать схему заново.
Следующие действия выполнятся на dbthree.example.

  1. Входим пользователем postgres в промежуточную базу данныхКопировать в буфер обмена> sudo -u postgres psql -p 5433 -d test
  2. Удаляем импортированные таблицыКопировать в буфер обменаselect ‘DROP FOREIGN TABLE ‘ || string_agg(table_name, ‘, ‘) || ‘;’ from information_schema.tables where table_type = ‘FOREIGN’ \gexec
  3. Импортируем таблицы внешней базыКопировать в буфер обменаIMPORT FOREIGN SCHEMA public FROM SERVER standby_server INTO public;

Свежие комментарии

Подписка

Лучшие статьи

Рубрики

Популярное

Previous Story

 NGINX redirect

Next Story

Nginx proxy_pass

Latest from Blog

Настройка роутера MikroTik с BGP для просмотра потокового видео дома

Про сервис antifilter.download Из-за большого наплыва пользователей после блокировки YouTube сервис испытывает перегрузки. Обещают починить. Изначально я пользовался именно сервисом antifilter.download, но по непонятным для меня причинам он перестал у меня работать. Я

Решаем проблему блокировок (и YouTube) за 5 минут на роутере Mikrotik через контейнеры и без VPN

как ускорить ютуб и разблокировать доступ к некоторым заблокированным ресурсам прямо на роутере Mikrotik и без VPN. В моем случае используется MikroTik hAP ax3. Стоит упомянуть, что подойдут только роутеры с архитектурой

Mikrotik — несколько ip на внешнем интерфейсе

Рассмотрим ситуацию, когда провайдер выдал нам один шнурок и несколько ip в нем (например, /29 подсеть). И за нашим роутером находится несколько разных подсетей, которые надо выпускать наружу с разными src-ip; также

Игра системный администратор

docker run -p 8080:8080 -p 3390:3389 –name play-adobe-flash-after-eol jchprj/play-adobe-flash-after-eolзайти localhost:8080, и открыть эту страницу, или https://serveradmin.ru/files/sysadmin.swf

Что делать, когда на сервере кончаются файловые дескрипторы (inode)

Нередки случаи, когда причиной проблем на сервере становится переполнение файловых дескрипторов (inode). Симптомы точно такие же, как при переполнившемся диске, только вот диск при этом может оказаться свободным. Количество inode каждой файловой системы определяется при разворачивании ОС.
Go toTop