Настройка репликации PostgreSQL в Docker

Thank you for reading this post, don't forget to subscribe!

БАЗА В КОНТЕЙНЕРА ЭТО ЗЛО

рас­смот­рим про­цесс под­ня­тия двух кон­тей­не­ров с PostgreSQL и настрой­ки репли­ка­ции дан­ных меж­ду ними. Исполь­зо­вать будем систе­му на базе Linux, одна­ко, сам про­цесс настрой­ки Docker и репли­ка­ции не зави­сит от опе­ра­ци­он­ной системы.

Запуск контейнеров с СУБД

Как гово­ри­лось выше, мы будем под­ни­мать наши кон­тей­не­ры с помо­щью docker-compose.

Созда­дим ката­лог, в кото­ром будем работать:

mkdir -p /opt/docker/postgresql

Пере­хо­дим в него:

cd /opt/docker/postgresql

Созда­ем файл для docker-compose:

vi docker-compose.yml

* рас­смот­рим неко­то­рый опции подробнее:

  • postgresql_01/postgresql_02 — назва­ния для сер­ви­сов, кон­тей­не­ры для кото­рых мы будем поднимать.
  • image — образ, из кото­ро­го будут созда­вать­ся кон­тей­не­ры. В дан­ном при­ме­ре мы берем офи­ци­аль­ный образ postgres.
  • container_name — имя, кото­рое будет при­сво­е­но кон­тей­не­ру после его запус­ка. В нашем при­ме­ре это postgresql_01 и postgresql_02.
  • restart — режим пере­за­пус­ка. Гово­рит, в каких слу­ча­ях наш кон­тей­нер дол­жен стартовать.
  • volumes — хоро­шим тоном для рабо­ты базы дан­ных в кон­тей­не­ре явля­ет­ся про­брос ката­ло­га хосто­во­го ком­пью­те­ра внутрь кон­тей­не­ра. Таким обра­зом, после уда­ле­ния кон­тей­не­ра дан­ные оста­нут­ся на ком­пью­те­ре. В нашем при­ме­ре в ката­ло­ге /data будут созда­ны ката­ло­ги postgresql_01 и postgresql_02, кото­рые будут про­ки­ну­ты в ката­лог /var/lib/postgresql/data контейнера.
  • environment — для пер­во­го запус­ка необ­хо­ди­ма ини­ци­а­ли­за­ция базы дан­ных. Без паро­ля систе­мы выда­ет ошиб­ку. Поэто­му мы зада­ем пере­мен­ную сре­ды POSTGRES_PASSWORD.

Запус­ка­ем наши контейнеры:

docker-compose up -d

Мы долж­ны увидеть:

Creating postgresql_02 … done
Creating postgresql_01 … done

А если выве­сти спи­сок контейнеров:

docker ps

… мы долж­ны уви­деть наши два.

Теперь мож­но пере­хо­дить к настрой­ке репликации.

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

Усло­вим­ся, что пер­вич­ный сер­вер или master будет в кон­тей­не­ре с назва­ни­ем postgresql_01. Вто­рич­ный — postgresql_02. Мы будем настра­и­вать пото­ко­вую (streaming) асин­хрон­ную репликацию.

Настройка на мастере

Под­клю­ча­ем­ся к кон­тей­не­ру docker:

docker exec -it postgresql_01 bash

Захо­дим под поль­зо­ва­те­лем postgres:

su - postgres

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

createuser --replication -P repluser

* в дан­ном при­ме­ре будет созда­вать­ся учет­ная запись repluser с пра­ва­ми репликации.

Систе­ма потре­бу­ет вво­да паро­ля. При­ду­мы­ва­ем его и наби­ра­ем дважды.

Выхо­дим из-под поль­зо­ва­те­ля postgres:

exit

Выхо­дим из контейнера:

exit

Откры­ва­ем кон­фи­гу­ра­ци­он­ный файл postgresql.conf:

vi /data/postgresql_01/postgresql.conf

При­во­дим к сле­ду­ю­щи­ем виду неко­то­рые параметры:

* где

  • wal_level ука­зы­ва­ет, сколь­ко инфор­ма­ции запи­сы­ва­ет­ся в WAL (жур­нал опе­ра­ций, кото­рый исполь­зу­ет­ся для репли­ка­ции). Зна­че­ние replica ука­зы­ва­ет на необ­хо­ди­мость запи­сы­вать толь­ко дан­ные для под­держ­ки архи­ви­ро­ва­ния WAL и репликации.
  • max_wal_senders — коли­че­ство пла­ни­ру­е­мых слейвов; 
  • max_replication_slots — мак­си­маль­ное чис­ло сло­тов репли­ка­ции (дан­ный пара­метр не нужен для postgresql 9.2 — с ним сер­вер не запустится); 
  • hot_standby — опре­де­ля­ет, мож­но или нет под­клю­чать­ся к postgresql для выпол­не­ния запро­сов в про­цес­се восстановления; 
  • hot_standby_feedback — опре­де­ля­ет, будет или нет сер­вер slave сооб­щать масте­ру о запро­сах, кото­рые он выполняет.

Посмот­рим под­сеть, кото­рая исполь­зу­ет­ся для кон­тей­не­ров с postgresql:

docker network inspect postgresql_default | grep Subnet

В моем слу­чае, ответ был:

"Subnet": "172.19.0.0/16",

Теперь откры­ва­ем файл:

vi /data/postgresql_01/pg_hba.conf

И добав­ля­ем стро­ку после осталь­ных «host    replication»:

host    replication     all             172.19.0.0/16           md5

* в дан­ном при­ме­ре мы раз­ре­ши­ли под­клю­че­ние поль­зо­ва­те­лю replication из под­се­ти 172.19.0.0/16 с про­вер­кой под­лин­но­сти по паролю.

Пере­за­пу­стим докер контейнер:

docker restart postgresql_01

Настройка на слейве

Выпол­ним настрой­ку вто­рич­но­го сер­ве­ра. Для нача­ла, уда­лим содер­жи­мое рабо­че­го ката­ло­га вто­рич­ной базы:

rm -r /data/postgresql_02/*

* в дан­ном при­ме­ре мы уда­лим все содер­жи­мое ката­ло­га /data/postgresql_02.

Мы долж­ны быть уве­ре­ны, что в базе нет ниче­го важ­но­го. Толь­ко после это­го сто­ить уда­лять данные.

Захо­дим внутрь кон­тей­не­ра postgresql_02:

docker exec -it postgresql_02 bash

Выпол­ня­ем команду:

su - postgres -c "pg_basebackup --host=postgresql_01 --username=repluser --pgdata=/var/lib/postgresql/data --wal-method=stream --write-recovery-conf"

* где postgresql_01 — наш мастер; /var/lib/postgresql/data — путь до ката­ло­га с дан­ны­ми слейва.

Систе­ма долж­на запро­сить пароль для поль­зо­ва­те­ля repluser — вво­дим его. Нач­нет­ся про­цесс репли­ка­ции, про­дол­жи­тель­ность кото­ро­го зави­сит от объ­е­ма данных.

Проверка

Смот­рим ста­тус рабо­ты мастера:

docker exec -it postgresql_01 su - postgres -c "psql -c 'select * from pg_stat_replication;'"

Смот­рим ста­тус рабо­ты слейва:

docker exec -it postgresql_02 su - postgres -c "psql -c 'select * from pg_stat_wal_receiver;'"