PostgreSQL

[PostgreSQL] PostgreSQL docker를 이용한 replication

bbugge 2021. 1. 22. 17:55

// docker를 이용한 PostgreSQL replication

// OS release : centos 7 (3.10.0-1127.el7.x86_64)

 

// docker 설치

[root@test]$ yum install docker -y

[root@test]$ systemctl enable docker

[root@test]$ systemctl start docker

 

// pgpool 설치 (failover 및 failback에 사용되는 패키지)

[root@test]$ yum install -y https://www.pgpool.net/yum/rpms/4.2/redhat/rhel-7-x86_64/pgpool-II-pg10-4.2.1-1pgdg.rhel7.x86_64.rpm

[root@test]$ yum install -y https://www.pgpool.net/yum/rpms/4.2/redhat/rhel-7-x86_64/pgpool-II-pg10-devel-4.2.1-1pgdg.rhel7.x86_64.rpm

[root@test]$ yum install -y https://www.pgpool.net/yum/rpms/4.2/redhat/rhel-7-x86_64/pgpool-II-pg10-debuginfo-4.2.1-1pgdg.rhel7.x86_64.rpm

[root@test]$ yum install -y https://www.pgpool.net/yum/rpms/4.2/redhat/rhel-7-x86_64/pgpool-II-pg10-extensions-4.2.1-1pgdg.rhel7.x86_64.rpm

 

// docker 디렉토리 확인 및 postgresql v.10 설치

[root@test]$ ls -l /var/lib/docker/

[root@test]$ docker pull postgres:10

 

// 설치된 docker 이미지 확인

[root@test]$ docker images

 

// docker 네트워크 생성 (각 노드의 ip를 static하게 주기위함)

[root@test]$ docker network create --subnet 172.18.0.0/16 mynet1

 

// docker 볼륨 생성 (각 노드의 저장소를 specific하게 지정하기 위함)

[root@test]$ docker volume create pgdata1

[root@test]$ docker volume create pgdata2

 

// postgresql docker container 생성

// 서로 다른 서버를 사용한다면 docker run 옵션에 --port를 추가하여 설정 (ex. 5432:5432/tcp)

[root@test]$ docker run -d -it --network mynet1 --ip 172.18.0.10 --name pg_node1 -e POSTGRES_PASSWORD=postgres -v pgdata1:/var/lib/postgresql/data postgres:10

[root@test]$ docker run -d -it --network mynet2 --ip 172.18.0.20 --name pg_node2 -e POSTGRES_PASSWORD=postgres -v pgdata1:/var/lib/postgresql/data postgres:10

 

// 생성된 postgresql docker container 확인

[root@test]$ docker ps

 

// pg_node1 이중화를 위한 서버 setting

[root@test]$ docker exec -it pg_node1 bash

#DOCKER> root@pg_node1 $ apt-get update

#DOCKER> root@pg_node1 $ apt-get install -y ssh rsync vim sudo net-tools iputils-ping procps

 

// postgres 계정 ssh 접속을 위해 비밀번호 설정

#DOCKER> root@pg_node1 $ passwd postgres

 

#DOCKER> root@pg_node1 $ su - postgres

 

// 테스트를 위해 데이터베이스와 테이블을 생성

#DOCKER> postgres@pg_node1 $ psql 

postgres=# create database mydb;

postgres=# \connect mydb

mydb=# create table repl_test (no int, name varchar(20));

mydb=# insert into repl_test values (1,'AAAA');

mydb=# commit;

 

// replication setting

mydb=# select proname from pg_proc where proname like 'pg_create_physical%';

mydb=# select * from pg_create_pg_create_physical_replication_slot('repl_slot_01');

mydb=# create role replication with replication password 'replication' login;

// wal 상태 확인

mydb=# SELECT name, setting FROM pg_settings 

mydb-# WHERE name IN ('archive_mode', 'archive_command', 'archive_timeout', 'wal_level', 'max_wal_senders');

      name              |               setting
-----------------------+--------------------------------------
 archive_command   |   cp %p /var/lib/postgresql/archive/%f
 archive_mode        |   on
 archive_timeout     |    0
 max_wal_senders   |    2
 wal_level              |   replica
(5 rows)  

 

mydb=# \q

 

// 설정이 안되어 있다면 /var/lib/postgresql/data 에 있는 postgresql.conf 를 변경하고 다시 docker restart

#DOCKER> postgres@pg_node1 $ vi postgresql.conf

wal_level = replica          -- 9.6 이전에는 archive
archive_mode = on
archive_command = 'cp %p /var/lib/postgresql/archive/%f' 
max_wal_senders = 2

 

#DOCKER> postgres@pg_node1 $ mkdir /var/lib/postresql/archive

 

// pg_hba.conf 설정 (docker로 설치 시, 하단에 모든 접근 가능하도록 설정이 되어있긴함.)

#DOCKER> postgres@pg_node1 $ vi pg_hba.conf

host    replication     replication    172.18.0.0/16     md5    -- 하단에 추가

 

#DOCKER> postgres@pg_node1 $ exit

#DOCKER> root@pg_node1 $ exit

[root@test]$ docker restart pg_node1

 

// pg_node2에 pg_basebackup을 이용해 데이터베이스 복제

[root@test]$ docker stop pg_node2

[root@test]$ cd /var/lib/docker/volumes/pgdata2/_data

[root@test]$ rm -rf ./*

[root@test]$ pg_basebackup -h 172.18.0.10 -p 5432 -D /var/lib/docker/volumes/pgdata2/_data -U replication -P -v -X stream

[root@test]$ chown -R polkitd:input .

[root@test]$ vi ./recovery.conf

standby_mode=on
primary_conninfo='host=172.18.0.10 port=5432 user=replication password=replication'
primary_slot_name='repl_slot_01'
trigger_file='/var/lib/postgresql/data/failover_trigger'


// pg_node2 server setting 및 replication 확인

[root@test]$ docker start pg_node2

[root@test]$ docker exec -it pg_node2 bash

#DOCKER> root@pg_node2 $ apt-get update
#DOCKER> root@pg_node2 $ apt-get install -y ssh rsync vim sudo net-tools iputils-ping procps

#DOCKER> root@pg_node2 $ su - postgres

#DOCKER> postgres@pg_node2 $ mkdir /var/lib/postgresql/archive

#DOCKER> postgres@pg_node2 $ psql

postgres=# select proname from pg_proc where proname like '%recovery%';

 

// 아래 명령어를 입력해서 결과 값이 t가 나온다면 pg_node2 는 standby로 동작 중임을 의미한다.

postgres=# select * from pg_is_in_recovery();

 

// 정확한 확인을 위해 pg_node1에서 쿼리 실행해본다.

postgres=# select * from pg_stat_replication;

postgres=# \connect mydb

postgres=# insert into repl_test values (2,'BBBB');

 

 

// pgpool을 위해 각 node에 ssh 서비스를 실행시켜준다.

#DOCKER> root@pg_node1 $ service ssh start

#DOCKER> root@pg_node2 $ service ssh start

 

// docker로 설치해서 linux가 debian으로 동작하는데 redhat만 쓰다보니 ssh runlevel을 변경해서 부팅 시 start 되며 올라오게 하고 싶지만, 잘 되지 않음.

// update-rc.d 및 sysv-rc-conf 를 사용하면 된다고 하지만, 시도 결과 되지 않았음.