Отказоустойчивый кластер Postgresql 9.6

Автор:human

Отказоустойчивый кластер Postgresql 9.6

Кластер Postgresql — repmgr,haproxy,keepalived,pgbouncer

image
На сегодняшний день процедура реализации «failover» в Postgresql является одной из самых простых и интуитивно понятных. Для ее реализации необходимо определиться со сценариями файловера — это залог успешной работы кластера, протестировать его работу. В двух словах — настраивается репликация, чаще всего асинхронная, и в случае отказа текущего мастера, другая нода(standby) становится текущем «мастером», другие ноды standby начинают следовать за новым мастером.
На сегодняшний день repmgr поддерживает сценарий автоматического Failover — autofailover, что позволяет поддерживать кластер в рабочем состоянии после выхода из строя ноды-мастера без мгновенного вмешательства сотрудника, что немаловажно, так как не происходит большого падения UPTIME. Для уведомлений используем telegram.

Появилась необходимость в связи с развитием внутренних сервисов реализовать систему хранения БД на Postgresql + репликация + балансировка + failover(отказоустойчивость). Как всегда в интернете вроде бы что то и есть, но всё оно устаревшее или на практике не реализуемое в том виде, в котором оно представлено. Было решено представить данное решение, чтобы в будущем у специалистов, решивших реализовать подобную схему было представление как это делается, и чтобы новичкам было легко это реализовать следуя данной инструкции. Постарались описать все как можно подробней, вникнуть во все нюансы и особенности.

Итак, что мы имеем: 5 VM с debian 8,Postgresql 9.6 + repmgr (для управления кластером), балансировка и HA на базе HAPROXY (ПО для обеспечения балансировки и высокой доступности web приложения и баз данных) и легковесного менеджера подключений Pgbouncer , keepalived для миграции ip адреса(VIP) между нодами,5-я witness нода для контроля кластера и предотвращения “split brain” ситуаций, когда не могла быть определена следующая мастер нода после отказа текущего мастера. Уведомления через telegram( без него как без рук).
Пропишем ноды /etc/hosts — для удобства, так как в дальнейшем все будет оперировать с доменными именами.

VIP 10.1.1.192 — запись, 10.1.1.202 — roundrobin(балансировка/только чтение).

Установка Postgresql 9.6 pgbouncer haproxy repmgr

Ставим на все ноды

Отключаем автозапуск Postgresql при старте системы — всеми процессами будет управлять пользователь postgres. Так же это необходимо, для того, чтобы бы не было ситуаций, когда у нас сможет оказаться две мастер-ноды, после восстановления одной после сбоя питания, например.

заменяем «auto» на «manual».
Лучше использовать chkconfig для контроля и управления автозапуском всех процессов в debian
apt-get install chkconfig -y

Смотрим всех

Смотрим postgresql
Отключаем

Смотрим postgresql теперь

Готово

Настройка ssh соединения без пароля — между всеми нодами(делаем на всех серверах)
Настроим подключения между всеми серверами и к самому себе через пользователя postgres(через пользователя postgres подключается также repmgr).
Установим пакеты, которые нам понадобятся для работы(сразу ставим)

Для начала установим ему локальный пароль для postgres (сразу проделаем это на всех нодах).

Введем новый пароль.
Ок.
Далее настроим ssh соединение

Генерируем ключ — без пароля.
Ставим ключ на другие ноды

Сразу настроим так же подключение из под postgres к root. Для возможности перезапускать сервисы при подключении через ssh.

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

Рестартуем ssh.
Данная опция удобная когда вы не слишком заботитесь о безопасности, например для тестирования кластера.
Перейдем на ноду 2,3,4 и всё повторим. Теперь мы можем гулять без паролей между нодами для переключения их состояния(назначения нового мастера и standby).
Ставим pgbouncer из git
Установим необходимые пакеты для сборки

Если хотите postgresql с PAM авторизацией — то ставим еще дом модуль и при configure ставим —with-pam

Ставим версию — 1.7.2 (на ноябрь 2016 года).
Готово. Видим

Обязательно настроим окружение — добавим переменную PATH=/usr/lib/postgresql/9.6/bin:$PATH(на каждой ноде).
Добавим в файл ~/.bashrc

Вставим код

Сохранимся.
Скопируем файл на .bashrc другие ноды

Настройке сервера в качестве мастера(pghost195)

Отредактируем конфиг /etc/postgresql/9.6/main/postgresql.conf — Приводим к виду необходимые опции(просто добавим в конец файла).

Как мы видим — будем запускать postgresql на порту 5433 — потому-что дефолтный порт для приложений будем использовать для других целей — а именно для балансировки,проксирования и failover’a. Вы же можете использовать любой порт, как вам удобно.
Настроим файл подключений

Приведем к виду

Применим права к конфигам, иначе будет ругаться на pg_hba.conf — нет доступа и postgresql не стартанет

Стартуем postgres(от postgres user).

Настройка пользователей и базы на Master-сервере(pghost195).

Создадим пользователя repmgr.

Создадим пользователя test_user с паролем 1234

Конфигурируем repmgr на master

Содержимое
cluster=etagi_test
node=1
node_name=node1
use_replication_slots=5
conninfo=’host=pghost195 port=5433 user=repmgr dbname=repmgr’
pg_bindir=/usr/lib/postgresql/9.6/bin

Сохраняемся.
Регистрируем сервер как мастер.

Смотрим наш статус

Видим

Идем дальше.

Настройка слейвов(standby) — pghost196,pghost197,pghost198

Конфигурируем repmgr на slave1(pghost197)

Содержимое

Сохраняемся.
Регистрируем сервер как standby

Будут скопированы конфиги на основании которых будет происходит переключение состояний master и standby серверов.
Просмотрим файлы, которые лежат в корне папки /var/lib/postgresql/9.6/main — обязательно должны быть эти файлы.

Регистрируем сервер в кластере

Видим

Настройка второго stand-by — pghost197
Конфигурируем repmgr на pghost197
nano /etc/repmgr.conf — создаем конфиг
Содержимое

Сохраняемся.
Регистрируем сервер как standby

или

Создадим временную папку, иначе постгрес будет ругаться

Данная команда с опцией -r/—rsync-only — используется в некоторых случаях, например, когда копируемый каталог данных — это каталог данных отказавшего сервера с активным узлом репликации.
Также будут скопированы конфиги на основании которых будет происходит переключение состояний master и standby серверов.
Просмотрим файлы, которые лежат в корне папки /var/lib/postgresql/9.6/main — обязательно должны быть следующие файлы:

Стартуем postgres(от postgres)

Регистрируем сервер в кластере

Просмотр состояния кластера

Видим

Настройка каскадной репликации.

Вы также можете настроить каскадную репликацию. Рассмотрим пример.
Конфигурируем repmgr на pghost198 от pghost197
nano /etc/repmgr.conf — создаем конфиг
Содержимое

Сохраняемся. Как мы видим, что в upstream_node мы указали node3, которой является pghost197.
Регистрируем сервер как standby от standby

Стартуем postgres(от postgres)

Регистрируем сервер в кластере

Просмотр состояния кластера

Видим

Настройка Автоматического Failover’а.

image
Итак мы закончили настройку потоковой репликации. Теперь перейдем к настройка автопереключения — активации нового мастера из stand-by сервера. Для этого необходимо добавить новые секции в файл /etc/repmgr.conf на stand-by серверах. На мастере этого быть не должно!!!!!
!!!!!!!!Конфиги на standby(slave’s) должны отличаться — как в примере ниже . Выставим разное время(master_responce_timeout)!!!!!!!
Добавляем строки на pghost196 в /etc/repmgr.conf

Добавляем строки на pghost197 в /etc/repmgr.conf

Добавляем строки на pghost198 в /etc/repmgr.conf

Как мы видим все настройки автофейоловера идентичны, разница только в priority. Если 0, то данный Standby никогда не станет Master. Данный параметр будет определять очередность срабатывания failover’a, т.е. меньшее число говорит о большем приоритете, значит после отказа master сервера его функции на себя возьмет pghost197.

Также необходимо добавить следующие строки в файл /etc/postgresql/9.6/main/postgresql.conf (только на stand-by сервера!!!!!!)

shared_preload_libraries = ‘repmgr_funcs, pg_stat_statements, pg_buffercache’

Для запуска демона детектирования автоматического переключения необходимо:

Процесс repmgrd будет запущен как демон. Смотрим

Видим

Всё ок. Идём дальше.

Проверим работу автофейловера

Пока все нормально — теперь проведем тест. Остановим мастер — pghost195

В логах на pghost196

Видим

В логах на pghost197

Видим

Всё работает. У нас новый мастер — pghost196, pghost197,pghost198 — теперь слушает stream от pghost2.

Возвращение упавшего мастера в строй!!!

image
Нельзя просто так взять и вернуть упавший мастер в строй. Но он вернется в качестве слейва.
Postges должна быть остановлена перед процедурой возвращения.
На ноде, которая отказала создаем скрипт. В этом скрипт уже настроено уведомление телеграмм, и настроена проверка по триггеру — если создан файл /etc/postgresql/disabled, то восстановление не произойдет. Так же создадим файл /etc/postgresql/current_master.list с содержимым — именем текущего master.

Назовем скрипт «register.sh» и разместим в каталоге /etc/postgresql
Скрипт восстановления ноды в кластер в качестве standby

Как вы видите у нас также есть в скрипте файл repmgrd.sh и telegram.sh. Они также должны находится в каталоге /etc/postgresql.

Скрипт для отправки уведомлений в telegram через аргумент/

Для отправки уведомлений через консоль будет использовать конструкцию вида

Отредактируем конфиг repmgr на упавшем мастере

Сохранимся.
Теперь запустим наш скрипт, на отказавшей ноде. Не забываем про права(postgres) для файлов.

Увидим

Вывод состояния кластера

Как мы видим скрипт отработал, мы получили уведомления и увидели состояние кластера.

Реализации процедуры Switchover(смены мастера вручную).

Допустим наступила такая ситуация, когда вам необходимо поменять местами мастер и определенный standby.
Допустим хотим сделать мастером pghost195 вместо ставшего по фейловеру pghost196, после его восстановления в качестве слейва. Наши шаги.
На pghost195

Теперь нам необходимо дать команду репликам, кроме старого мастера, дать команду на перенос на новый мастер
На pghost197

Видим что мы следуем за новым мастером.
На pghost198 — то же самое

Видим что мы следуем за новым мастером.
На pghost196 — он был предыдущим мастером, у которого мы отобрали права

Видим ошибку

Cтопаем pghost196

Для ее исправления идем на phgost195(новый мастер)

Видим

Идем на pghost196, и делаем все по аналогии с пунктом.

Создание и использование witness ноды

image
Witness нода используется для управления кластером, в случае наступления файловера и выступает своего рода арбитром, следит за тем чтобы не наступали конфликтные ситуации при выборе нового мастера. Она не является активной нодой в плане использования как standby сервера, может быть установлена на той же ноде что и postgres или на отдельной ноде.
Добавим еще одну ноду pghost205 для управления кластером( настройка абсолютно аналогична настройке слейва), толь будет отличаться способ копирования:

Увидим вывод

Готово. Идем далее. Правим файл repmgr.conf для witness ноды
Отключаем автоматический файловер на ноде witness

На witness ноде обязательно изменить порт на 5499 в conninfo.
Обязательно (пере)запускаем repmgrd на всех нодах, кроме мастера

Настройка менеджера соединений Pgbouncer и балансировки через Haproxy. Отказоустойчивости через Keepalived.

image

Настройка Pgbouncer

Pgbouncer мы уже установили заранее. Для чего он нужен…

Мультиплексором соединений. Он выглядит как обычный процесс Postgres, но внутри он управляет очередями запросов что позволяет в разы ускорить работу сервера. Из тысяч запросов поступивших к PgBouncer до базы данных дойдет всего несколько десятков.
Перейдем к его настройке.
Скопируем установленный pgbouncer в папку /etc/(для удобства)

Приведем к виду файл в

Отредактируем файл

Применим права

После редактирования запустим командой как демон (-d)

Смотрим порт

Смотрим лог

Пробуем подключиться. Повторяем все тоже на всех нодах.

Установка и настройка Haproxy.

image
Ставим Xinetd и Haproxy

Добавляем строку в конец файла

Устанавливаем скрипт для проверки состояния postgres — pgsqlcheck

Сохраняемся.
Настраиваем haproxy.
Редактируем конфиг — удалим старый и вставим это содержимое. Этот конфиг для первой ноды, на которой крутится мастер, на данный момент допустим, что это pghost195. Соответственно для данного хоста мы сделаем активным в пуле соединений свой-же хост, работающий на порте 6432(через pgbouncer).

Сам порт haproxy для подключения к базе крутится на порте 5432. Админка доступна на порте 8080. Пользователь admin с паролем adminpassword.
Рестартим сервисы

Тоже самое делаем еще на всех нодах.
На той ноде, которую вы хотите сделать балансировщиком, например pghost198(запросы на нее будут идти только на чтение) конфиг haproxy приводим к такому виду.

Статистику смотри на http://hostip:8080

Установка keepalived.

Keepalived позволяет использовать виртуальный ip адрес (VIP) и в случае выходы из строя одной из нод(выключение питания или другое событие) ip адрес перейдет на другую ноду. Например у нас будет VIP 10.1.1.192 между нодой pghost195,pghost196,pghost197. Соответвенно при выключение питании на ноде pghost195 нода pghost196 автоматически присвоит себе ip addr 10.1.1.192 и так как она является второй в приоритете на продвижение к роли мастера станет доступной для записи благодаря или haproxy или pgbouncer — тут все зависит от вашего выбора. В нашем сценарии — это Haproxy.

Ставим keepalived

Настраиваем keepalived. Приводим к виду. НА 1-ой ноде(pghost195)

Рестартим

Настраиваем keepalived на 2-ой ноде(pghost196)

Настраиваем keepalived на 3-ой ноде(pghost197)

Рестартим

Как мы видим, мы также можем использовать скрипты, например для уведомления при изменении состояния. Смотрим следующую секцию

Так же из конфига видно что мы настроили VIP на 10.1.8.111 который будет жить на eth0. В случае падения ноды pghost195 он перейдет на pghost196, т.е. подключение мы так же будем настраивать через IP 10.1.1.192. так же установим на pghost197, только изменим vrrp_instance и lvs_id LVS_.
На нодах pghost196,pghost197 отключим keepalived. Он будет запускаться только после процедуры failover promote, которая описана в файле. Мы указали

в файле /etc/repmgr.conf (см. в конфигах выше).
Данные скрипты будут запускаться при возникновении failover ситуации -отказе мастера.
promote_command=’sh /etc/postgresql/failover_promote.sh — выпоняет номинированный на master host,
follow_command=’sh /etc/postgresql/failover_follow.sh’ — исполняют ноды, которые следуют за мастером.

Конфиги

Файл /etc/postgresql/failover_promote.sh

Скрипт остановки мастера — принудительного failover, удобно использовать для тестирования процедур «перевыборов» в кластере.

С помощью скриптов можно понять логику работу и настроить сценарии под себя. Как мы видим из кода ,нам будет необходим доступ к root пользователю от пользователя postgres. Получаем его таким же образом — через ключи. Про это уже говорилось выше, но всё же.

Повторяем на всех нодах.
Для особых параноиков, можем настроить скрипт проверки состояний и добавить его в крон например раз в 2 минуты. Сделать это можно без, используя конструкции и используя полученные значения из файлов.

Дополнения и устранение неисправностей.

Сбор статистики запросов в базу

Мы добавили библиотеку pg_stat_statements( необходимо сделать рестарт)

Далее активируем расширение:

# CREATE EXTENSION pg_stat_statements;

Пример собранной статистики:

Для сброса статистики есть команда pg_stat_statements_reset:

Удаление ноды из кластера если она ‘FAILED’

где — etagi_test — название кластера;
node1 — имя ноды в кластере

Проверка состояния репликации

Если в базе давно не было Insert’ов — то это значение будет увеличиваться. На hiload базах это значение будет стремиться к нулю.

Устранение ошибки Slot ‘repmgr_slot_номер слота’ already exists as an active slot

Останавливаем postgresql на той ноде, на которой возникла ошибка

На ноде master’e

Устранение ошибки INSERT или UPDATE в таблице «repl_nodes» нарушает ограничение внешнего ключа ОШИБКА: INSERT или UPDATE в таблице «repl_nodes» нарушает ограничение внешнего ключа «repl_nodes_upstream_node_id_fkey»
DETAIL: Ключ (upstream_node_id)=(-1) отсутствует в таблице «repl_nodes».

Если у вас возникла данная ошибка при попытке ввести упавшую ноду обратно в кластер то необходимо сделать Процедуру switchover любой ноды в кластере(standby)

Standby станет мастером
На “Старом Мастере” ставшем standby

Устранение ошибки ОШИБКА: база данных «dbname» занята другими пользователями

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

Ошибка ВАЖНО: не удалось открыть каталог «/var/run/postgresql/9.6-main.pg_stat_tmp»:

Просто создаем каталог

Устранение ошибки при регистрации кластера no password supplied.

При регистрации кластера после того как мы слили с ноды данные бывает возникает ошибка
“no password supplied”
Не стали с ней долго разбираться, помогла перезагрузка, видимо какой-то сервис не смог нормально загрузиться.

Backup кластера

Скрипт бэкапа баз данных Postgres

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

Восстанавливаем из бэкапа

где ${DBNAMEPG} — имя базы данных для восстановления
${DBNAMEPGFILE} — файл дампа

Тестирование с pgbench

Заключение

Итак, что мы получили в итоге:

-кластер master-standby из четырех нод;
-автоматический failover в случае отказа мастера(с помощью repmgr’a);
-балансировку нагрузки(на чтение) через haproxy и pgbouncer(менеджер сеансов);
-отсутствие единой точки отказа — keepalived переносит ip адрес на другую ноду, которая была автоматически “повышена” до мастера в случае отказа;
— процедура восстановления(возвращение отказавшего сервера в кластер) не является трудоемкой — если разобраться);
— гибкость системы — repmgr позволяет настроить и другие события в случае наступления инцидента с помощью bash скриптов;
— возможность настроить систему “под себя”.
Для начинающего специалиста настройка данной схемы может показаться немного сложной , на практике же, один раз стоит со всем хорошо разобраться и вы сможете создать HA системы на базе Postgresql и сами управлять сценариями реализации механизма Failover.

Всё файлы по данной статье, я представил на своем аккаунте в github. Пользуйтесь с удовольствием))

Об авторе

human administrator

    3 комментария

    АлександрДата:6:49 пп - Янв 24, 2017

    А почему Вы отказались от PGPool’а, если не секрет?

    humanДата:7:21 пп - Янв 26, 2017

    Я много читал о том, что выбрать, в итоге пробывал и то и то, по тестам выйграл pgbouncer и он проще в настройке. Вроде как-то так.

    amwДата:10:53 дп - Фев 10, 2017

    А почему не drdb, pacemaker,corosync?

    Оставить ответ

    Войти с помощью: 

     

    Яндекс.Метрика