В статье расскажу про мой опыт настройки Postgresql для работы под контролем кластерной службы PacemakerПод нагрузкой данное решение не проверялось, всегда делайте (и проверяйте) резервные копии.
Для хранения базы данных будет рассмотрен пример использования кластерной файловой системе OCFS2.
Версии ПО, использованные в примере:
*** OCFS2 - драйвер из ядра 5.10, утилиты ocfs2-tools - 1.8.6
*** Corosync - 3.1.2
*** Pacemaker - 2.0.5
*** Postgresql 13
В статье будет три типа кластеров:
*** кластер файловой системы OCFS2 - обеспечивает хранение файлов на общем диске и согласованную работу с ними
*** кластер Corosync/Pacemaker - обеспечивает отслеживание работы процессов СУБД, запуск виртуального ip-адреса СУБД
*** кластер баз данных Postgresql - набор баз, управляемых одним экземпляром работающего сервера СУБД
++ Подготовка операционных систем
Для устойчивой работы кластеров (OCFS2, Pacemaker/Corosync) необходимо как минимум три сервера. Сервера могут быть как физические так и виртуальные. Желательно, чтобы сервера имели одинаковые характеристики производительности.
Я для демонстрации подготовил три виртуальные машины с помощью Qemu-KVM.
Устанавливаем ОС Debian 11 на каждый из серверов в минимальной конфигурации.
++ Настройка сети
В примере у меня будут сервера с адресами:
*** node1 - ip 192.168.1.11
*** node2 - ip 192.168.1.12
*** node3 - ip 192.168.1.13
Имена узлов должны разрешаться в IP-адреса на каждом из серверов, для этого необходимо прописать сопоставление в файле /etc/hosts или создать записи на DNS-сервере.
root:~# cat /etc/hosts
127.0.0.1 localhost
192.168.1.11 node1.local node1
192.168.1.12 node2.local node2
192.168.1.13 node3.local node3
В случае реальной реализации кластера, сетевых карт на каждом из серверов должно быть как минимум две - карты необходимо объединить в логическое устройство bonding или teaming. Физически карты должны подключаться к двум независимым коммутаторам. В примере у меня будет по одной сетевой карте на сервер.
++ Настройка сетевого экрана
Выполняем настройку экрана на каждом узле:
*** устанавливаем пакет для управления брандмауэром ufw
*** создаём разрешающие правила для ssh, postgres, узлов кластера
*** активируем правила
root# apt install ufw
root# ufw allow ssh
root# ufw allow postgres
root# ufw allow from 192.168.1.11 to any
root# ufw allow from 192.168.1.12 to any
root# ufw allow from 192.168.1.13 to any
root# ufw enable
Кластер OCFS2 для отслеживания работы узлов по-умолчанию использует протокол TCP порт 7777 (задаётся в файле /etc/ocfs2/cluster.conf), а Corosync - протокол UDP, порт 5405 (задаётся в файле /etc/corosync/corosync.conf), с учётом этого, можно настроить более тонкие правила брандмауэра:
root# ufw allow proto tcp from 192.168.1.11 to any port 7777
root# ufw allow proto tcp from 192.168.1.12 to any port 7777
root# ufw allow proto tcp from 192.168.1.13 to any port 7777
root# ufw allow proto udp from 192.168.1.11 to any port 5405
root# ufw allow proto udp from 192.168.1.12 to any port 5405
root# ufw allow proto udp from 192.168.1.13 to any port 5405
++ Настройка дисковой системы
На каждом сервере будет индивидуальный диск для системы (/dev/vda, 20 Гб) и общий диск на все сервера для хранения БД (/dev/vdb, 5 Гб):
root# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
vda 254:0 0 20G 0 disk
├─vda1 254:1 0 512M 0 part /boot/efi
├─vda2 254:2 0 18,5G 0 part /
└─vda3 254:3 0 976M 0 part [SWAP]
vdb 254:16 0 5G 0 disk /mnt/ocfs2clst
++ Настройка кластерной файловой системы
Для реального использования общий диск должен быть расположен на системе хранения данных, и подключатся к серверам по нескольким путям.
Для демонстрации общий диск будет реализован с помощью средств Qemu-KVM.
++ Настройка службы кластера ФС OCFS2
++ Настройка ядра Linux
Необходимо изменить параметры ядра, чтобы сервер автоматически перезагружался при сбое кластерной ФС, для это нужно создать файл /etc/sysctl.d/10-ocfs2.conf
kernel.panic_on_oops = 1
kernel.panic = 30
После применить параметры:
root# systemctl restart systemd-sysctl
Данные настройки указывают ядру Linux при возникновении сбоя (когда связь по сети пропала, но узел продолжает запись heartbeat сообщений на общий диск) автоматически перезагрузить узел через 30 секунд.
++ Установка пакетов OCFS2
Устанавливаем пакеты на каждом из узлов
root# apt install ocfs2-tools
++ Настройка кластера ФС OCFS2
Все настройки кластера OCFS2 хранятся в файле /etc/ocfs2/cluster.conf.
Нужно либо выполнить команды на каждом узле кластера, либо выполнить на одном узле и после скопировать файл /etc/ocfs2/cluster.conf на каждый узел, а после выполнить регистрацию и запуск.
Создаём кластер (выполнить на каждом узле кластера)
root# o2cb add-cluster ocfs2clst
Добавляем узлы в кластер (выполнить на каждом узле кластера), имя узла должно совпадать с тем, что выдаёт команда hostname
root# o2cb add-node --ip 192.168.1.11 --port 7777 --number 1 ocfs2clst node1
root# o2cb add-node --ip 192.168.1.12 --port 7777 --number 2 ocfs2clst node2
root# o2cb add-node --ip 192.168.1.13 --port 7777 --number 3 ocfs2clst node3
Регистрируем кластер (выполнить на каждом узле кластера)
root# o2cb register-cluster ocfs2clst
Включаем кластер (выполнить на каждом узле кластера)
root# o2cb start-heartbeat ocfs2clst
Выполняем настройку драйвера ФС (обязательно выполнить на каждом узле кластера)
root# dpkg-reconfigure ocfs2-tools
Запускать кластер OCFS2 (O2CB) во время загрузки компьютера?: Y
Имя кластера, запускаемого во время загрузки компьютера: ocfs2clst
Настройки драйвера хранятся в файле /etc/default/o2cb
Содержимое файла:
# O2CB_ENABLED: 'true' means to load the driver on boot.
O2CB_ENABLED=true
# O2CB_BOOTCLUSTER: If not empty, the name of a cluster to start.
O2CB_BOOTCLUSTER=ocfs2clst
# O2CB_HEARTBEAT_THRESHOLD: Iterations before a node is considered dead.
O2CB_HEARTBEAT_THRESHOLD=31
# O2CB_IDLE_TIMEOUT_MS: Time in ms before a network connection is considered dead.
O2CB_IDLE_TIMEOUT_MS=30000
# O2CB_KEEPALIVE_DELAY_MS: Max. time in ms before a keepalive packet is sent.
O2CB_KEEPALIVE_DELAY_MS=2000
# O2CB_RECONNECT_DELAY_MS: Min. time in ms between connection attempts.
O2CB_RECONNECT_DELAY_MS=2000
++ Создание ФС OCFS2
Можно создать разделы на кластерном томе и создавать ФС уже на разделе, но это добавит сложностей при расширении тома, так как придётся вручную править границы раздела с помощью parted/fdisk и после расширять ФС. Но у нас кластерный том планируется целиком отдать под работу СУБД Postgresql, поэтому ФС предлагаю создать сразу на всем томе (в примере это диск /dev/vdb).
Выполняем форматирование общего тома на одном из узлов:
root# mkfs.ocfs2 -L pg-data --cluster-name=ocfs2clst -N 5 -T datafiles --fs-feature-level=max-features --cluster-stack=o2cb /dev/vdb
Описание параметров:
*** -L pg-data - метка ФС
*** --cluster-name=ocfs2clst - имя кластера OCFS2, который управляет ФС
*** -N 5 - максимальное количество узлов, которые могут работать одновременно с ФС, позже можно поменять с помощью tunefs.ocfs2, но рекомендуется создавать структуру заранее
*** -T datafiles - тип хранимых данных, может быть mail, datafiles, vmstore
*** --fs-feature-level=max-features - включаем все доступные возможности ФС, т.к. узлы у нас идентичные
*** --cluster-stack=o2cb - используем для управления ФС стандартный стек o2cb
Проверяем, что метки новой ФС видны на всех узлах кластера:
root# blkid /dev/vdb
/dev/vdb: LABEL="pg-data" UUID="ce92b1e7-30cb-4883-9a92-57c986f76acd" BLOCK_SIZE="4096" TYPE="ocfs2"
Вывод команды blkid на всех узлах кластера должен совпадать.
++ Выполняем пробное монтирование
Монтирование выполняется 20-30 секунд, так как требует согласования по сети. Выполняем команды на всех узлах кластера.
root# mkdir /mnt/ocfs2clst
root# mount /dev/disk/by-uuid/ce92b1e7-30cb-4883-9a92-57c986f76acd /mnt/ocfs2clst
Команда mounted.ocfs2 показывает на каких узлах смонтирована ФС.
root# mounted.ocfs2 -f
Device Stack Cluster F Nodes
/dev/vdb o2cb ocfs2clst node1, node2, node3
Создаём пробные файлы/папки в каталоге /mnt/ocfs2clst на одном из узлов и проверяем, что они видны на остальных узлах кластера OCFS2.
Размонтируем ФС на каждом узле:
root# umount /mnt/ocfs2clst
++ Расширение ФС OCFS2
Если потребуется увеличить размер хранилища:
*** Увеличиваем размер тома на СХД
*** Пересканируем том на сервере или перезагружаем узлы кластера
*** Расширяем ФС
root# tunefs.ocfs2 -S /dev/vdb
++ Добавление узла в кластер OCFS2
Если потребуется добавить ещё узел (например, node4, с ip 192.168.1.14) в кластер OCFS2, то необходимо выполнить команду на каждом узле:
root# o2cb_ctl -C -i -n node4 -t node -a number=4 -a ip_address=192.168.1.14 -a ip_port=7777 -a cluster=ocfs2clst
Необходимо заметить, что для обеспечения кворума, количество узлов должно быть нечётным.
++ Установка PostgreSQL
Устанавливаем пакеты на все узлы кластера:
root# apt install postgresql
Отключаем службу на каждом узле кластера, т.к. запуском СУБД будет управлять Pacemaker
root# systemctl disable postgresql
++ Настройка Pacemaker/Corosync
++ Установка пакетов
root# apt install pacemaker corosync crmsh fence-agents
++ Настройка Corosync
Служба Corosync обеспечивает обмен сообщениями между узлами кластера, с помощью неё отслеживается, что узлы работают корректно. А уже на основании информации о том какие узлы доступны, служба Pacemaker принимает решение о запуске сервисов (запуск виртуальных ip-адресов, монтирование файловых систем, запуск процессов СУБД).
Настройки Corosync хранятся в файле /etc/corosync/corosync.conf.
Рабочий пример файла указан ниже:
# Please read the corosync.conf.5 manual page
totem {
version: 2
cluster_name: pgclst
crypto_cipher: aes256
crypto_hash: sha256
}
logging {
fileline: off
to_stderr: yes
to_logfile: yes
logfile: /var/log/corosync/corosync.log
to_syslog: yes
debug: off
logger_subsys {
subsys: QUORUM
debug: off
}
}
quorum {
provider: corosync_votequorum
}
nodelist {
node {
name: node1
nodeid: 1
ring0_addr: 192.168.1.11
}
node {
name: node2
nodeid: 2
ring0_addr: 192.168.1.12
}
node {
name: node3
nodeid: 3
ring0_addr: 192.168.1.13
}
}
++ Включение шифрования сообщений Corosync
Для повышения безопасности можно включить шифрование служебных сообщений при обмене между узлами кластера. Для этого на одном из узлов необходимо выполнить команду:
root# corosync-keygen
Она создаст файл /etc/corosync/authkey, этот файл необходимо скопировать на другие узлы кластера.
root@node1:~# scp /etc/corosync/authkey root@node2:/etc/corosync/authkey
root@node1:~# scp /etc/corosync/authkey root@node3:/etc/corosync/authkey
В файле настроек /etc/corosync/corosync.conf необходимо задать параметры crypto_cipher и crypto_hash в секции totem:
totem {
...
crypto_cipher: aes256
crypto_hash: sha256
...
}
Если вам необходимо разместить файл-ключ по не стандартному пути, то расположение можно указать с помощью директивы keyfile.
После изменений необходимо перезапустить службы на каждом узле:
root# systemctl restart corosync pacemaker
++ Параметры узлов кластера Corosync
Для работы кластера необходимо указать список узлов. Это делается в секции nodelist.
nodelist {
node {
name: node1
nodeid: 1
ring0_addr: 192.168.1.11
}
node {
name: node2
nodeid: 2
ring0_addr: 192.168.1.12
}
node {
name: node3
nodeid: 3
ring0_addr: 192.168.1.13
}
}
После настройки, копируем файл /etc/corosync/corosync.conf на остальные узлы. Перезагружаем все узлы кластера и проверяем работу службы corosync с помощью команд corosync-quorumtool и crm_mon
root@node1:~# corosync-quorumtool -s
Quorum information
------------------
Date: Thu Jul 14 21:09:17 2022
Quorum provider: corosync_votequorum
Nodes: 3
Node ID: 1
Ring ID: 1.139
Quorate: Yes
Votequorum information
----------------------
Expected votes: 3
Highest expected: 3
Total votes: 3
Quorum: 2
Flags: Quorate
Membership information
----------------------
Nodeid Votes Name
1 1 node1 (local)
2 1 node2
3 1 node3
root@node1:~# crm_mon -1
Cluster Summary:
* Stack: corosync
* Current DC: node3 (version 2.0.5-ba59be7122) - partition with quorum
* Last updated: Thu Jul 14 21:11:18 2022
* Last change: Thu Jul 14 20:24:25 2022 by root via cibadmin on node1
* 3 nodes configured
* 0 resource instances configured
Node List:
* Online: [ node1 node2 node3 ]
++ Настройка Pacemaker
Ресурсы Pacemaker описываются через XML-файлы, я вместо ручного написания xml-объектов буду использовать crm (CRM shell), где параметры ресурсов можно задать в виде аргументов.
++ Смена имени кластера
Ранее мы создали кластер OCFS2 с именем ocfs2clst, кластер Corosync с именем pgclst, теперь укажем имя кластера Pacemaker.
После установки, имя кластера Pacemaker, обычно debian, поменяем его также на pgclst:
root# crm_attribute --query --name=cluster-name
scope=crm_config name=cluster-name value=debian
root# crm_attribute --type crm_config --name cluster-name --update pgclst
++ Параметры по-умолчанию
Меняем параметры по-умолчанию для новых ресурсов:
*** resource-stickiness - "липучесть" ресурса к текущему расположению в кластере (по-умолчанию 0), или "стоимость" переноса ресурса на другой узел. При увеличении значения, pacemaker будет стараться восстановить состояние сбойного ресурса на том же узле, при малом значении - предпочтёт восстановить ресурс запуском на других узлах.
root# crm_attribute --type rsc_defaults --name resource-stickiness --update 10
*** migration-threshold - кол-во сбоев ресурса на узле, при превышении которого происходит миграция на другой узел
root# crm_attribute --type rsc_defaults --name migration-threshold --update 2
++ Ассиметричный кластер
Можно указать, что для запуска каких-либо ресурсов необходимо наличие явного разрешающего правила. Это может понадобиться если не все узлы кластера идентичны по характеристикам:
root# crm_attribute -n symmetric-cluster -v false
После включения для каждого ресурса будет необходимо создать правила.
crm conf location <имя правила> <имя ресурса> <приоритет>: <узел>
Например, для ресурса виртуального ip-адреса (ip-pgclst) можно указать, что c приоритетом 100 он будет размещаться на узле node1, с приоритетом 10 - на узле node2, а на узле node3 его запуск будет запрещён (приоритет -infinity ):
root~# crm conf
crm(live)configure# location loc-ip-1 ip-pgclst 100: node1
crm(live)configure# location loc-ip-2 ip-pgclst 10: node2
crm(live)configure# location loc-ip-3 ip-pgclst -inf: node3
++ Изоляция узлов (stonith)
В Pacemaker для каждого узла необходимо указать метод изоляции (fencing) в случае сбоя сетевой доступности. Осуществляется изоляция с помощью stonith ресурсов. Это могут быть программы для отключения питания на UPS, программы, которые подключаются к гипервизору и принудительно завершают работу виртуальной машины (нашего узла кластера) и много других вариантов.
Без STONITH устройств Pacemaker откажется запускать ресурсы:
root:~# crm_verify -L -V
(unpack_resources) error: Resource start-up disabled since no STONITH resources have been defined
(unpack_resources) error: Either configure some or disable STONITH with the stonith-enabled option
(unpack_resources) error: NOTE: Clusters with shared data need STONITH to ensure data integrity
Errors found during check: config not valid
Список устройств для изоляции можно узнать из команды:
root# stonith_admin --list-installed
Параметры, необходимые устройству для работы, можно узнать:
root# stonith -t <имя устройста stonith> -n
Простейшие stonith ресурсы можно создать так.
Ресурс-пустышка dummy - ничего не отключает:
root# crm conf primitive sh-dummy stonith:null params hostlist="192.168.1.11 192.168.1.12 192.168.1.13"
root# crm conf clone fency sh-dummy
SSH-stonith - пытается подключиться к сбойному узлу через SSH и запланировать выключение через службу at (должна быть установлена на всех узлах).
root# apt install at
root# crm conf primitive fence-ssh stonith:ssh params hostlist="192.168.1.11 192.168.1.12 192.168.1.13"
root# crm conf clone fency fence-ssh
Имитируем сбой на узле node3:
root# stonith -t ssh -p "node1 node2 node3" -T reset node3
Для тестирования может понадобится отключение STONITH (НЕ РЕКОМЕНДУЕТСЯ):
root~# crm_attribute -n stonith-enabled -v false
Очистить ошибки можно командой:
root# stonith_admin --cleanup --history=node3
Стоит заметить что, в случае сбоя сети, кроме STONITH устройств, узел кластера может перезагрузить служба OCFS2.
Если у какого-либо узла пропадёт связь с другими узлами, но он продолжит посылать heartbeat сообщения на кластерный диск, то через 30 секунд (значение sysctl kernel.panic = 30) этот узел будет перезагружен принудительно.
++ Настройка PostgreSQL для работы под управлением Pacemaker/Corosync
Для запуска PostgreSQL необходимо создать три ресурса:
*** Ресурс, который будет монтировать ФС, где расположена БД
*** Ресурс виртуального ip-адреса, по которому будут обращаться клиенты к СУБД
*** Ресурс, запускающий процессы СУБД PostgreSQL
После необходимо настроить правила совместного расположения ресурсов и указать порядок запуска.
В примере будет созданы ресурсы, обеспечивающие работу экземпляра СУБД.
++ Ресурс, обеспечивающий монтирование ФС с БД
++ Описание ресурса Pacemaker для ФС OCFS2
Ресурс fs-ocfs2 будет монтировать кластерную ФС OCFS2 в каталог /mnt/ocfs2clst на каждом узле.
Монтирование будет производится по метке ФС.
Том, где расположена БД, у меня имеет UUID метку ce92b1e7-30cb-4883-9a92-57c986f76acd (см. Создание ФС OCFS2).
root~# mkdir -p /mnt/ocfs2clst # выполнить на каждом узле
root@node1:~# crm conf
crm(live/node1)configure# primitive fs-ocfs2 Filesystem \
params device="/dev/disk/by-uuid/ce92b1e7-30cb-4883-9a92-57c986f76acd" \
directory="/mnt/ocfs2clst" \
fstype=ocfs2 options="rw,relatime,commit=5,coherency=buffered" \
op start timeout=60s interval=0 \
op stop timeout=60s interval=0 \
op monitor timeout=40 interval=20
Полный список параметров монтирования можно узнать на странице https://www.kernel.org/doc/html/latest/filesystems/ocfs2.html
По-умолчанию, ресурс запускается только на одном узле, но так как у нас ФС кластерная, необходимо запустить ресурс на всех узлах.
Это возможно с помощью клона ресурса:
crm(live/node1)configure# clone fs-clone-ocfs2 fs-ocfs2
Проверяем конфигурацию и выходим:
crm(live/node1)configure# verify
crm(live/node1)configure# commit
crm(live/node1)configure# quit
После создания ресурса, ФС должна автоматически смонтироваться на всех узлах кластера.
root@node1:~# mounted.ocfs2 -f
Device Stack Cluster F Nodes
/dev/vdb o2cb ocfs2clst node1, node3, node2
++ Правила размещения ресурса на узлах
Если указан параметр symmetric-cluster=false, то для запуска ресурсов необходимо указать явные правила, где ресурсы могут запускаться. Указываем, что ресурс кластерной ФС должен запускаться на всех узлах кластера с равным приоритетом 1:
root~# crm conf
crm(live)configure# location loc-fs-ocfs2-1 fs-clone-ocfs2 1: node1
crm(live)configure# location loc-fs-ocfs2-2 fs-clone-ocfs2 1: node2
crm(live)configure# location loc-fs-ocfs2-3 fs-clone-ocfs2 1: node3
crm(live)configure# verify
crm(live)configure# commit
crm(live)configure# quit
Если symmetric-cluster=true (или параметр не задан), то создавать правила не обязательно.
++ Ресурс виртуального ip-адреса
Создаём ресурс ip-pgclst виртуального ip-адреса 192.168.1.10. Именно этот ip-адрес будет использовать СУБД для приёма подключений.
root~# crm conf
crm(live)configure# primitive ip-pgclst IPaddr \
params ip=192.168.1.10 \
op monitor interval=10s
Если в атрибутах кластера Pacemaker указан параметр symmetric-cluster=false, то аналогично ресурсу файловой системы создаём правила размещения. Ресурс ip-адреса будет располагаться совместно с СУБД. Если производительность узлов отличается, то можно указать разные приоритеты для запуска. Предположим, что node1 мощнее, чем node2, а node3 вообще исключим для работы СУБД:
root~# crm conf
crm(live)configure# location loc-ip-pgclst-1 ip-pgclst 100: node1
crm(live)configure# location loc-ip-pgclst-2 ip-pgclst 10: node2
crm(live)configure# location loc-ip-pgclst-3 ip-pgclst -inf: node3
crm(live)configure# verify
crm(live)configure# commit
crm(live)configure# quit
Если symmetric-cluster=true (или параметр не задан), то создавать правила не обязательно.
У меня в примере правила размещения не используются.
++ Ресурс Pacemaker, запускающий процессы СУБД PostgreSQL
++ Инициализация файлов кластера БД PostgreSQL
Изменяем владельца и права доступа на каталог с БД:
root# chown -R postgres:postgres /mnt/ocfs2clst
root# chmod 750 /mnt/ocfs2clst
Инициализируем файлы кластера БД PostgreSQL в каталоге /mnt/ocfs2clst/pg-data с включением контроля чётности страниц БД, а после запускаем СУБД:
postgres@node1:~$ /usr/lib/postgresql/13/bin/initdb -D /mnt/ocfs2clst/pg-data/ -A peer -k
postgres@node1:~$ /usr/lib/postgresql/13/bin/pg_ctl -D /mnt/ocfs2clst/pg-data/ start
++ Настройка конфигурации PostgreSQL
Подключаемся к СУБД через unix-сокет:
root@node1:~# su - postgres
postgres@node1:~$ psql
Изменяем параметры БД для возможности работы под управлением Pacemaker:
psql> alter system set logging_collector=on;
psql> alter system lc_messages = 'C.UTF-8';
psql> alter system set listen_addresses='192.168.1.10';
Здесь я включил сборщик сообщений (logging collector), поменял язык сообщений на английский (при работе по Pacemaker, русские сообщения заменялись вопросами) и указал, что СУБД должна принимать соединения только на кластерном ip-адресе.
Если потребуется в кластере Pacemaker запустить несколько экземпляров Postgresql, то необходимо разместить unix-сокет СУБД по отдельным каталогам, так как по-умолчанию все экземпляры будут создавать сокет в каталоге /tmp.
psql> alter system set unix_socket_directories = '/mnt/ocfs2clst/pg-data';
Например, если бы у нас было две БД:
СУБД 1, кластерный ip 192.168.1.21, каталог /mnt/ocfs2clst/pg-db1
СУБД 2, кластерный ip 192.168.1.22, каталог /mnt/ocfs2clst/pg-db2
то unix_socket_directories необходимо задать:
psql db1> alter system set unix_socket_directories = '/mnt/ocfs2clst/pg-db1';
psql db2> alter system set unix_socket_directories = '/mnt/ocfs2clst/pg-db2;
В дальнейшем для подключения через unix-сокет необходимо указать путь к нему (команду необходимо выполнять на том узле, где работает СУБД):
postgres@node1:~$ psql -h /mnt/ocfs2clst/pg-data/
Редактируем файл /mnt/ocfs2clst/pg-data/pg_hba.conf, разрешаем подключение по сети с паролем:
...
# IPv4 network connections
host all all all md5
...
После внесения настроек, останавливаем СУБД:
postgres@node1:~$ /usr/lib/postgresql/13/bin/pg_ctl -D /mnt/ocfs2clst/pg-data/ stop
++ Создание ресурса СУБД PostgreSQL
root~# crm configure
crm(live/node1)configure# primitive db-pgclst pgsql \
params pgctl="/usr/lib/postgresql/13/bin/pg_ctl" \
psql="/usr/lib/postgresql/13/bin/psql" \
pgdba=postgres \
pglibs="/usr/lib/postgresql/13/lib" \
pgdata="/mnt/ocfs2clst/pg-data" \
socketdir="/mnt/ocfs2clst/pg-data" \
config="/mnt/ocfs2clst/pg-data/postgresql.conf" \
op start timeout=120s interval=0 \
op stop timeout=120s interval=0 \
op monitor timeout=30 interval=30
Значения параметра socketdir в описании ресурса Pacemaker должно совпадать с параметром unix_socket_directories в файле конфигурации PostgreSQL postgresql.conf/postgresql.auto.conf.
++ Правила размещения ресурса на узлах
Аналогично ресурсу ip-адреса, если в атрибутах указан параметр symmetric-cluster=false, то создаём правила размещения ресура:
root~# crm conf
crm(live)configure# location loc-db-pgclst-1 db-pgclst 100: node1
crm(live)configure# location loc-db-pgclst-2 db-pgclst 10: node2
crm(live)configure# location loc-db-pgclst-3 db-pgclst -inf: node3
crm(live)configure# verify
crm(live)configure# commit
crm(live)configure# quit
Если symmetric-cluster=true (или параметр не задан), то создавать правила не обязательно, тогда СУБД сможет запускаться на любом из узлов, при условии, что ресурсу ip-адреса так же разрешен запуск на всех узлах.
У меня в примере правила размещения не используются.
++ Правила, описывающие совместное расположение ресурсов
Необходимо, чтобы виртуальный ip-адрес и экземпляра СУБД PostgreSQL располагались на одном узле, иначе СУБД не запустится.
crm conf colocation <имя правила> <приоритет>: <ресурс1> <ресурс2>
Для этого создаём соответствующее правило:
root~# crm conf
crm(live/node1)configure# colocation col-ip-pgsql inf: ip-pgclst db-pgclst
crm(live/node1)configure# verify
crm(live/node1)configure# commit
crm(live/node1)configure# quit
++ Правила, описывающие порядок запуска ресурсов
Необходимо, чтобы ресурс виртуального ip-адреса и ресурс, монтирующий кластерную ФС OCFS2, запускались раньше ресурса СУБД PostgreSQL.
crm conf order <имя правила> <приоритет>: <ресурс1> <ресурс2>
Для этого создаём соответсвующие правила:
root~# crm conf
crm(live/node1)configure# order ord-fs-pgsql Mandatory: fs-clone-ocfs2 db-pgclst
crm(live/node1)configure# order ord-ip-pgsql Mandatory: ip-pgclst db-pgclst
crm(live/node1)configure# verify
crm(live/node1)configure# commit
crm(live/node1)configure# quit
++ Проверка работы
После настройки ресурсов проверяем, что все они запущены с помощью команды crm_mon:
root@node1:~# crm_mon -nr1
Cluster Summary:
* Stack: corosync
* Current DC: node3 (version 2.0.5-ba59be7122) - partition with quorum
* Last updated: Sat Jul 16 18:04:00 2022
* Last change: Sat Jul 16 10:52:30 2022 by root via cibadmin on node2
* 3 nodes configured
* 8 resource instances configured
Node List:
* Node node1: online:
* Resources:
* fs-ocfs2 (ocf::heartbeat:Filesystem): Started
* sh-dummy (stonith:null): Started
* Node node2: online:
* Resources:
* sh-dummy (stonith:null): Started
* fs-ocfs2 (ocf::heartbeat:Filesystem): Started
* db-pgclst (ocf::heartbeat:pgsql): Started
* ip-pgclst (ocf::heartbeat:IPaddr): Started
* Node node3: online:
* Resources:
* sh-dummy (stonith:null): Started
* fs-ocfs2 (ocf::heartbeat:Filesystem): Started
Inactive Resources:
* No inactive resources
Из вывода видно, что СУБД запущена на узле node2. Подключимся к нему через ssh и создадим пользователя в Postgresql:
user@pc:~$ ssh user@192.168.1.12
user@node2:~$ sudo su - postgres
postgres@node2:~$ psql -h /mnt/ocfs2clst/pg-data/
postgres=# create role pguser login encrypted password 'пароль';
postgres=# \q
Проверяем подключение к СУБД с клиента:
user@pc:~$ psql -h 192.168.1.10 -U pguser postgres
postgres=> select count(*) from pg_settings;
count
-------
308
(1 строка)
С любого узла кластера перемещаем СУБД на другой узел:
root@node1:~# crm_resource --move -r db-pgclst -H node1
или с помощью CRM Shell
root@node1:~# crm resource move db-pgclst node1
Определяем где запущен ресурс:
root@node1:~# crm_resource -W -r db-pgclst
resource db-pgclst is running on: node1
Выполняем повторный запрос с клиента:
postgres=> select count(*) from pg_settings;
FATAL: terminating connection due to administrator command
сервер неожиданно закрыл соединение
Скорее всего сервер прекратил работу из-за сбоя
до или в процессе выполнения запроса.
Подключение к серверу потеряно. Попытка восстановления удачна.
psql (14.1, сервер 13.7 (Debian 13.7-0+deb11u1))
postgres=> select count(*) from pg_settings;
count
-------
308
(1 строка)
Как видно, при перемещении ресурса все соединения с СУБД закрылись, но повторный sql-запрос выполнился успешно.
Команды перемещения ресуров crm_resource --move или crm resource move на самом делее создают в базе Pacemaker CIB запись:
<rsc_location id="cli-prefer-db-pgclst" rsc="db-pgclst" role="Started" node="node1" score="INFINITY"/>
Эта запись указывает в дальнейшем запускать ресурс db-pgclst на узле node1. Для того чтобы вернуть возможность запуска ресурса на любом из узлов достаточно выполнить одну из команд:
root# crm_resource -r db-pgclst --clear
root# crm resource clear db-pgclst
++ Команды управления кластером Pacemaker
root# crm_verify -L -V - проверка конфигурации Pacemaker
root# crm_mon -rf - отслеживание статуса ресурсов
root# crm_resource -W -r db-pgclst - определить расположение ресурса db-pgclst в кластере
root# crm node standby - приостановить работу узла
root# crm node online - возобновить работу узла
root# crm resource status - посмотреть список ресурсов
root# crm resource move db-pgclst node2 - мигрировать ресурс ip-pgclst на узел node2
root# crm resource clear db-pgclst - убрать привязку после переноса
root# crm resource stop db-pgclst - остановить ресурс db-pgclst
root# crm resource start db-pgclst - запустить работу ресурса db-pgclst
root# crm resource cleanup db-pgclst или # crm_resource --resource db-pgclst --cleanup - сброс количества ошибок ресурса
root# crm configure delete db-pgclst - удаление ресурса
root# cibadmin --query > tmp.xml - создать дамп базы Pacemaker CIB
URL:
Обсуждается: http://www.opennet.dev/tips/info/3211.shtml