Отказоустойчивый кластер PostgreSQL с помощью crm
Автор — Игорь Косенков, инженер Postgres Professional
Привет всем! Сегодня речь пойдет о кластере. Да, снова об отказоустойчивом кластере на базе Corosync/Pacemaker. Только настраивать мы его будем не как обычно — с помощью утилиты pcs, а с помощью мало используемой утилиты crm.
С точки зрения использования этих утилит (pcs и crm) весь мир Unix-like операционок делится на два вида:
- содержит пакеты утилиты pcs (RHEL, CentOS, Debian, Ubuntu);
- содержит пакеты утилиты crm (SLES, Opensuse, Elbrus, Leningrad и т.д.).
crm — cluster resource manager — специальная утилита, которая используется для создания и управления отказоустойчивым кластером. Она включена в пакет crmsh, который обычно не входит в состав самых распространенных дистрибутивов Linux.
Идея написать статью об этой утилите пришла однажды, когда я спросил у поисковика: «Как настроить отказоустойчивый кластер с помощью crm». В ответ не получил ничего нужного и полезного, т.к. поисковик мне предложил много вариантов, никак не связанных с crm.
В то же время, если спросить у поисковика про утилиту настройки кластера pcs, которая является по функционалу такой же утилитой, как и crm
, то информации будет много. Есть даже несколько статей на Хабре (в том числе и моя статья Кластер pacemaker/corosync без валидола).
Утилита crm такая же мощная и гибкая, как и pcs, но незаслуженно обделена вниманием.
Решено было исправить этот пробел и написать статью.
Причины, по которым те или иные разработчики дистрибутивов предпочитают кто crm, а кто pcs, мне неизвестны. Могу предположить, что все дело в зависимостях. Например, если сравнить количество зависимостей у pcs и crm, то получается такая картина:
$ sudo rpm -qpR crmsh-3.0.1-1.el7.centos.noarch.rpm | wc -l
19
$ sudo rpm -qpR pcs-0.9.169-3.el7.centos.x86_64.rpm | wc -l
50
Сторонники минимализма, скорей всего, предпочтут crmsh. А если еще учесть, что pcs «тянет» за собой ruby, openssl, pam и python, а crmsh только python, то выбор в некоторых случаях будет однозначно на стороне crm. В каких случаях? Ну, например, при сертификации ОС есть некоторые трудности с пакетом ruby. Также известны случаи, когда в банковских структурах служба безопасности не разрешает установку нерегламентированного ПО.
Сходства и различия
У утилиты crm есть как сходства, так и различия с известной всем утилитой pcs.
Сходства утилит приведены в таблице 1:
На этом сходства заканчиваются и дальше идут различия, которых много, поэтому привожу лишь некоторые из них (таблица 2):
Различия начинаются с самого начала — с момента инициализации кластера. Инициализировать кластер с помощью crm можно одной командой, а у pcs это происходит в два этапа — авторизация и инициализация.
Удалить кластер («разобрать») у pcs можно одной командой сразу, а у crm необходимо удалять по одному узлу до тех пор, пока их не останется в кластере.
Чтобы изменить параметры ресурса, который мы уже создали в кластере, у pcs есть опция update. У crm такой опции нет, но есть команда configure edit, которая позволяет менять любые настройки кластера налету и мгновенно. Даже больше — мы можем за один прием отредактировать любое количество параметров и ресурсов, и в конце редактирования применить все изменения сразу. Удобно? Думаю, да.
Еще различие – у pcs есть веб-интерфейс, с помощью которого можно выполнить различные действия – запустить, остановить, создать какой-нибудь ресурс с помощью любого браузера.
У crm в стандартной поставке нет веб-инструмента, но зато он есть в коммерческой версии SUSE — HAWK.
Подготовка к настройке отказоустойчивого кластера
Лучший способ узнать и познакомиться с crm — это настроить отказоустойчивый кластер.
Чем мы сейчас и займемся. Для примера возьмем ОС CentOS 7.9.
Для создания отказоустойчивого кластера PostgreSQL нам понадобится стенд, состоящий из 3-х узлов — node1, node2, node3. На каждом узле установлена ОС CentOS 7.9 и пакеты corosync, pacemaker, fence-agents* (агенты фенсинга).
В качестве СУБД будем использовать Postgres Pro Standard v.11, но вы можете с таким же успехом использовать «ванильную» версию PostgreSQL. В нашей системе установлены необходимые пакеты — postgrespro-std-11-server, postgrespro-std-11-libs, postgrespro-std-11-contrib, postgrespro-std-11-client.
Настройки СУБД (postgresql.conf) и доступа к ней (pg_hba.conf) не рассматриваются в данной статье, информации об этом достаточно в интернете. На одном из узлов (например, node1) необходимо инициализировать базу данных с помощью initdb, а на двух других узлах с помощью pg_basebackup скопировать базу данных с node1.
Кроме того, в будущем кластере должны быть настроены синхронизация времени на узлах и разрешение имен узлов в кластере с помощью файла /etc/hosts.
ПРИМЕЧАНИЕ:
В этом разделе все команды необходимо выполнить на всех узлах кластера.
Поскольку пакет crmsh не входит в состав дистрибутива ОС, то необходимо подключить репозиторий Extra OKay Packages for Enterprise Linux с этим пакетом.
node1,2,3$ sudo rpm -ivh http://repo.okay.com.mx/centos/7/x86_64/release/okay-release-1-5.el7.noarch.rpm
Нам также понадобится репозитарий EPEL:
node1,2,3$ sudo yum install epel-release
node1,2,3$ sudo yum update
Устанавливаем пакет crmsh:
node1,2,3$ sudo yum install crmsh
При установке и настройке кластера нам также понадобится пакет csync2
. Это пакет синхронизации конфигураций, созданный специально для кластеров.
Разработчики crmsh
вставили код вызова этой кластерной утилиты для удобства настройки. Можно, конечно, обойтись и без csync2
, но в таком случае будет больше ручной работы с конфигурационными файлами на каждом узле.
ОТСТУПЛЕНИЕ:
Сервис csync2 может использоваться не только для создания отказоустойчивого кластера Corosync/Pacemaker. Например, если есть несколько серверов, у которых меняются конфигурационные файлы и эти файлы периодически нужно синхронизировать по критерию «самый свежий файл».
Итак, устанавливаем csync2
и простейшую базу данных для хранения мета-данных (sqlite).
$ sudo yum install csync2 libsqlite3x-devel
Тут нас поджидает подводный камень.
Поскольку csync2 и crmsh не являются «родными» для CentOS, то без дополнительных «танцев» сразу после установки они не заработают. Вызов crm влечет вызов утилиты csync2, которой в свою очередь не хватает парочки systemd-юнитов. Почему этих файлов нет в пакете csync2 для CentOS — мне неизвестно. Замечу, что в коммерческом дистрибутиве SLES (crmsh там «родной») все необходимые файлы есть, все работает из коробки сразу после установки пакетов.
Итак, создадим и добавим недостающие systemd-юниты.
Первый называется csync2.socket
и содержит:
[Socket]
ListenStream=30865
Accept=yes
[Install]
WantedBy=sockets.target
Второй называется csync2@.service
с таким содержимым:
[Unit]
Description=csync2 connection handler
After=syslog.target
[Service]
ExecStart=-/usr/sbin/csync2 -i -v
StandardInput=socket
StandardOutput=socket
Оба файла нужно разместить в стандартной папке systemd — /usr/lib/systemd/system.
Юнит, относящийся к сокету, нужно активировать и установить в автозапуск при загрузке ОС:
node1,2,3$ sudo systemctl enable --now csync2.socket
Примечание. Все настройки выполнялись для ОС CentOS, но есть подозрение, что эти действия также понадобятся и для других систем, например, для Debian или Ubuntu.
Теперь у нас все готово к началу работ по настройке кластера.
Настройка кластера с помощью crm
Настройка кластера производится в 2 этапа — инициализация, затем создание и добавление ресурсов. Инициализация кластера с настроенным сервисом синхронизации конфигураций csync2 производится на одном узле.
Если по каким-то причинам вам не удалось «победить» этот сервис, то это не беда, в конце статьи я расскажу, как обойтись без csync2.
На всякий случай сначала удалим кластер (на всех узлах) с помощью такого набора команд:
node1,2,3$ sudo systemctl stop corosync;sudo find /var/lib/pacemaker/cib/ -type f -delete; sudo find -f /etc/corosync/ -type f -delete
Далее надо выполнить команду инициализации кластера:
node1$ sudo crm cluster init --name demo-cluster --nodes "node1 node2 node3" --yes
где demo-cluster — название нашего кластера.
По этой команде создаются необходимые файлы в папке /etc/corosync: corosync.conf, ключ авторизации authkey, а также прописываются ssh-ключи для беспарольной авторизации и выполнения команд в кластере с привилегиями суперпользователя root (на всех трех узлах кластера).
По умолчанию инициализация кластера выполняется в режиме multicast. Но есть также возможность проинициализировать кластер в режиме unicast:
node1$ sudo crm cluster init --unicast --name demo-cluster --nodes "node1 node2 node3" --yes
Кластер проинициализирован и запущен.
Проверить работоспособность можно с помощью консольного монитора состояния кластера crm_mon:
node1$ sudo crm_mon -Afr
Далее можно приступать к созданию ресурсов в кластере.
Создание ресурсов в кластере
Для начала поменяем некоторые значению по умолчанию. Например, порог миграции ресурсов migration-threshold по умолчанию равен 0. Меняем на 1, чтобы после первого сбоя ресурсы мигрировали на другой узел.
node1$ sudo crm configure rsc_defaults rsc-options: migration-threshold=1 resource-stickiness=INFINITY
По умолчанию кластер запускается в симметричном режиме.
Чем отличается симметричный кластер от несимметричного? В симметричном кластере любой созданный ресурс будет запускаться на любом узле, если не установлены дополнительные правила размещения или старта.
В несимметричном — наоборот, ресурс не будет запущен ни на одном узле, пока явно не будет указано, где и в какой последовательности его запускать.
Зачем это нужно? Ну, например, в ситуации, когда в кластере ресурсы запускаются не на всех узлах, т.е. узлы неравноценны по ресурсам и назначению.
Если, вдруг, вам когда-то понадобится изменить режим кластера с симметричного на несимметричный, то достаточно ввести команду:
node1$ sudo crm configure property symmetric-cluster=false
Мы оставим этот параметр без изменения.
Включаем механизм stonith:
node1$ sudo crm configure property stonith-enabled=yes
Создадим и добавим ресурс «виртуальный IP адрес»:
node1$ sudo crm configure primitive master-vip IPaddr2 op start timeout=20s interval=0 op stop timeout=20s interval=0 op monitor timeout=20s interval=10s params ip=<virtual IP> nic=eth0
где <virtual IP> — виртуальный IP-адрес в кластере.
С помощью монитора состояния кластера crm_mon можно убедиться в том, что ресурс успешно создан и запущен на первом попавшемся узле:
node1$ sudo crm_mon -Afr
Создадим ресурс postgresql и назовем его pg:
node1$ sudo crm configure primitive pg pgsql op start interval=0 timeout=120s op stop interval=0 timeout=120s op monitor interval=30s timeout=30s op monitor interval=29s role=Master timeout=30s params pgctl="/opt/pgpro/std-11/bin/pg_ctl" psql="/opt/pgpro/std-11/bin/psql" pgdata="/var/lib/pgpro/std-11/data" pgport="5432" repuser=postgres master_ip=<virtual IP> rep_mode=sync node_list="node1 node2 node3"
ПРИМЕЧАНИЕ:
В данном примере пути расположения бинарников и БД указаны по умолчанию для версии Postgres Pro Std 11. Также для упрощения указан пользователь для репликации «postgres». Но ничто не мешает вам изменить «умолчательные» пути и пользователя репликации на свои.
Хочу обратить внимание на параметр rep_mode: он задан «sync». Это означает, что в отказоустойчивом кластере хотя бы одна реплика будет синхронной. Синхронность реплики в кластере обеспечивает RPO=0 (кластер без потерь данных в случае сбоя).
Зададим тип ресурса Master-Standby (ms):
node1$ sudo crm configure ms mspg pg meta target-role=Master clone-max="3"
Нам нужно, чтобы ресурсы vip-master и mspg в режиме «мастер» запускались на одном узле:
node1$ sudo crm configure colocation pgsql-colocation inf: master-vip:Started mspg:Master
Указываем порядок запуска ресурсов – сначала СУБД в режиме «мастер», потом виртуальный IP:
node1$ sudo crm configure order order-promote-pgsql Mandatory: mspg:promote master-vip:start
Таким образом, мы создали 2 необходимых ресурса — виртуальный IP адрес и ресурс postgresql.
Теперь можно переходить к настройке фенсинга в отказоустойчивом кластере.
Фенсинг узлов
Про фенсинг в кластере — что это и зачем он нужен — есть много информации в интернете, не хочется повторяться. Добавлю только одно — он необходим в любом кластере. А это значит, что мы его сейчас настроим.
Для начала можно ознакомиться со списком всех агентов фенсинга:
node1$ sudo crm ra list stonith
На моем стенде node1, node2, node3 — это виртуальные машины, которые запущены и управляются с помощью гипервизора KVM. Соответственно, ресурс-агент фенсинга для KVM называется fence_virsh.
Вывести полную информацию о fence_virsh:
node1$ sudo crm ra info stonith:fence_virsh
Прежде чем создавать ресурс фенсинга, рекомендую проверить работоспособность всей цепочки от ОС виртуалки до гипервизора.
Проверка работоспособности фенсинга для узла node1 выглядит так:
node1$ fence_virsh -a <hypervisor IP> -l <username>-p <password> -n node1 -x --use-sudo -o status
где username & password — учетная запись на хосте гипервизора.
Фенсинг для node1 настраивается так:
node1$ sudo crm configure primitive fence-node1 stonith:fence_virsh params ipaddr=<hypervisor IP> ip=<hypervisor IP> login=<username> username=<username> passwd=<password> pcmk_host_list=node1 sudo=1 op monitor interval=60s
ПРИМЕЧАНИЕ:
Ресурсы фенсинга не должны запускаться на «своих» узлах, иначе фенсинг может не сработать.
Следующее правило расположения запретит ресурсу фенсинга для узла node1 располагаться на этом узле:
node1$ sudo crm configure location l_fence_node1 fence-node1 -inf: node1
Для node2:
node2$ sudo crm configure primitive fence-node2 stonith:fence_virsh params ipaddr=<hypervisor IP> ip=<hypervisor IP> login=<username> username=<username> passwd=<password> pcmk_host_list=node2 sudo=1 op monitor interval=60s
node2$ sudo crm configure location l_fence_node2 fence-node2 -inf: node2
Для node3:
node3$ sudo crm configure primitive fence-node3 stonith:fence_virsh params ipaddr=<hypervisor IP> ip=<hypervisor IP> login=<username> username=<username> passwd=<password> pcmk_host_list=node3 sudo=1 op monitor interval=60s
node3$ sudo crm configure location l_fence_node3 fence-node3 -inf: node3
Можно написать скрипт, который будет содержать все команды сразу, останется только его выполнить. Но сегодня наша цель не автоматизация создания кластера, а изучение crm.
Инициализация кластера с помощью crm без csync2
Как обещал выше, расскажу про вариант инициализации кластера без установки и настройки csync2 (если по каким-то причинам вам не удалось его настроить).
Сначала вариант с использованием multicast.
Все команды выполняются на одном узле, например, на node1.
node1$ sudo crm cluster init --name demo-cluster --nodes "node1" --yes
По этой команде создаются необходимые файлы в папке /etc/corosync: corosync.conf, ключ авторизации authkey.
Далее нужно скопировать авторизационный файл authkey и corosync.conf на узлы node2 и node3:
node1$ sudo scp /etc/corosync/{authkey,corosync.conf} node2:/etc/corosync/
node1$ sudo scp /etc/corosync/{authkey,corosync.conf} node3:/etc/corosync/
На остальных узлах (на node1 кластер уже запущен) запустить кластер:
node2,3$ sudo crm cluster start
С помощью монитора crm_mon можно убедиться, что кластер проинициализирован и запущен:
node1$ sudo crm_mon -Afr
В случае настройки кластера с использованием unicast действия и команды будут отличаться.
Все команды выполняются на одном узле, например, на node1.
node1$ sudo crm cluster init --unicast --name demo-cluster --nodes "node1" --yes
Открываем файл /etc/corosync/corosync.conf и добавляем строки в секцию nodelist:
node {
ring0_addr: node2
nodeid: 2
}
node {
ring0_addr: node3
nodeid: 3
}
В секции quorum меняем число голосов:
expected_votes: 3
Далее необходим рестарт сервиса corosync на первом узле:
node1$ sudo systemctl restart corosync
Затем нужно скопировать файл authkey и отредактированный corosync.conf на узлы node2 и node3:
node1$ sudo scp /etc/corosync/{authkey,corosync.conf} node2:/etc/corosync/
node1$ sudo scp /etc/corosync/{authkey,corosync.conf} node3:/etc/corosync/
На остальных узлах (на node1 кластер уже запущен) запустить кластер:
node2,3$ sudo crm cluster start
С помощью монитора crm_mon можно убедиться, что кластер проинициализирован и запущен:
node1$ sudo crm_mon -Afr
На этом инициализация кластера без csync2 закончена.
Вспомогательные команды crm
При работе с кластером могут пригодиться некоторые crm-команды.
Для удобства команды и пояснения сведены в таблицу 3:
На этом все. Буду рад, если статья поможет кому-то в создании и настройке отказоустойчивого кластера с помощью утилиты crm.