Часть 1. Введение.
Часть 2. Репликация. Repmgr.
Часть 3. Auto-failover. Демоны repmgr.
Часть 4. Высокая доступность. Бэкапирование. Демоны repmgr. Barman.
Часть 5. Тестирование. Ansible. Вместо послесловия.
Ручное переключение серверов
На сервере backup запустите.
su - postgres repmgr standby switchover -f /etc/repmgrd_db2.conf --log-to-file
Автоматическое переключение серверов
db2 теперь новый мастер. Погасите db2.
shutdown -h now
Подождите пока db1 не станет новым мастером. Запускайте на сервере backup:
tail -50 /var/log/syslog | grep repmgr
repmgrd[6872]: unable to ping "host=10.8.2.1 user=repmgr dbname=repmgr connect_timeout=2" repmgrd[6872]: unable to connect to upstream node "db2" (node ID: 2) repmgrd[6872]: checking state of node 2, 1 of 6 attempts repmgrd[6872]: unable to ping "user=repmgr connect_timeout=2 dbname=repmgr host=10.8.2.1 fallback_application_name=repmgr" repmgrd[6872]: sleeping 10 seconds until next reconnection attempt repmgrd[6872]: checking state of node 2, 2 of 6 attempts repmgrd[6872]: unable to ping "user=repmgr connect_timeout=2 dbname=repmgr host=10.8.2.1 fallback_application_name=repmgr" repmgrd[6872]: sleeping 10 seconds until next reconnection attempt repmgrd[6872]: checking state of node 2, 3 of 6 attempts repmgrd[6872]: unable to ping "user=repmgr connect_timeout=2 dbname=repmgr host=10.8.2.1 fallback_application_name=repmgr" repmgrd[6872]: sleeping 10 seconds until next reconnection attempt repmgrd[6872]: checking state of node 2, 4 of 6 attempts repmgrd[6872]: unable to ping "user=repmgr connect_timeout=2 dbname=repmgr host=10.8.2.1 fallback_application_name=repmgr" repmgrd[6872]: sleeping 10 seconds until next reconnection attempt repmgrd[6872]: checking state of node 2, 5 of 6 attempts repmgrd[6872]: unable to ping "user=repmgr connect_timeout=2 dbname=repmgr host=10.8.2.1 fallback_application_name=repmgr" repmgrd[6872]: sleeping 10 seconds until next reconnection attempt repmgrd[6872]: checking state of node 2, 6 of 6 attempts repmgrd[6872]: unable to ping "user=repmgr connect_timeout=2 dbname=repmgr host=10.8.2.1 fallback_application_name=repmgr" repmgrd[6872]: unable to reconnect to node 2 after 6 attempts repmgrd[6872]: primary and this node have the same location ("default") repmgrd[6872]: no other sibling nodes - we win by default repmgrd[6872]: this node is the only available candidate and will now promote itself repmgrd[6872]: promote_command is:#012 "ssh postgres@10.8.1.1 /usr/bin/repmgr standby promote -f /etc/repmgr.conf --log-to-file" repmgrd[6872]: executing notification command for event "repmgrd_failover_promote" repmgrd[6872]: 0 followers to notify repmgrd[6872]: switching to primary monitoring mode repmgrd[6872]: executing notification command for event "repmgrd_reload" repmgrd[6872]: monitoring cluster primary "db1" (node ID: 1)
Проверьте кластер.
su - postgres repmgr -f /etc/repmgrd_db1.conf cluster show
Возврат экс-мастера назад в кластер
db1 снова мастер. Вернем db2 назад в кластер.
Для начала, запустите db2.
Затем, запустите OpenVPN.
systemctl start openvpn
Потом, запустите rejoin на сервере db2.
su - postgres repmgr -f /etc/repmgr.conf node rejoin -d "postgres://repmgr@10.8.1.1:5432/repmgr" --force-rewind
Repmgr будет использовать pg_rewind, так что возврат сервера в строй должен быть быстрее, чем при полном бэкапировании.
ВАЖНО. Убедитесь, что демоны repmgr переподключились к свежевозвращенному серверу каждый раз когда хотите опять деградировать кластер.
tail -50 /var/log/syslog | grep repmgr
repmgrd[10061]: monitoring primary node "db2" (node ID: 2) in normal state repmgrd[10061]: attempting to reconnect to node "db2" (ID: 2) repmgrd[10061]: reconnected to node "db2" (ID: 2) repmgrd[10061]: node is now a standby, switching to standby monitoring repmgrd[10061]: executing notification command for event "repmgrd_standby_reconnect"
Возврат поврежденного экс-мастера назад в кластер
ОК, давайте представим, что файлы базы данных на сервере db2 повреждены, но ОС продолжает работать. Процесс восстановления в таком случае очень похож на процесс создания резервного сервера.
Запустите OpenVPN.
systemctl start openvpn
Запустите клонирование и перерегистрацию резервного сервера.
su - postgres rm -r /var/lib/postgresql/11/main/* #not remove, but move if you need to repmgr -h 10.8.1.1 -U repmgr -d repmgr -f /etc/repmgr.conf standby clone -F chmod 700 /var/lib/postgresql/11/main/ sudo pg_ctlcluster 11 main start repmgr standby register --force
Если repmgr сконфигурирован на использование barman, файлы бэкапа будут взяты с сервера barman и процесс восстановления не потревожит мастер-сервер.
Проверяем бэкап
Сымитируйте нагрузку на БД. Зайдите в базу как repmgr на сервере backup.
su - postgres psql -U repmgr -d repmgr -h 10.8.3.1 -p 54322
Создайте тестовую таблицу и запустите тестовый скрипт.
create table t(n integer); DO $ begin for i in 1..100000 loop insert into t values(i); RAISE NOTICE 'Val: %',i; commit; end loop; end; $;
Сразу после этого, жестко перезагрузите сервер db1.
Подождите пока сервер db2 не станет мастером, как было показано выше.
Зайдите на новый мастер(db2) и вставьте еще строчку данных.
psql -U repmgr -d repmgr -h 10.8.3.1 -p 54322 insert into t values (0);
Остановите тестовый экземпляр БД на сервере backup перед разворачиванием бэкапа.
systemctl stop postgresql
Подготовьте директорию PostgreSQL для barman.
rm -r /var/lib/postgresql/11/main/* chown barman:barman /var/lib/postgresql/11/main/
Восстановите последний возможный бэкап. Barman пока что не поддерживает ключевое слово latest в качестве target-time, поэтому просто укажите дату где-нибудь в будущем, мы переопределим её вскоре.
barman recover main_backup --target-time="2030-01-01 00:00:00" latest /var/lib/postgresql/11/main/
Скопируйте последний имеющийся partial WAL и переименуйте его.
cp /var/lib/barman/main_backup/streaming/*.partial /var/lib/postgresql/11/main/pg_wal/ rename 's/.partial//' /var/lib/postgresql/11/main/pg_wal/*
Переопределите точку восстановления, автоматически заданную barman.
echo "recovery_target_timeline = 'latest'" >> /var/lib/postgresql/11/main/recovery.conf
Верните права назад юзеру postgres и запустите экземпляр.
chown -R postgres:postgres /var/lib/postgresql/11/main/ systemctl start postgresql
Успешный старт базы командой не означает, что она уже восстановлена на последнюю точку. Проверяйте логи, пока база не будет готова принимать rw-соединения.
tail -50 /var/log/postgresql/postgresql-11-main.log
... [31625] LOG: restored log file "0000000D000000000000002B" from archive [31625] LOG: restored log file "0000000E000000000000002C" from archive ... [31624] LOG: database system is ready to accept connections
Зайдите в psql и проверьте что все строки на месте.
su - postgres psql -U repmgr -d repmgr -h 127.0.0.1 select count(*) from t;
I want to ride my Ansible! Ansible!
Вместо послесловия
Так, и что мне дальше делать?
- Установите HAproxy, чтобы иметь отдельный порт для ro-соединений. Перенаправьте ro-запросы к резервному серверу с автопереключением на мастер, если резервный недоступен. Вы можете использовать external check script и селект к repmgr через порт 54322 чтобы определить роль сервера.
- Запустите pgbouncer через порт 54322
- Подумайте дважды о безопасности сервера backup. Это наиболее уязвимый сервер кластера, потому что на нем располагаются все бэкапы и он может подключаться к серверам БД без пароля по ssh.
- Подумайте дважды о безопасности серверов db1 и db2. Если вы используете barman как метод восстановления в repmgr, серверы БД могут подключаться к backup без пароля по ssh.
- Установите систему мониторинга, которая будет мониторить демонов repmgr, barman и состояние кластера после автоматического переключения.
- Поблагодарите меня. Это было нелегко.
Большое спасибо за отличную статью!
Подскажите пожалуйста, когда выполняю ручное переключение мастера с db1 на db2, db2 становится новым мастером, но db1 не становится слейвом.
На db1 не может стартовать кластер main.
В логах db1 вижу информацию, что идет восстановление файлов журнала, к примеру последний 00000006.history восстановлен успешно, а следующий 00000007.history (которого еще нет на самом backup сервер) очевидно не восстанавливается.
Ошибка в логах:
ERROR: WAL file ‘00000007.history’ not found in server ‘main_backup’ (SSH host: 192.168.6.188)
ERROR: Remote ‘barman get-wal’ command has failed!
Если отключить восстановление из бэкапа barman, а тянуть состояние с нового мастера то ошибок нет…
Здравствуйте!
Возможно, проблема в конфигурации и ни одно из звеньев репликации данных не было синхронным. Если это не так, могу написать вам на почту для дальнейшего исследования проблемы.
В целом, очень хорошо написано! У меня получилось завести на тестовом стенде.
Отлично! Спасибо.
а как вы мониторите постгресс если не секрет?
Я использую обычно postgres_exporter для прометея, вот этот
https://github.com/wrouesnel/postgres_exporter, однако ему требуется shared_preload_libraries = ‘pg_stat_statements’, но
в случае с repmgr shared_preload_libraries = ‘repmgr’ и он не работает.
Парметр shared_preload_libraries умеет принимать несколько либ через запятую.
Добрый день.
repmgr standby switchover -f /etc/repmgrd_db2.conf —log-to-file
Чет в это пункте он мне ругается.
ERROR: ownership error for file «/var/lib/postgresql/11/main/recovery.conf»
DETAIL: file owner is «root», data directory owner is «postgres»
где я что мог упустит везде с правами норм тем боле на recovery.conf во всех нодах postgres стоит. А на самих нодах переключение выполняется на ура. в чем мож быть проблема?
И всё же попрошу вывод
ls -l /var/lib/postgresql/11/main/recovery.conf
, чтобы было понятно наверняка 🙂postgres@pgdbslave:~/11/main$ ls -la /var/lib/postgresql/11/main/recovery.conf
-rw——- 1 postgres postgres 147 Aug 12 11:17 /var/lib/postgresql/11/main/recovery.conf
Интересно.
А если вручную зайти под пользователем postgres и попробовать открыть файл, то всё в порядке и он открывается, верно?
Если да, то какого-то решения в голову больше не приходит.
Да все открывается без проблем под пользователем postgres.
Hi.
Thank you for your excellent work and documentation.
I just want to clarify one thing that i tried to get from this howto and i could not.
You said that this can work without any HAproxy setup on the client side because, if i understood correctly, all the queries are routed through the backup server to the correct dbX server.
But.. what happen if the backup server dies?
You understand it right. Backup server is the main entry point for such cluster configuration. So, if it dies, all you can do is to manually reconfigure app to use primary postgres instance. The question is it acceptable to do so if you have no backups.
Добрый день!
Поясните роль open-vpn в этой схеме. Можно
ли обойтись без него?
Здравствуйте.
Использование OpenVPN опционально и отсылает к первой статье цикла.
В тестах оно носит роль восстановления сетевой связности, т.к. тестирование было на несвязанных локальной сетью машинах.
Если у вас машины в одной сети, то инструкции для OpenVPN можно (скорее всего) проигнорировать.