Кластер Postgres для 1С. Повествование об интеллектуальных скитаниях инженера со счастливым концом

от автора

Источник картинки - https://postgrespro.ru/blog/news/3876555
Источник картинки — https://postgrespro.ru/blog/news/3876555

Как и у многих, в нашей компании возник вопрос импортозамещения. В целом вопрос понятный, много раз обсужденный со всех точек зрения. И вот настал счастливый момент, когда слова трансформировались в конкретные задачи с конкретными сроками. И одна из них была о замене СУБД для 1С.

Ну и конечно же, первым делом был поднят вопрос о кластеризации этой истории. Никто подвоха особого не ожидал, ибо у нас есть уже зарекомендовавшее себя решение в виде связки pg_auto_failover версии 1.6 от Citus (далее PGAF для краткости) и keepalived. Это решение нас целиком и полностью устраивает, поэтому выбор наш был очевиден.

Но когда мы начали настраивать выяснился очень неприятный момент — обычная сборка PGAF просто не работает с версией СУБД от PostgresPro — все ломается из-за жестко прописанных зависимостей. Тут то и началось «веселье».

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


Кластер предполагается разворачивать используя продукты PostgresPro 14 в редакции 1C (14.2.1) и PGAF (1.6.4)

В соответствии с архитектурой системы разворачиваем минимально необходимые 3 ноды (схема из гита проекта):

У нас это будет 3 чистых (с набором минимально необходимого для комфортной работы) сервера Ubuntu Server 20.04 LTS (Focal Fossa) и называем их, например так:

  1. serv-pg-mon.local — сервер, который будет выполнять роль монитор-сервера. Для его полноценной работы будет достаточно выделить всего 1 ядро и 1 ГБ оперативной памяти, 20 Гб медленного дискового пространства. 

  2. serv-pg-data1.local — первый дата-сервер, который будет хранить базы и выполнять роль primary или secondary в процессе репликации — конфигурацию железа следует подбирать исходя из ваших потребностей.

  3. serv-pg-data2.local — второй дата-сервер, который будет хранить базы и выполнять роль primary или secondary в процессе репликации — конфигурацию железа следует подбирать исходя из ваших потребностей — она должна совпадать с конфигурацией первого дата-сервера.

Настройку имён хостов, сети, фаервола и доступа к хостам по ssh оставим за рамками этой статьи — будем считать, что это всё уже сделано. Важно, чтобы серверы могли обращаться друг к другу по указанным именам — всё взаимодействие в конфигах ниже построено на их DNS-именах, а не их IP-адресах.

Пункт 1: Первоначальная настройка хостов и установка софта из репозиториев

На всех нодах настраиваем русскую локаль (пригодится для корректной работы 1С). 
Для начала смотрим текущую локаль:
locale
Если в выводе не ru_RU.UTF-8, то делаем следующее:

sudo locale-gen ru_RU.UTF-8 sudo localectl set-locale LANG=ru_RU.UTF-8 LC_TIME=ru_RU.UTF-8 LC_COLLATE=ru_RU.UTF-8

Если всё прошло без ошибок, то для всех новых сессий кодировка будет ru_RU.UTF-8 — проверяем, перелогинившись. 

На всех нодах подключаем репозиторий PostgresPRO:

bash -c 'curl https://repo.postgrespro.ru/pg1c-14/keys/pgpro-repo-add.sh | sudo bash'

На всех нодах устанавливаем пакеты:

sudo apt install postgrespro-1c-14 postgrespro-1c-14-dev

Пакет postgrespro-1c-14-dev нам пригодится из-за входящей в его состав утилиты pg_config, которая требуется для работы PGAF
PostgresPRO по дефолту установится по пути /opt/pgpro/1c-14/ — в дальнейшем это будет важно.

На всех нодах создаём папки, в которых у нас будут размещаться файл PostgreSQL, например, папку «/data/postgres/». В нашем случае это просто отдельный диск, но и там где это не требуется, все равно делаем такую папку — это наши договоренности внутри команды. Если же необходимости в этом нет, можно использовать стандартный путь /var/lib/postgresql/ — в таком случае этот шаг можно пропустить и перейти сразу к подключению репозитория.

sudo mkdir -p /data/postgres/ sudo chown -R postgres. /data

Обратите внимание, что права юзеру postgres нужно выдавать не на папку /data/postgres/, а на папку выше (/data) — в ней PGAF должен иметь возможность при необходимости создавать и удалять папку backup и совершать операции с самой папкой /data/postgres. 

На всех нодах задаём переменные окружения (чтобы облегчить себе жизнь —  потом меньше параметров передавать PGAF вручную) создаём файл /etc/profile.d/02-pgenv.sh со следующим содержимым (указываем, где у нас будут файлы PostgreSQL и где его бинарники):

export PGDATA="/data/postgres" export PATH="$PATH:/opt/pgpro/1c-14/bin"

Если же мы не создавали отдельную папку, то содержимое файла будет:

export PGDATA="/var/lib/postgresql/" export PATH="$PATH:/opt/pgpro/1c-14/bin"

Пункт 2: Сборка PGAF из исходников

Ставим необходимые для сборки пакеты:

sudo apt install libssl-dev libkrb5-dev libncurses6 libselinux1-dev liblz4-dev libxslt1-dev libpam0g-dev libreadline-dev git

Скачиваем из гита проекта, собираем и устанавливаем PGAF (ставим наиболее свежую на момент написания статьи версию 1.6.4 — тестировалось всё на ней и всё работает, если хотите, можете попробовать на других):

cd /tmp git clone https://github.com/citusdata/pg_auto_failover -b v1.6.4 cd pg_auto_failover/ make sudo make install

Создаём отдельную службу в systemd, которая будет производить управление Postgres-ом через pgaf — создаём файл /etc/systemd/system/pgautofailover.service с правами root:root 0644 и со следующим содержимым:

[Unit] Description = pg_auto_failover  [Service] WorkingDirectory = /var/lib/postgresql Environment = 'PGDATA=/data/postgres/' User = postgres ExecStart = /opt/pgpro/1c-14/bin/pg_autoctl run Restart = always StartLimitBurst = 0  [Install] WantedBy = multi-user.target

Обратите внимание, что в поле Environment нужно вписать своё значение. Без корректного значения служба нормально стартовать не будет.
Применяем изменения, включаем службу PGAF и отключаем запуск стандартной службы postgrespro-1c-14.service:

sudo systemctl daemon-reload sudo systemctl disable --now postgrespro-1c-14.service sudo systemctl enable pgautofailover.service

Повторяем на остальных серверах.

Пункт 3: Настройка монитор-ноды

Внимание! Команды настройки кластера PGAF выполняются от имени локального пользователя postgres — чтобы начать в консоли сеанс этого пользователя выполните:

sudo su - postgres

Создаём конфигурацию монитор-ноды, выполнив в консоли:

pg_autoctl create monitor --auth md5 --ssl-mode require --ssl-self-signed --pgport 5432 --hostname serv-pg-mon.local

Объясняю, что мы только что сделали — мы создали монитор-ноду:

  • используем метода аутентификации md5

  • шифруем траффик между нодами (с использованием самоподписанных сертификатов)

  • используем FQDN хоста в качестве имени ноды

В данном примере мы используем конкретные настройки, которые подойдут большинству. Для ознакомления с альтернативными настройками обратитесь к документации — https://pg-auto-failover.readthedocs.io/en/v1.6.3/

Результатом выполнения команды станет инициализация БД в каталоге, который мы указали в PGDATA и сообщения такого вида

Если всё так и прошло, можно двигаться дальше. В случае возникновения ошибок, обратитесь к документации.

Теперь запускаем службу PGAF (обратите внимание, что команды выполняются с sudo, а пользователя postgres обычно таких прав не имеет — переключитесь на нужного пользователя):

sudo systemctl enable --now pgautofailover.service sudo systemctl status pgautofailover.service

На выходе должны получить картину типа такой:

Теперь нужно задать пароль служебного пользователя autoctl_node (см. документацию). Пусть у нас это будет пароль, например, «BeLL1ss1m0PaSSw0rd1ss1m0».
(Этот пароль будет использоваться для аутентификации между нодами и монитором. Позднее нужно будет также задать ещё один пароль для авторизации дата-нод между собой — пароль репликации. Удобно использовать одинаковый пароль для обеих операций — в этой инструкции мы рассматриваем именно такую схему. Но вы при желании можете задать отдельные пароли.)
Для этого выполняем от имени локального пользователя postgres:

psql -c "alter user autoctl_node password 'BeLL1ss1m0PaSSw0rd1ss1m0'"

Переопределяем стандартные настройки частоты проверок хостов на более приближённые к реальным требованиям — добавляем в конфиг postgresql.conf следующие строки:

#время задается в миллисекундах pgautofailover.health_check_period = 500 pgautofailover.health_check_retry_delay = 300 pgautofailover.health_check_timeout = 500 pgautofailover.node_considered_unhealthy_timeout = 3000 pgautofailover.primary_demote_timeout = 6000

Значения выведены эмпирически и могут быть изменены в зависимости от ваших потребностей или предпочтений — значения указываются в мс (см. документацию по PGAF).

Перезапускаем службу для применения всех изменений:

sudo systemctl restart pgautofailover.service

Теперь можно приступать к настройке дата-нод.

Пункт 4: Настройка первой дата-ноды

# очищаем дефолтные настройки rm -f /etc/default/postgrespro-1c-14 # инициализируем PostgreSQL, создавая дефолтную пустые базы из шаблонов - указание ru-локали обязательно для дальнейшей работы 1С sudo /opt/pgpro/1c-14/bin/pg-setup initdb -D /data/postgres/ --locale=ru_RU.UTF-8  # создаём служебную папку backup, которая будет использоваться PGAF для хранения временных файлов при репликации и восстановлении БД в случае сбоя sudo mkdir /data/backup # выдаём на неё нужные права sudo chown -R postgres. /data/backup # переключаемся на пользователя postgres sudo su - postgres # регистрируем дата-ноду на монитор-ноде pg_autoctl create postgres --hostname serv-pg-data1.local --name serv-pg-data1 --auth md5 --ssl-self-signed --monitor 'postgres://autoctl_node:BeLL1ss1m0PSSw0rd1ss1m0@serv-pg-mon.local:5432/pg_auto_failover?sslmode=require' --pgport 5432 --pgctl /opt/pgpro/1c-14/bin/pg_ctl

После выполнения последней команды должны получить примерно такую картину:

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

sudo su - postgres -c "pg_autoctl show state"

должно показать примерно такую картину:

          Name |  Node |                    Host:Port |       TLI: LSN |   Connection |      Reported State |      Assigned State --------------+-------+------------------------------+----------------+--------------+---------------------+-------------------- serv-pg-data1 |     1 | serv-pg-data1.local:5432     |   1: 0/1755380 | read-write ! |              single |              single

Теперь задаём основные параметры репликации (всё на той же первой дата-ноде):

# переключаемся на пользователя postgres sudo su - postgres # указываем пароль репликации - он запишется в конфиг pgaf и будет использован в случае, если эта нода станет standby  pg_autoctl config set replication.password 'BeLL1ss1m0PSSw0rd1ss1m0'  # задаём тот же пароль для пользователя БД psql -c "alter user pgautofailover_replicator password 'BeLL1ss1m0PaSSw0rd1ss1m0';" # выставляем значения таймаутов - опять же выведены эмпирически и могут быть изменены в зависимости от ваших потребностей или предпочтений - значения указываются в секундах (см. документацию по PGAF) pg_autoctl config set timeout.network_partition_timeout 3 pg_autoctl config set timeout.prepare_promotion_catchup 6 pg_autoctl config set timeout.prepare_promotion_walreceiver 3 pg_autoctl config set timeout.postgresql_restart_failure_timeout 6 pg_autoctl config set timeout.postgresql_restart_failure_max_retries 2 # ограничение на максимальную скорость репликации - значение 1024M это 1 Гигабит/c - может быть полезно, если Вы реплицируете большую базу и ограничены в пропускной скорости сети. В более ранних версиях PGAF (например, версии 1.4) скорость 1024М была максимально возможной, которую можно быть установить - значение по умолчанию - 100M (то есть 100 Мбит/c) pg_autoctl config set replication.maximum_backup_rate 1024M

Теперь можно запускать службу PGAF:

sudo systemctl enable --now pgautofailover.service sudo systemctl status pgautofailover.service

Получаем примерно такую картину:

Теперь можно приступать к настройке второй дата-ноды.

Пункт 5: Настройка второй дата-ноды

После выполнения последней команды должно начаться копирование БД с первой ноды — в логе мы должны получить примерно такую картину:

Если всё пройдёт успешно, далее увидим примерно вот такое:

При этом на монитор-ноде выполнение команды

sudo su - postgres -c "pg_autoctl show state"

должно показать примерно такую картину:

          Name |  Node |                    Host:Port |       TLI: LSN |   Connection |      Reported State |      Assigned State --------------+-------+------------------------------+----------------+--------------+---------------------+-------------------- serv-pg-data1 |     1 | serv-pg-data1.local:5432     |   1: 0/8000060 | read-write   | wait_primary        | wait_primary serv-pg-data2 |     2 | serv-pg-data2.local:5432     |   1: 0/8000000 | read-only !  | catchingup          | catchingup

Это означает, что обе ноды успешно зарегистрированы, вторая нода находится в состоянии catchingup и пока что недоступна (службу pgautofailover мы ещё не запустили).
Теперь задаём параметры репликации — в этот раз уже на второй ноде (да, на каждой ноде эти параметры задаются в конфиге отдельно)

sudo su - postgres pg_autoctl config set replication.password 'BeLL1ss1m0PSSw0rd1ss1m0'  pg_autoctl config set timeout.network_partition_timeout 3 pg_autoctl config set timeout.prepare_promotion_catchup 6 pg_autoctl config set timeout.prepare_promotion_walreceiver 3 pg_autoctl config set timeout.postgresql_restart_failure_timeout 6 pg_autoctl config set timeout.postgresql_restart_failure_max_retries 2 pg_autoctl config set replication.maximum_backup_rate 1024M

Теперь можно запускать службу PGAF и на ней:

sudo systemctl enable --now pgautofailover.service sudo systemctl status pgautofailover.service

При этом на монитор-ноде выполнение команды

sudo su - postgres -c "pg_autoctl show state"

должно показать примерно такую картину:

          Name |  Node |                    Host:Port |       TLI: LSN |   Connection |      Reported State |      Assigned State --------------+-------+------------------------------+----------------+--------------+---------------------+-------------------- serv-pg-data1 |     1 | serv-pg-data1.local:5432     |   1: 0/8000230 |   read-write |             primary |             primary serv-pg-data2 |     2 | serv-pg-data2.local:5432     |   1: 0/8000230 |    read-only |           secondary |           secondary

Это означает, что всё прошло успешно, ноды синхронизированы и всё работает, как часы.

Создаём скрипт /etc/keepalived/pg_auto_check.sh который проверяет, запущен ли на хосте ноде и какую роль она выполняет в кластере.

#!/bin/bash if [ "`pidof pg_autoctl`" ]; then         if  [ "`su - postgres -c 'pg_autoctl show state --pgdata /data/postgres | grep $HOSTNAME | grep -e primary -e single -e stop_replication'`" ]; then                 exit 0         else                 exit 1         fi else         exit 1 fi

Даем разрешение на запуск этого скрипта:

sudo chmod +x /etc/keepalived/pg_auto_check.sh

Приводим настройки /etc/keepalived.conf к следующему виду (предполагается, что у нас на серверах основной сетевой интерфейс eth0, мы присвоили этому кластеру virtual_router_id 66, мы выделили кластеру IP-адрес 172.16.6.66 и задали пароль ‘123qwe-1A’):

! Configuration File for keepalived   global_defs { #    notification_email { #        admin@example.com #    } #    notification_email_from admin@example.com #    smtp_server mail.example.com #    smtp_connect_timeout 10 # }   vrrp_script chk_pg_auto {     script "/etc/keepalived/pg_auto_check.sh"     interval 3     timeout 2     weight 100     rise 3     fall 3     user root }   vrrp_instance <имя_вашего_сервера> {     state BACKUP     interface eth0     dont_track_primary     track_script {         chk_pg_auto     }     virtual_router_id 66     priority 50     advert_int 1     authentication {         auth_type PASS         auth_pass 123qwe-1A     }     virtual_ipaddress {         172.16.6.66 dev eth0 label eth0:1     } #    smtp_alert }

Не забудьте вписать имя своего сервера в конфиг там где «vrrp_instance».
Если хотите получать почтовые оповещения о переходе IP-адреса с одной ноды на другую, раскомментируйте закомментированные строки и укажите свои актуальные данные.

Теперь стартуем сервис keepalived:

sudo systemctl enable --now keepalived.service

Проверяем, что на primary-ноде появился наш кластерный IP, если так — мы великолепны, если нет — курим мануалы.

Пункт 7: Создание базы 1С

Здесь сложностей возникнуть не должно — мануалов, как создать базу 1С на сервере PostgreSQL средствами самой 1С, более чем достаточно в интернете. 
Из тонкостей:
— рекомендуется создать отдельного пользователя для баз 1С
— в параметрах подключения в качестве адреса сервере БД нужно указывать IP-адрес нашего кластера Keepalived

Пункт 8: Тюнинг настроек Postgres

Рекомендуем ознакомиться со статьёй https://postgrespro.ru/docs/postgrespro/14/config-one-c и выставить параметры в соответствии с указанными там.
Что же касается настроек типа shared_buffers, work_mem,effective_cache_size и параметров autovacuum — то можно немного расслабиться — эти параметры pgaf задаём сам, рассчитывая их по формуле исходя из текущей конфигурации железа сервера. То есть, стоит вам накинуть памяти вашей виртуалке — и при первом же старте значения будут пересчитаны. Текущие параметры можно посмотреть в файле конфига postgresql-auto-failover.conf в корне вашей Postgres.

Пункт 9: Траблшутинг

Логи работы службы pgautofailover можно просмотреть через:

sudo journalctl -u pgautofailover.service

Логи событий в кластере:

su - postgres -c "pg_autoctl show events"

Логи самого PostgreSQL находятся в папке  $PGDATA/log/

Послесловие:
не забывайте везде в конфигах и командах изменить значения из примера на свои актуальные


ссылка на оригинал статьи https://habr.com/ru/post/664858/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *