PostgreSQL 10 — Потоковая репликация с отработкой фейловера. Данная запись посвящается исключительно «Потоковой репликации», не архивированию, не логической репликации, не восстановлению из бэкапа. Тут описывается потоковая репликация, настройка одного мастера, одного слейва и переключение между ними. Репликация — не бэкап.
Репликация PostgreSQL 10 — это когда вы превращаете слейв в текущий мастер и продолжаете радаснаработать с минимально возможным оставанием текущего мастера от старого мастера на момент выхода из строя и минимальным временем простоя.
Даже если вы просто не знаете что произошло с мастером но уверены что в ближайшие секунды он не заработает — вы можете превратить слейв в мастер для восстановления работы. А уже потом вы будете разбираться с тем что случилось с прошлым мастером. Главное не допустить существования в вашей сети двух рассинхронизированных мастеров. Тогда вас тоже повесят 🙂
Не смотрите на то что запись получилось достаточно объемной. Она приняла такие масштабы исключительно по причине желания сделать её более понятной и рассмотреть все ситуации работы данной схемы. Сам процесс — это пара десятков команд на обоих серверах и пара минут времени.
sudo su postgres #В этот момент мы авторизовываемся под пользователем postgres
psql
postgres=# CREATE USER replica REPLICATION LOGIN CONNECTION LIMIT 2 ENCRYPTED PASSWORD '4UtKbw';
\q
У данного пользователя в postgresql будет пароль 4UtKbw и лимит в 2 одновременных подключения. Помним что если в pg_hba.conf у нас настроено следующим образом:
# Database administrative login by Unix domain socket
local all postgres md5
То при вводе команды
psql
cp /etc/postgresql/10/main/pg_hba.conf /etc/postgresql/10/main/pg_hba.bkp
nano /etc/postgresql/10/main/pg_hba.conf
Приводим раздел репликации к такому виду:
#Настройки pg_hba.conf для ag-psql10-s1
# Allow replication connections from localhost, by a user with the
# replication privilege.
#local replication all peer
#host replication all 127.0.0.1/32 md5
#host replication all ::1/128 md5
host replication replica 192.168.1.232/32 md5
Мы указываем что репликация разрешена пользователю с именем replica, подключающемуся с адреса 192.168.1.232 с авторизацией по паролю
Сохраняем внесенные изменения командой Ctrl+O, закрываем nano командой Ctrl+X
cp /etc/postgresql/10/main/postgresql.conf /etc/postgresql/10/main/postgresql.bkp
nano /etc/postgresql/10/main/postgresql.conf
Для того чтобы быстро находить нужные нам параметры, можно использовать поиск, активируемый комбинацией Ctrl+W
listen_addresses = '*'
hot_standby = on
wal_level = replica
max_wal_senders = 10
wal_keep_segments = 32
Приводим параметры к указанному выше виду.
Немного комментариев:
listen_addresses
hot_standby
wal_level
max_wal_senders
wal_keep_segments
service postgresql restart
#система попросит ввести пароль вашей админской учеткиexit
sudo su postgres
service postgresql stop #система попросит ввести пароль вашей админской учетки
rm -R /var/lib/postgresql/10/main/
Для того чтобы инициализировать репликацию, необходимо скачать с сервера свежую копию данных. Иначе если разрыв данных будет слишком велик (больше чем доступно данных согласно wal_keep_segments), репликация попросту не запустится.
pg_basebackup -P -R -X stream -c fast -h 192.168.1.231 -U replica -D /var/lib/postgresql/10/main/
service postgresql start #система попросит ввести пароль вашей админской учетки
Система запросит пароль от пользователя replica. Когда мы изначально создавали этого пользователя на мастере, мы назначили ему пароль 4UtKbw.
Дожидаемся окончания загрузки.
После использования команды pg_basebackup на слейве автоматом был создан файл /var/lib/postgresql/10/main/recovery.conf с настройками репликации
nano /var/lib/postgresql/10/main/recovery.conf
standby_mode = 'on'
primary_conninfo = 'user=replica password=4UtKbw host=192.168.1.231 port=5432 sslmode=prefer sslcompression=1 krbsrvname=postgres target_session_attrs=any'
trigger_file = '/tmp/to_master'
standby_mode = ‘on’
— значит что сервер является резервным и после скачивания последнего WAL файла продолжит пытаться скачивать их используя данные из primary_conninfoprimary_conninfo
— строка подключения слейва к мастеруtrigger_file
— путь к файлу, наличие которого, в случае работы сервера в режиме репликации тут же заставит его превратиться в мастер и выйти из режима READONLY.nano /etc/postgresql/10/main/pg_hba.conf
host replication replica 192.168.1.231/32 md5
На слейве в pg_hba.conf мы указываем IP адрес ag-psql10-s1, чтобы когда он станет слейвом он смог инициализировать подключение пользователя replica
sudo su postgres
#Если вдруг мы авторизованы под другим пользователемpsql
#Запускаем psql, вводим пароль если авторизация стоит md5
sudo su postgres
#Если вдруг мы авторизованы под другим пользователемpsql #Запускаем psql, вводим пароль если авторизация стоит md5
postgres
=# \l
Список баз данных
Имя | Владелец | Кодировка | LC_COLLATE | LC_CTYPE | Права доступа
-----------------+----------+-----------+-------------+-------------+-----------------------
postgres | postgres | UTF8 | ru_RU.UTF-8 | ru_RU.UTF-8 |
replica_test_ok | postgres | UTF8 | ru_RU.UTF-8 | ru_RU.UTF-8 |
template0 | postgres | UTF8 | ru_RU.UTF-8 | ru_RU.UTF-8 | =c/postgres +
| | | | | postgres=CTc/postgres
template1 | postgres | UTF8 | ru_RU.UTF-8 | ru_RU.UTF-8 | =c/postgres +
| | | | | postgres=CTc/postgres
(4 строки)
Всё ок, можно создать или удалить еще какую-нибудь базу или таблицу на мастере и данные тут же приедут на реплику (к слову о том что будет если вы убьете в продакшене базу на мастере не имея её бекапа)
Итак, мы настроили репликацию. Наш мастер: ag-psql10-s1, наш слейв: ag-psql10-s2. Теперь мы отработаем фейловер в процессе которого ag-psql10-s1 умрёт и роль мастера уедет на ag-psql10-s2.
sudo su postgres
psql
CREATE DATABASE failover_s1_to_s2_test_ok;
\q
exit
sudo service postgresql stop
sudo shutdown -h now
sudo su postgres
psql
postgres=# \l
Список баз данных
Имя | Владелец | Кодировка | LC_COLLATE | LC_CTYPE | Права доступа
---------------------------+----------+-----------+-------------+-------------+-----------------------
failover_s1_to_s2_test_ok | postgres | UTF8 | ru_RU.UTF-8 | ru_RU.UTF-8 |
postgres | postgres | UTF8 | ru_RU.UTF-8 | ru_RU.UTF-8 |
replica_test_ok | postgres | UTF8 | ru_RU.UTF-8 | ru_RU.UTF-8 |
template0 | postgres | UTF8 | ru_RU.UTF-8 | ru_RU.UTF-8 | =c/postgres +
| | | | | postgres=CTc/postgres
template1 | postgres | UTF8 | ru_RU.UTF-8 | ru_RU.UTF-8 | =c/postgres +
| | | | | postgres=CTc/postgres
На нем должна быть созданная нами на мастере база failover_s1_to_s2_test_ok
Пытаемся создать в нем базу данных
postgres=# CREATE DATABASE test;
ОШИБКА: в транзакции в режиме "только чтение" нельзя выполнить CREATE DATABASE
\q #выходим из psql
Видим отказ, т.к. слейв еще не знает что мастер умер
Помним что в recovery.conf триггер файлом мы указали файл «/tmp/to_master»
Создаем этот файл
touch /tmp/to_master
Пытаемся снова создать базу
postgres=# CREATE DATABASE failover_s1_to_s2_complete;
CREATE DATABASE
Видим что база успешно создана. Мастер умер! Даздравствует новый Мастер! В этот момент клиенты уже могут набигать на новый мастер
После того как мы перенесли роль мастера на ag-psql10-s2, наш почивший мастер ag-psql10-s1 не в курсе последних событий, и как только он стартанет — он начнет активно принимать подключения и писать в себя данные. Ну а клиентам плевать куда писать, им куда дадут они туда и пишут. Поэтому если часть клиентов уже пишет на s2, а часть например еще не в курсе что в сети новый хозяин, в случае пробуждения пребывающего в таком же неведнии s1, мы рискуем получить в сети 2 мастера. Этим и хорош способ со сменой адреса DNS имени, что клиент сам не подозревая переключится на новый мастер. В любом случае сразу же после включения нам надо вырубить постгрес на старом мастере
Это та же команда что и ранее только IP изменен на новый. На ag-psql10-s2 сейчас полная копия данных с ag-psql10-s1 до его выхода из строя. Включая пользователей и пароли.
sudo su postgres
rm -R /var/lib/postgresql/10/main/
pg_basebackup -P -R -X stream -c fast -h 192.168.1.232 -U replica -D /var/lib/postgresql/10/main/
На новом мастере при отработке фейловера файл recovery.conf переименовался в recovery.done, он так же будет закачан, его нужно удалить
rm /var/lib/postgresql/10/main/recovery.done
При синхронизации pg_basebackup снова создала нам recovery.conf с актуальными параметрами подключения. Прописываем туда trigger_file
nano /var/lib/postgresql/10/main/recovery.conf
standby_mode = 'on'
primary_conninfo = 'user=replica password=4UtKbw host=192.168.1.231 port=5432 sslmode=prefer sslcompression=1 krbsrvname=postgres target_session_attrs=any'
trigger_file = '/tmp/to_master'
service postgresql start
psql
postgres=# create database qwe;
ОШИБКА: в транзакции в режиме "только чтение" нельзя выполнить CREATE DATABASE
postgres=# CREATE DATABASE master_to_slave_config_ok;
CREATE DATABASE
postgres-# \l
Список баз данных
Имя | Владелец | Кодировка | LC_COLLATE | LC_CTYPE | Права доступа
----------------------------+----------+-----------+-------------+-------------+-----------------------
failover_s1_to_s2_complete | postgres | UTF8 | ru_RU.UTF-8 | ru_RU.UTF-8 |
failover_s1_to_s2_test_ok | postgres | UTF8 | ru_RU.UTF-8 | ru_RU.UTF-8 |
master_to_slave_config_ok | postgres | UTF8 | ru_RU.UTF-8 | ru_RU.UTF-8 |
postgres | postgres | UTF8 | ru_RU.UTF-8 | ru_RU.UTF-8 |
replica_test_ok | postgres | UTF8 | ru_RU.UTF-8 | ru_RU.UTF-8 |
template0 | postgres | UTF8 | ru_RU.UTF-8 | ru_RU.UTF-8 | =c/postgres +
| | | | | postgres=CTc/postgres
template1 | postgres | UTF8 | ru_RU.UTF-8 | ru_RU.UTF-8 | =c/postgres +
| | | | | postgres=CTc/postgres
(7 строк)
База приехала! Yaaaay!
Собсно действия абсолютно такие же как в случае ag-psql10-s1 => ag-psql10-s2.
touch /tmp/to_master
sudo service postgresql stop
sudo su postgres
rm -R /var/lib/postgresql/10/main/
pg_basebackup -P -R -X stream -c fast -h 192.168.1.231 -U replica -D /var/lib/postgresql/10/main/
Внимательно проверяем что указан IP адрес текущего мастера, теперь это 192.168.1.231 (ag-psql10-s1)
rm /var/lib/postgresql/10/main/recovery.done
nano /var/lib/postgresql/10/main/recovery.conf
standby_mode = 'on'
primary_conninfo = 'user=replica password=4UtKbw host=192.168.1.231 port=5432 sslmode=prefer sslcompression=1 krbsrvname=postgres target_session_attrs=any'
trigger_file = '/tmp/to_master'
service postgresql start
Собственно вот и все дела. Если есть какие-то вопросы — не стесняйтесь задавать их в комментариях.
P.S. Лучше обкатать 2 фейловера, с мастера на слейв с полной передачей ролей и обратно. Делается это за тем, чтобы проверить все конфиги в контролируемой среде. До того, как что-то реально сломается.
When you subscribe to the blog, we will send you an e-mail when there are new updates on the site so you wouldn't miss them.
Просто делюсь интересными на мой взгляд событиями и статьями.