Настройка Corosync, Pacemaker и DRBD для Active/Passive PostgreSQL-кластера
К чему это руководство
Это руководство объясняет, как настроить и мониторить Active/Passive кластер PostgreSQL с использованием Pacemaker, Corosync (openAIS) и DRBD. Приведены точные команды для двух узлов (node1 и node2), примеры ожидаемого вывода и подробные списки действий для администраторов. Предполагается базовый опыт работы с Linux, сетью и PostgreSQL.
Важно: все команды и конфигурации даны в том виде, в каком их нужно выполнять. Кодовые блоки и примеры логов сохранены оригинальными.
Основные варианты запроса (SEO intent)
- Настройка Corosync Pacemaker DRBD PostgreSQL
- Active/Passive кластер PostgreSQL
- DRBD мультиплексирование и Pacemaker
- Как настроить кластер PostgreSQL с Corosync
6. Настройка Corosync (openAIS)
Corosync — форк проекта Heartbeat, который хорошо работает вместе с Pacemaker. В этом разделе показано, как подготовить конфигурацию Corosync на двух узлах и как запустить сервис.
Подготовка на node1 — переменные окружения
На node1 установите переменные окружения, которые будут использоваться для генерации конфигурации Corosync:
export ais_port=4000
export ais_mcast=226.94.1.1
export ais_addr=ip address show eth0 | grep "inet " | tail -n 1 | awk '{print $4}' | sed s/255/0/
Пояснение: ais_addr должен содержать сетевой адрес подсети, на котором будет слушать кластер. В примерах статьи это 10.0.0.0.
Проверим переменные:
env | grep ais_Важно: переменная ais_addr должна содержать сетевой адрес подсети кластера (в примере 10.0.0.0).
Создание конфигурации Corosync
Скопируйте пример файла конфигурации и подставьте значения:
cp /etc/corosync/corosync.conf.example /etc/corosync/corosync.conf
sed -i.gres "s/.*mcastaddr:.*/mcastaddr:\ $ais_mcast/g" /etc/corosync/corosync.conf
sed -i.gres "s/.*mcastport:.*/mcastport:\ $ais_port/g" /etc/corosync/corosync.conf
sed -i.gres "s/.*bindnetaddr:.*/bindnetaddr:\ $ais_addr/g" /etc/corosync/corosync.confДобавим секцию aisexec и объявим загрузку Pacemaker в конфигурацию:
cat <<-END >>/etc/corosync/corosync.conf
aisexec {
user: root
group: root
}
END
cat <<-END >>/etc/corosync/corosync.conf
service {
# Load the Pacemaker Cluster Resource Manager
name: pacemaker
ver: 0
}
ENDФайл /etc/corosync/corosync.conf в результате будет содержать примерно следующее:
compatibility: whitetank
totem {
version: 2
secauth: off
threads: 0
interface {
ringnumber: 0
bindnetaddr: 10.0.0.0
mcastaddr: 226.94.1.1
mcastport: 4000
}
}
logging {
fileline: off
to_stderr: yes
to_logfile: yes
to_syslog: yes
logfile: /tmp/corosync.log
debug: off
timestamp: on
logger_subsys {
subsys: AMF
debug: off
}
}
amf {
mode: disabled
}
aisexec {
user: root
group: root
}
service {
# Load the Pacemaker Cluster Resource Manager
name: pacemaker
ver: 0
} Примечание: если ваша сеть использует другое имя интерфейса (не eth0), замените ip-выражение соответствующим интерфейсом.
Распространение конфигурации на node2
Скопируйте конфигурационные файлы Corosync с node1 на node2:
scp /etc/corosync/* node2:/etc/corosync/На обоих узлах создайте директорию для логов кластера:
mkdir /var/log/cluster/Запуск Corosync
На node1 запустите Corosync:
/etc/init.d/corosync startПроверим логи на предмет успешного старта:
grep -e "Corosync Cluster Engine" -e "configuration file" /var/log/messagesПример ожидаемого вывода:
[root@node1 bin]# grep -e “Corosync Cluster Engine” -e “configuration file” /var/log/messages
Apr 7 12:37:21 node1 corosync[23533]: [MAIN ] Corosync Cluster Engine (‘1.2.0’): started and ready to provide service.
Apr 7 12:37:21 node1 corosync[23533]: [MAIN ] Successfully read main configuration file ‘/etc/corosync/corosync.conf’.
Проверка, что Corosync слушает на правильном интерфейсе:
grep TOTEM /var/log/messagesПример:
[root@node1 bin]# grep TOTEM /var/log/messages
Apr 7 12:37:21 node1 corosync[23533]: [TOTEM ] Initializing transport (UDP/IP).
Apr 7 12:37:21 node1 corosync[23533]: [TOTEM ] Initializing transmit/receive security: libtomcrypt SOBER128/SHA1HMAC (mode 0).
Apr 7 12:37:21 node1 corosync[23533]: [TOTEM ] The network interface [10.0.0.191] is now up.
Apr 7 12:37:21 node1 corosync[23533]: [TOTEM ] A processor joined or left the membership and a new membership was formed.
Проверим запуск Pacemaker внутри Corosync:
grep pcmk_startup /var/log/messagesПример:
[root@node1 bin]# grep pcmk_startup /var/log/messages
Apr 7 12:37:21 node1 corosync[23533]: [pcmk ] info: pcmk_startup: CRM: Initialized
Apr 7 12:37:21 node1 corosync[23533]: [pcmk ] Logging: Initialized pcmk_startup
Apr 7 12:37:21 node1 corosync[23533]: [pcmk ] info: pcmk_startup: Maximum core file size is: 4294967295
Apr 7 12:37:21 node1 corosync[23533]: [pcmk ] info: pcmk_startup: Service: 9
Apr 7 12:37:21 node1 corosync[23533]: [pcmk ] info: pcmk_startup: Local hostname: node1
Проверим процессы Corosync и связанные демоны:
ps axfОжидаемый фрагмент вывода:
[root@node1 bin]# ps axf
(should contain something like this)
23533 ? Ssl 0:00 corosync
23539 ? SLs 0:00 _ /usr/lib/heartbeat/stonithd
23540 ? S 0:00 _ /usr/lib/heartbeat/cib
23541 ? S 0:00 _ /usr/lib/heartbeat/lrmd
23542 ? S 0:00 _ /usr/lib/heartbeat/attrd
23543 ? S 0:00 _ /usr/lib/heartbeat/pengine
23544 ? S 0:00 _ /usr/lib/heartbeat/crmd
После успешного старта на node1 запустите Corosync на node2:
/etc/init.d/corosync startПроверка статуса кластера (можно запускать с любого узла):
crm_mon -1Пример вывода:
Last updated: Fri Oct 29 17:44:36 2010
Stack: openais
Current DC: node1.clusterbr.int - partition with quorum
Version: 1.0.9-89bd754939df5150de7cd76835f98fe90851b677
2 Nodes configured, 2 expected votes
0 Resources configured.
Online: [ node1.clusterbr.int node2.clusterbr.int ]
Убедитесь, что оба узла в онлайне.
Сделаем автозапуск Corosync при старте системы на уровнях запуска 3 и 5 (оба узла):
chkconfig --level 35 corosync on7. Настройка Pacemaker
Pacemaker реплицирует конфигурацию кластера между узлами: любые изменения, выполненные на одном узле, применяются ко всему кластеру. Поэтому выполняйте crm-команды только на одном узле в момент времени — не запускайте одну и ту же команду одновременно на двух узлах.
Важные команды управления кластером
- Проверка конфигурации кластера:
crm_verify -L- Показать статус и вернуться в shell:
crm_mon -1- Показать конфигурацию кластера:
crm configure show- Открыть интерактивную консоль crm (введите quit для выхода):
crmНастройка Stonith
STONITH (Shoot The Other Node In The Head) — механизм fencing, который жестко отключает проблемный узел (обычно через устройства удалённого питания или управляющие контроллеры). Без корректного fencing вы рискуете появлением split-brain и повреждением данных.
В этой инструкции STONITH будет отключён (для лабораторной среды). Для продакшена рекомендуется настроить корректное оборудование fencing (IPMI, iLO, DRAC и т. п.). См. документацию проекта для вариантов настройки fencing: http://www.clusterlabs.org/doc/crm_fencing.html
Проверим, что crm_verify выдаёт ошибки, связанные с Stonith:
crm_verify -LЧтобы отключить Stonith (на одном из узлов):
crm configure property stonith-enabled=falseПроверим повторно:
crm_verify -LОбщая конфигурация кластера
Выполните далее команды один раз с любого узла.
Укажем политику при отсутствии кворума — игнорировать (подходит для двухузловой лабораторной конфигурации):
crm configure property no-quorum-policy=ignoreЗададим resource-stickiness, чтобы ресурсы «прилипали» к узлу и не перемещались автоматически при кратковременных проблемах:
crm configure rsc_defaults resource-stickiness=100Проверим конфигурацию:
crm configure showПример части вывода:
[root@node1 ~]# crm configure show
node node1.clusterbr.int
node node2.clusterbr.int
property $id=”cib-bootstrap-options” \
dc-version=”1.0.9-89bd754939df5150de7cd76835f98fe90851b677” \
cluster-infrastructure=”openais” \
expected-quorum-votes=”2” \
stonith-enabled=”false” \
no-quorum-policy=”ignore”
rsc_defaults $id=”rsc-options” \
resource-stickiness=”100”
Конфигурация виртуального IP (DBIP)
Для доступа к PostgreSQL извне нужен плавающий IP. Добавим примитив ресурса IP:
crm configure primitive DBIP ocf:heartbeat:IPaddr2 \
params ip=10.0.0.190 cidr_netmask=24 \
op monitor interval=30sПроверим статус:
Last updated: Fri Oct 29 17:47:53 2010
Stack: openais
Current DC: node1.clusterbr.int - partition with quorum
Version: 1.0.9-89bd754939df5150de7cd76835f98fe90851b677
2 Nodes configured, 2 expected votes
1 Resources configured.
Online: [ node2.clusterbr.int node1.clusterbr.int ]
DBIP (ocf::heartbeat:IPaddr2): Started node2.clusterbr.int
Статус показывает, на каком узле сейчас запущен ресурс (в примере — node2).
Конфигурация DRBD в кластере
Добавим DRBD-ресурс в конфигурацию Pacemaker:
crm configure primitive drbd_postgres ocf:linbit:drbd \
params drbd_resource="postgres" \
op monitor interval="15s"Создадим мастер/слейв (Master/Slave) для DRBD, указывая, что одновременно мастер может быть только один:
crm configure ms ms_drbd_postgres drbd_postgres \
meta master-max="1" master-node-max="1" \
clone-max="2" clone-node-max="1" \
notify="true"Добавим ресурс для монтирования устройства DRBD в файловую систему:
crm configure primitive postgres_fs ocf:heartbeat:Filesystem \
params device="/dev/drbd0" directory="/var/lib/pgsql" fstype="ext3"Конфигурация PostgreSQL как ресурса кластера
Добавим ресурс PostgreSQL (OCF-скрипт pgsql):
crm configure primitive postgresql ocf:heartbeat:pgsql \
op monitor depth="0" timeout="30" interval="30"Теперь создадим группу, в которую войдут виртуальный IP, файловая система и сам PostgreSQL. Имя группы — postgres:
crm configure group postgres postgres_fs DBIP postgresqlСоздадим колокацию, чтобы группа запускалась вместе с DRBD на узле, который является Primary для DRBD:
crm configure colocation postgres_on_drbd inf: postgres ms_drbd_postgres:MasterУкажем порядок запуска — сначала DRBD должно перейти в промоцию (Master), потом запустится postgres:
crm configure order postgres_after_drbd inf: ms_drbd_postgres:promote postgres:startПроверим финальную конфигурацию:
crm configure showПример вывода (основные строки):
primitive DBIP ocf:heartbeat:IPaddr2
params ip=”10.0.0.190” cidr_netmask=”24”
op monitor interval=”30s”
primitive drbd_postgres ocf:linbit:drbd
params drbd_resource=”postgres”
op monitor interval=”15s”
primitive postgres_fs ocf:heartbeat:Filesystem
params device=”/dev/drbd0” directory=”/var/lib/pgsql” fstype=”ext3”
primitive postgresql ocf:heartbeat:pgsql
op monitor interval=”30” timeout=”30” depth=”0”
meta target-role=”Started”
group postgres postgres_fs DBIP postgresql
meta target-role=”Started”
ms ms_drbd_postgres drbd_postgres
meta master-max=”1” master-node-max=”1” clone-max=”2” clone-node-max=”1” notify=”true”
colocation postgres_on_drbd inf: postgres ms_drbd_postgres:Master
order postgres_after_drbd inf: ms_drbd_postgres:promote postgres:start
Назначение предпочтительного узла
Чтобы задать предпочтение для запуска служб на node1, используйте:
crm configure location master-prefer-node1 DBIP 50: node1.clusterbr.intПояснение: вес 50 устанавливает предпочтение, но из-за resource-stickiness=100 Pacemaker не будет перемещать ресурс обратно автоматически, если он работает на другом узле. Это помогает избежать «флаппинга» сервисов и проблем с синхронизацией после кратковременных перебоев.
Проверим статус:
crm_mon -1Пример (все ресурсы запущены на node2):
Last updated: Fri Oct 29 19:54:09 2010
Stack: openais
Current DC: node2.clusterbr.int - partition with quorum
Version: 1.0.9-89bd754939df5150de7cd76835f98fe90851b677
2 Nodes configured, 2 expected votes
2 Resources configured.
Online: [ node2.clusterbr.int node1.clusterbr.int ]
Master/Slave Set: ms_drbd_postgres
Masters: [ node2.clusterbr.int ]
Slaves: [ node1.clusterbr.int ]
Resource Group: postgres
postgres_fs (ocf::heartbeat:Filesystem): Started node2.clusterbr.int
DBIP (ocf::heartbeat:IPaddr2): Started node2.clusterbr.int
postgresql (ocf::heartbeat:pgsql): Started node2.clusterbr.int
Если при проверке статуса появляются ошибки, иногда помогает корректная перезагрузка обоих узлов, чтобы Corosync полностью согласовал конфигурацию. После перезагрузки можно подключиться к DBIP (10.0.0.190) на порт TCP 5432 и проверить работу PostgreSQL.
Тестирование: выключите один узел (poweroff) или остановите corosync на нём и убедитесь, что ресурсы перезапустились на другом узле.
Управление кластером — полезные команды
- Миграция ресурса на конкретный узел:
crm resource migrate postgres node1.clusterbr.int- Отмена миграции:
crm resource unmigrate postgres- Очистка ошибок ресурса:
crm resource cleanup postgres- Остановка ресурса postgres:
crm resource stop postgresql- Запуск ресурса postgres:
crm resource start postgresqlДополнения и практическая информация (value add)
Ниже — дополнительные полезные разделы: чек-листы, план действий при сбое, тест-кейсы, матрица рисков, рекомендации по безопасности и совместимости.
Факт-бокс — ключевые параметры
- Multicast порт Corosync: 4000
- Multicast адрес: 226.94.1.1
- Виртуальный IP (пример): 10.0.0.190/24
- Интервалы мониторинга: DBIP 30s, DRBD 15s, PostgreSQL 30s
- Resource-stickiness: 100
- no-quorum-policy: ignore (для 2-нодовой лаборатории)
- STONITH: отключён (не рекомендуется для продакшена)
Мини‑методология: порядок действий при развертывании
- Подготовьте сеть (уточните интерфейсы, multicast разрешён).
- Настройте DRBD-ресурс и убедитесь в синхронизации дисков вне Pacemaker (локально).
- Настройте Corosync на node1, затем скопируйте конфиг на node2.
- Запустите Corosync на node1, затем на node2, проверьте membership.
- Настройте Pacemaker: stonith, общие свойства, виртуальный IP, DRBD, FS, postgres.
- Протестируйте failover и откат, проверьте целостность данных.
Playbook / SOP для развёртывания (короткий чек‑лист)
Роль: системный администратор
- Актуализировать пакеты Corosync, Pacemaker, DRBD, OCF-скрипты.
- Проверить сетевые настройки (multicast, firewall, MTU).
- Выполнить подготовку переменных ais_port, ais_mcast, ais_addr.
- Скопировать и отредактировать /etc/corosync/corosync.conf.
- Синхронизировать файл /etc/corosync/* на все узлы.
- Создать /var/log/cluster/ на всех узлах.
- Запустить Corosync на node1, проверить логи и ps.
- Запустить Corosync на node2 и проверить crm_mon.
- Настроить Pacemaker (stonith, no-quorum-policy, rsc_defaults).
- Добавить DBIP, drbd_postgres, postgres_fs, postgresql и сгруппировать их.
- Тестировать: остановка узла, сетевая деградация, восстановление.
- Документировать результаты тестов и план отката.
Runbook при отказе (быстрые шаги)
Сценарий: основной узел внезапно упал, но кластер не перевёл ресурсы
- Проверить статус Corosync и Pacemaker на оставшемся узле:
- crm_mon -1
- crm_verify -L
- Если Corosync видит только один узел и нет кворума, проверить no-quorum-policy.
- Если ресурс не стартовал автоматически — попытаться промотировать DRBD и запустить группу:
- crm resource migrate postgres node2.clusterbr.int
- crm resource start postgresql
- Если есть split-brain для DRBD — выполнить ручную проверку состояния DRBD и синхронизацию (drbdadm / drbd-overview).
- При повреждении сервиса PostgreSQL — проверить логи PostgreSQL, fsck (если нужно), и выполнить восстановление из реплики или backup.
Критерии приёмки
- Оба узла видны в crm_mon и имеют корректную роль.
- Виртуальный IP (DBIP) доступен на ожидаемом узле.
- DRBD синхронизирован (Primary/Secondary по ожиданиям).
- PostgreSQL запускается через OCF-скрипт и доступен по DBIP:5432.
- При отключении одного узла ресурсы корректно переносятся на второй узел.
Тест-кейсы / Acceptance tests
- Отключение network-интерфейса на node1: ресурсы должны перейти на node2 за время, близкое к сумме таймаутов мониторинга.
- Выключение node2: ресурсы должны перенестись на node1.
- Возврат node2 в сеть: ресурсы не должны мигрировать автоматически обратно из-за resource-stickiness.
- Split-brain DRBD: симулировать рассинхронизацию и проверить корректность обнаружения и ручной процедуры восстановления.
- Проверка восстановления после перезагрузки: оба узла поднимаются, кластер стабилен.
Матрица рисков и меры снижения
- Риск: отсутствие fencing → возможен split-brain и повреждение данных.
Митигирование: настроить STONITH через IPMI/управляемый PDU в продакшене. - Риск: сетевой флаппинг между узлами → постоянные переводы ресурсов.
Митигирование: увеличить resource-stickiness, настроить сетевая устойчивость и мониторинг. - Риск: ненадёжные проверки здоровья PostgreSQL (слишком буквальные OCF-скрипты).
Митигирование: тестировать сценарии, доработать OCF-скрипт, добавить более глубокие проверки (pg_isready, тестовые запросы).
Безопасность и GDPR-заметки
- Доступ к управляющему интерфейсу кластера (crm, hb) должен быть ограничен по сети и пользователям.
- Логи кластера содержат информацию о состоянии и IP-адресах — храните и архивируйте с учетом корпоративной политики хранения логов.
- Если в кластере хранятся персональные данные, настройте шифрование дисков и корректные бэкапы соответствующие требованиям GDPR/локального законодательства.
Совместимость и примечания по версиям
В примерах логов показаны версии: Corosync 1.2.0 и Pacemaker/CRM 1.0.9. Новые версии Corosync/Pacemaker имеют отличия в конфигурации и командах (systemd unit-файлы вместо /etc/init.d/, изменения в синтаксисе конфигов). Перед применением проверьте совместимость OCF-скриптов (linbit/drbd, heartbeat/Filesystem, pgsql) с вашей версией Pacemaker.
Если вы мигрируете с более старых релизов (Heartbeat → Corosync), выполните тестовую миграцию и проверьте все OCF-ресурсы.
Рекомендации по резервному копированию и тестам отката
- Делайте регулярные полные бэкапы PostgreSQL (pg_basebackup, WAL-архивация).
- Тестируйте восстановление на отдельной тестовой среде.
- Документируйте процедуру ручного recovery при повреждении данных и поддерживайте список контактных лиц.
Чек-лист после развёртывания (быстрая проверка)
- Corosync запущен на обоих узлах
- Узлы видят друг друга в crm_mon
- DBIP отвечает на порту 5432
- DRBD в состоянии синхронизации
- PostgreSQL доступен и отвечает на простые запросы
- STONITH настроен для продакшена или прокомментирован причину отключения
Глоссарий — 1‑строчные определения
- Corosync: коммуникационный слой и менеджер членства кластера.
- Pacemaker: менеджер ресурсов кластера (CRM).
- DRBD: блочное зеркало по сети (disk replication block device).
- STONITH: механизм fencing для изолирования проблемного узла.
- OCF: Open Cluster Framework — стандарт для сценариев запуска ресурсов.
Советы по отладке (полезные команды)
- Просмотр текущего состояния ресурсов: crm_mon -1
- Проверка конфигурации на ошибки: crm_verify -L
- Просмотр лога corosync: tail -n 200 /var/log/messages | grep corosync
- Просмотр логов pacemaker/pengine: /var/log/messages (grep pcmk)
- Проверка статуса DRBD: cat /proc/drbd или drbdadm status
Когда этот подход не подходит (контрпримеры)
- Нужна множественная геораспределённая репликация с автоматическим failover и минимальными задержками для чтения/записи — лучше рассмотреть архитектуры с несколькими мастерами или репликацию на уровне PostgreSQL (logical replication, Patroni, BDR).
- Если нельзя отключать STONITH или нет возможности физически управлять питанием — данный пример с отключением STONITH не подходит для продакшена.
Короткое резюме
- Настройка Corosync + Pacemaker + DRBD позволяет сделать Active/Passive PostgreSQL-кластер с плавающим IP.
- Важные параметры: multicast, bindnetaddr, intervals мониторинга, resource-stickiness и stonith.
- Обязательно протестируйте отказоустойчивость и процедуры восстановления до ввода в продакшн.
Важно: перед развёртыванием в реальном окружении настройте STONITH, протестируйте сетевую устойчивость и выполните резервные копии данных.
Дополнительные материалы и ссылки:
- Документация Pacemaker и Corosync — https://clusterlabs.org/
- DRBD и linbit — https://www.linbit.com/