Postgresql DB 이중화 구성(Docker-Compose)

강동현·2024년 11월 3일

DB

목록 보기
2/3

docker-compose 구성

이번시간에는 저번에 했었던 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에서 하려고 하니까 상당히 많은 문제를 겪게 되었다.

  1. primary_db-init.sh 스크립트 작성
    • postgresql.conf 파일 설정
    • pg_hba.conf 파일 설정
    • 복제 사용자 생성
  2. standby_db1-init.sh 스크립트 작성
    • 복제를 할 폴더 삭제
    • 복제 준비하기 위한 primary_db 서비스 시작하기까지 대기
    • 복제 서버 초기화 및 기본설정
    • postgresql.conf 파일 설정
    • standby.signal파일 생성(이는 standby임을 증명하는 파일임 내용 없어도 됨)
    • pg_hba.conf파일 설정
    • 데이터 디렉토리 권한 설정
  3. standby_db1-init.sh 스크립트 작성
    • 위와 동일함

위와 같은 작업을 하게 되면서 공유 메모리에 대한 오류, 복제하는 과정에서 문제가 생겨 사용자 권한이 없는 경우, 서버를 시작하게 되면 postgresql.pid 파일이 생기는데 이 파일이 없어 서버 시작이 안되는 경우 등등 많은 문제를 겪게 되었다.

그래서 dockerhub에 공식문서를 찾아보던 중
https://hub.docker.com/r/bitnami/postgresql-repmgr
bitnami/postgresql-repmgr 이 이미지로 DB 이중화 구성을 하는 것을 보고 참고하여 구성하게 되었다.

동작 확인

그럼 정상적으로 잘 작동이 되는지 확인해 보자.


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


docker Desktop에 잘 실행되어있는 모습을 확인할 수 있었다.
그럼 이제 정상적으로 잘 복제가 되었는지 데이터를 primary에 넣고 standbydb에 넣은 데이터가 있는지 확인해보자.(참고로 본인은 window에서 진행하고 있다.)

  1. Postgres-Primary-0
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에는 쓰기는 할 수 없다 한번 데이터를 넣어보면

위와 같이 쓰기는 안되는 모습을 확인할 수 있었다.

pgpool failover 관리

그럼 이제 이중화 구성을 끝났다. 하지만 여기서 끝나게 되면 안된다.
저번시간에 배웠던 것 처럼 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

profile
인프라 재밌는데?

0개의 댓글