Настройка потоковой репликации с replication slots в postgresql 9.6 в docker контейнерах через docker-compose
Исходные данные – виртуалки для docker c ip
10.10.1.1 - master 10.10.1.1 - slave1 10.10.1.1 - slave2
На них есть docker-ce и docker-compose
Настройка master сервера postgresql
Создадим директории для нашего добра на мастере
mkdir /database cd /database mkdir data mkdir backup
Создаем файл docker-compose.yml
nano docker-compose.yml
Вставляем в него
version: '3.3' services: dbpostgres.itc-life.ru: image: postgres:9.6 #build: build/www.etagi.dev.pg/ container_name: dbpostgres.itc-life.ru hostname: dbpostgres.itc-life.ru restart: always volumes: - ./data/:/var/lib/postgresql/data/ - ./backup:/var/backup_db ports: - "5432:5432" privileged: true environment: - POSTGRES_USER: postgres - POSTGRES_PASSWORD: Пароль_постгрес networks: - db-network environment: - "TZ=Asia/Yekaterinburg" ###Сети докера - создаются автоматом networks: db-network: driver: bridge
Поднимаем контейнер
docker-compose up -d
Заходим в контейнер на мастере
docker exec -ti -u 0 dbpostgres.itc-life.ru bash
Создаем пользователя для репликации
create user replica with replication encrypted password 'Пароль_репликации';
Правим конфиг на мастере
nano /var/lib/postgresql/data/postgresql.conf
Добавим в конец
listen_addresses = '*' # comma-separated list of addresses; # defaults to 'localhost'; use '*' for all # (change requires restart) port = 5432 # (change requires restart) max_connections = 3000 # (change requires restart) ##Настройка репликации # — необходимый формат WAL-логов для репликации hot_standby = on wal_level = 'hot_standby' wal_log_hints = on #— количество одновременных соединений для репликации max_wal_senders = 3 #— логи складываем в pg_log logging_collector = on max_replication_slots = 3 shared_buffers = 25048MB #25% from ram effective_cache_size = 25000MB #50% from ram maintenance_work_mem = 2280MB fsync = on #this parameter is on, the PostgreSQL server will try to make sure that updates are physically written to disk,fsync can only be set in the postgresql.conf file or on the server command line. If you turn this parameter off, also consider turning off full_page_writes. full_page_writes = on
Правим pg_hba.conf
nano /var/lib/postgresql/data/pg_hba.conf
Добавим в конец
#host all all all trust host all all 0.0.0.0/0 md5 host replication postgres 0.0.0.0/0 md5 host replication replica 0.0.0.0/0 md5
Создаем слоты репликации на мастере
su posgres -c "psql"
# SELECT pg_create_physical_replication_slot('standby_slot1'); # SELECT pg_create_physical_replication_slot('standby_slot2'); #\q
Релоадим конфиг на мастере в докере
su - postgres -c '/usr/lib/postgresql/9.6/bin/pg_ctl -D /var/lib/postgresql/data reload'
Настройка слейва №1
Создадим директории для нашего добра на слейве
mkdir /database cd /database mkdir data mkdir backup mkdir slave
Создаем файл docker-compose.yml
nano docker-compose.yml
Вставляем в него
version: '3.3' services: dbpostgres.itc-life.ru: image: postgres:9.6 #build: build/www.etagi.dev.pg/ container_name: dbpostgres.itc-life.ru hostname: dbpostgres.itc-life.ru restart: always volumes: - ./data/:/var/lib/postgresql/data/ #- ./slave/:/var/lib/postgresql/data/ - ./backup:/var/backup_db ports: - "5433:5432" privileged: true networks: - db-network environment: - "TZ=Asia/Yekaterinburg" adminer: image: adminer container_name: dbpostgres.adminer hostname: dbpostgres.adminer restart: always ports: - 48080:8080 networks: - db-network ###Сети докера - создаются автоматом networks: db-network: driver: bridge
Затем поднимаем контейнер
docker-compose up -d
Заходим в контейнер на слейве
docker exec -ti -u 0 dbpostgres.itc-life.ru bash
Снимаем данные с мастера
su - postgres -c 'rm -rf /var/lib/postgresql/data/slave/*' su - postgres -c ' chmod go-rwx /var/lib/postgresql/data/slave && /usr/lib/postgresql/9.6/bin/pg_basebackup -P -R -X stream -c fast -h 10.10.1.1 -v -U replica -D /var/lib/postgresql/data/slave'
Введем пароль от пользователя replica
Поправим файл
/var/lib/postgresql/data/slave/recovery.conf
Добавим в конец
primary_slot_name = 'standby_slot1' recovery_target_timeline = 'latest'
Выходим из docker конейнера
Делаем
docker-compose down
Правим файл docker-compose.yml
nano docker-compose.yml
Изменяем в нем закоментированную строку slave и data комментируем #
version: '3.3' services: dbpostgres.itc-life.ru: image: postgres:9.6 #build: build/www.etagi.dev.pg/ container_name: dbpostgres.itc-life.ru hostname: dbpostgres.itc-life.ru restart: always volumes: #- ./data/:/var/lib/postgresql/data/ - ./slave/:/var/lib/postgresql/data/ - ./backup:/var/backup_db ports: - "5433:5432" privileged: true networks: - db-network environment: - "TZ=Asia/Yekaterinburg" adminer: image: adminer container_name: dbpostgres.adminer hostname: dbpostgres.adminer restart: always ports: - 48080:8080 networks: - db-network ###Сети докера - создаются автоматом networks: db-network: driver: bridge
Затем поднимаем контейнер
docker-compose up -d
Проверяем статус репликации на мастере
su postgres -c "psql -qAt -c 'select client_addr, state, sent_location, write_location,flush_location, replay_location from pg_stat_replication;'"
Со вторым слейвом делаем тоже самое, только в recovery.conf
primary_slot_name = 'standby_slot2'
Промоутим реплику до мастера
В контейнере реплики например 10.10.1.2 делаем
su postgres -с '/usr/lib/postgresql/9.6/bin/promote -D /var/lib/postgresql/data/'
Переключение второй реплики на новый мастер – допустим им стал 10.10.1.2
su postgres -c '/usr/lib/postgresql/9.6/bin/pg_rewind -D /var/lib/postgresql/data/ --source-server="host=10.10.1.2 port=5432 user=replica password=Пароль_репликации"'
Какую смысловую нагрузку тут несё докер? Всё можно раскатывать ансиблем. Если бы был пример как скейлить, но это больше подходит для мультимастер репликации.
Докером можно быстро поднимать множество постгрес инстансов на вм. В общем – это удобно.
Как вариант для тестов можно
За СУБД в докере на продакшене – надо сжигать на костре ;-)