이번시간에는 저번에 했었던 Postgresql DB 이중화 개념에 이어서 이번엔 직접 구현을 해볼 예정이다. Aws 환경이 아닌 로컬 환경에서 먼저 docker-compose를 사용해 구성해보려고 한다.
version: '3.7'
x-common-environment: &common_environment
POSTGRESQL_POSTGRES_PASSWORD: ${POSTGRESQL_POSTGRES_PASSWORD}
POSTGRES_USERNAME: ${POSTGRES_USERNAME}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DATABASE: ${POSTGRES_DATABASE}
REPMGR_PASSWORD: ${REPMGR_PASSWORD}
REPMGR_PRIMARY_HOST: ${REPMGR_PRIMARY_HOST}
REPMGR_PRIMARY_PORT: ${REPMGR_PRIMARY_PORT}
REPMGR_PORT_NUMBER: ${REPMGR_PORT_NUMBER}
services:
postgres-primary-0:
image: bitnami/postgresql-repmgr:15
container_name: postgres-primary-0
volumes:
- postgres_primary_data:/bitnami/postgresql
environment:
<<: *common_environment
REPMGR_PARTNER_NODES: postgres-primary-0,postgres-replica-1:5432,postgres-replica-2:5432
REPMGR_NODE_NAME: postgres-primary-0
REPMGR_NODE_NETWORK_NAME: postgres-primary-0
postgres-replica-1:
image: bitnami/postgresql-repmgr:15
container_name: postgres-replica-1
volumes:
- postgres_replica_1_data:/bitnami/postgresql
environment:
<<: *common_environment
REPMGR_PARTNER_NODES: postgres-primary-0,postgres-replica-1:5432,postgres-replica-2:5432
REPMGR_NODE_NAME: postgres-replica-1
REPMGR_NODE_NETWORK_NAME: postgres-replica-1
postgres-replica-2:
image: bitnami/postgresql-repmgr:15
container_name: postgres-replica-2
volumes:
- postgres_replica_2_data:/bitnami/postgresql
environment:
<<: *common_environment
REPMGR_PARTNER_NODES: postgres-primary-0,postgres-replica-1:5432,postgres-replica-2:5432
REPMGR_NODE_NAME: postgres-replica-2
REPMGR_NODE_NETWORK_NAME: postgres-replica-2
pgpool:
image: bitnami/pgpool:4
container_name: pgpool
ports:
- "${PGPOOL_PORT}:5432"
environment:
- PGPOOL_BACKEND_NODES=0:postgres-primary-0:${REPMGR_PRIMARY_PORT},1:postgres-replica-1:${REPMGR_PORT_NUMBER},2:postgres-replica-2:${REPMGR_PORT_NUMBER}
- PGPOOL_SR_CHECK_USER=${PGPOOL_SR_CHECK_USER}
- PGPOOL_SR_CHECK_PASSWORD=${PGPOOL_SR_CHECK_PASSWORD}
- PGPOOL_ENABLE_LDAP=no
- PGPOOL_POSTGRES_USERNAME=${POSTGRES_USERNAME}
- PGPOOL_POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- PGPOOL_ADMIN_USERNAME=${PGPOOL_ADMIN_USERNAME}
- PGPOOL_ADMIN_PASSWORD=${PGPOOL_ADMIN_PASSWORD}
healthcheck:
test: ["CMD", "/opt/bitnami/scripts/pgpool/healthcheck.sh"]
interval: 10s
timeout: 5s
retries: 5
위의 코드를 살펴보면 먼저 맨 앞단에 pgpool 미들웨어를 두고 그 뒤에 3개의 DB를 구성하였다. primary_db, standby_db1, standby_db2로 구성하였다.

bitnami/postgresql-repmgr 이미지를 사용하는게 이중화 구성하기에 좋았다. 설명도 잘되어있기도 하고... 본인은 처음에는 bitnami/postgresql를 사용해서 이전 개념에서 배웠던 대로 docker에서 하려고 하니까 상당히 많은 문제를 겪게 되었다.
- postgresql.conf 파일 설정
- pg_hba.conf 파일 설정
- 복제 사용자 생성
- 복제를 할 폴더 삭제
- 복제 준비하기 위한 primary_db 서비스 시작하기까지 대기
- 복제 서버 초기화 및 기본설정
- postgresql.conf 파일 설정
- standby.signal파일 생성(이는 standby임을 증명하는 파일임 내용 없어도 됨)
- pg_hba.conf파일 설정
- 데이터 디렉토리 권한 설정
- 위와 동일함
위와 같은 작업을 하게 되면서 공유 메모리에 대한 오류, 복제하는 과정에서 문제가 생겨 사용자 권한이 없는 경우, 서버를 시작하게 되면 postgresql.pid 파일이 생기는데 이 파일이 없어 서버 시작이 안되는 경우 등등 많은 문제를 겪게 되었다.
그래서 dockerhub에 공식문서를 찾아보던 중
https://hub.docker.com/r/bitnami/postgresql-repmgr
bitnami/postgresql-repmgr 이 이미지로 DB 이중화 구성을 하는 것을 보고 참고하여 구성하게 되었다.
그럼 정상적으로 잘 작동이 되는지 확인해 보자.

먼저 docker-compose up -d 명령을 사용해서 컨테이너들을 실행해보자

docker Desktop에 잘 실행되어있는 모습을 확인할 수 있었다.
그럼 이제 정상적으로 잘 복제가 되었는지 데이터를 primary에 넣고 standbydb에 넣은 데이터가 있는지 확인해보자.(참고로 본인은 window에서 진행하고 있다.)
docker exec -it -e PGPASSWORD=mypassword postgres-primary-0 psql -U myuser -d mydb -c "CREATE TABLE test (id SERIAL PRIMARY KEY, name VARCHAR(255));"
docker exec -it -e PGPASSWORD=mypassword postgres-primary-0 psql -U myuser -d mydb -c "INSERT INTO test (name) VALUES ('donghyeon'), ('kang');"

위처럼 아무런 데이터를 primary-0-db에 넣어보자.
2.Postgres-replica-1
docker exec -it -e PGPASSWORD=mypassword postgres-replica-1 psql -U myuser -d mydb -c "SELECT * FROM test;"

replica-1db에 데이터가 잘 있는 것을 확인할 수 있다. 그럼 replica에는 쓰기는 할 수 없다 한번 데이터를 넣어보면

위와 같이 쓰기는 안되는 모습을 확인할 수 있었다.
그럼 이제 이중화 구성을 끝났다. 하지만 여기서 끝나게 되면 안된다.
저번시간에 배웠던 것 처럼 db가 죽으면 어떻게 할 것인가? 다른 live인 db를 master db로 승격하는 과정을 거쳐야 더욱 안전한 db라고 말할 수 있다. 이를 이제 진행해보려고 한다.

먼저 postgres-primary-0을 종료해보자.
pgpool 로그

그런 다음 종료를 시키고 pgpool의 상태를 봐보자. 제대로 승격이 이루어진 것 같다. 확인을 해보니
postgres-replica-1 로그

본인의 경우 postgres-replica-1가 primary가 된 모습을 확인할 수 있었다. 그럼 이제 postgres-replica-1에 데이터를 한번 넣어보자.

위와 같이 제대로 삽입이 되었고 postgres-replica-2에서

위와 같이 데이터가 잘 저장되어있는 모습을 확인할 수 있었다.
원래 docker-compose를 구성할 때 failover.sh 스크립트를 작성했었는데 bitnami/postgresql-repmgr에서는 기본적으로 기능이 제공되는 것 같다.
[참고자료]
https://hub.docker.com/r/bitnami/pgpool
https://hub.docker.com/r/bitnami/postgresql-repmgr