본문으로 건너뛰기

4.3 PostgreSQL 노드 생성

데이터 노드는 모두 같은 명령 pg_autoctl create postgres로 만듭니다. primary와 standby 중 어느 역할로 만들지는 명령이 아니라 monitor가 정합니다. 노드가 등록을 요청하면 monitor는 그 group에 노드가 이미 있는지 확인합니다. 확인 결과에 따라 single 또는 wait_standby를 반환합니다. 따라서 같은 명령을 두 번째 노드에서 실행하면 자동으로 pg_basebackup을 받아 standby가 됩니다.

네 가지 초기화 모드​

v2.2 명령 문서는 PGDATA 상태와 monitor 응답에 따른 네 가지 경로를 설명합니다.

모드 1과 3은 새로 구축할 때 사용하는 경로입니다. 모드 2와 4는 기존 데이터 디렉터리를 인수하는 경로입니다. 뒤의 두 모드는 4.5에서 따로 다룹니다.

실습 명령​

pg_autoctl create postgres \
--name node1 --hostname node1 --pgport 5432 \
--dbname appdb \
--ssl-self-signed --auth trust --pg-hba-lan \
--run

PG_AUTOCTL_MONITOR 환경 변수에 monitor URI를 넣었으므로 --monitor는 생략했습니다. 첫 노드는 up 후 2.0초 만에 single에 도달했습니다. 두 번째 노드는 97.8초가 걸렸습니다. 이 가운데 95초는 pg_basebackup의 checkpoint 대기 시간이었습니다. 원인과 대처 방법은 1.4에 정리했습니다.

주요 옵션​

옵션의미기본값
--pgdata데이터 디렉터리PGDATA
--monitormonitor URI. autoctl_node 사용자와 pg_auto_failover DB를 가리켜야 함PG_AUTOCTL_MONITOR
--namemonitor에 표시되는 노드 이름자동
--hostname다른 노드와 monitor가 이 노드에 접속할 주소monitor 연결 기준 자동 계산
--dbname애플리케이션용 데이터베이스. 없으면 생성--username 값, 없으면 postgres
--authreplication, 애플리케이션용 HBA 규칙의 인증 방식. monitor health check용 pgautofailover_monitor 규칙은 이 값과 무관하게 trust없음(--skip-pg-hba가 없으면 필수)
--pg-hba-lan감지한 LAN CIDR 전체에서 --dbname 접속 허용꺼짐
--skip-pg-hbaHBA 편집 생략, 필요한 규칙은 로그에 출력꺼짐
--candidate-priority승격 우선순위(0~100)50
--replication-quorum동기 복제 quorum 참여 여부true
--maximum-backup-ratepg_basebackup 전송 속도 상한100M
--ssl-self-signed, --ssl-mode, --ssl-ca-file 등monitor와 같은 SSL 옵션. self-signed, 인증서 파일, --no-ssl 중 하나는 필수
--run생성 후 keeper 서비스로 계속 실행꺼짐

--name은 사람이 읽는 이름이고 --hostname은 접속 주소입니다. 문서는 노드 이름에 primary, standby 같은 역할을 넣지 않도록 권합니다. failover가 발생할 때마다 역할이 바뀌기 때문입니다.

HBA 규칙과 역방향 DNS​

pg_autoctl은 monitor의 health check용 사용자(pgautofailover_monitor)와 복제 사용자(pgautofailover_replicator)를 위한 규칙을 pg_hba.conf 끝에 추가합니다. 호스트명으로 규칙을 작성하려면 PostgreSQL이 접속한 IP의 역방향 DNS를 확인할 수 있어야 합니다. Docker 기본 네트워크에는 역방향 DNS가 없어 다음 경고가 발생했습니다.

05:05:41 10 WARN Postgres might deny connection attempts from "monitor", even with the new HBA rules.
05:05:41 10 WARN Using IP address "172.18.0.2" in HBA file instead of hostname "monitor"
05:05:42 10 WARN Postgres might deny connection attempts from "node2", even with the new HBA rules.
05:05:42 10 WARN Using IP address "172.18.0.4" in HBA file instead of hostname "node2"

그 결과 node1의 pg_hba.conf에는 호스트명 규칙과 IP 규칙이 함께 남았습니다(첫 실습, 기본 Docker 네트워크).

hostssl "appdb" "postgres" node1 trust # Auto-generated by pg_auto_failover
hostssl "appdb" "postgres" 172.18.0.0/16 trust # Auto-generated by pg_auto_failover
hostssl all "pgautofailover_monitor" 172.18.0.2/32 trust # Auto-generated by pg_auto_failover
hostssl replication "pgautofailover_replicator" 172.18.0.4/32 trust # Auto-generated by pg_auto_failover
hostssl "appdb" "pgautofailover_replicator" 172.18.0.4/32 trust # Auto-generated by pg_auto_failover
hostssl replication "pgautofailover_replicator" node2 trust # Auto-generated by pg_auto_failover
hostssl "appdb" "pgautofailover_replicator" node2 trust # Auto-generated by pg_auto_failover

두 번째 줄의 172.18.0.0/16은 --pg-hba-lan이 계산한 LAN입니다. --dbname(appdb)에 대해 LAN 전체의 접속을 허용하는 규칙입니다. 따라서 운영에서는 범위를 확인한 뒤 사용해야 합니다.

경고

IP로 기록된 규칙은 IP가 바뀌면 적용되지 않습니다. 실습에서 node2 컨테이너를 다시 만들어 IP가 바뀌었습니다. 그 결과 no pg_hba.conf entry for replication connection from host "172.18.0.6" 오류가 발생했습니다. node2는 5분 넘게 catchingup에 머물렀습니다. 역방향 DNS를 구성하거나 고정 IP를 사용합니다. 또는 --skip-pg-hba로 규칙을 직접 관리합니다. 규칙이 --dbname에만 생겨 pg_rewind(dbname=postgres로 접속)가 거부되는 문제도 있습니다(6.5).

자동 생성되는 PostgreSQL 설정​

pg_autoctl은 postgresql.conf 맨 위에 include 지시어를 추가하고 postgresql-auto-failover.conf를 만듭니다. include가 앞에 있으므로 postgresql.conf 뒤쪽에 같은 항목을 다시 작성하면 덮어쓸 수 있습니다. 다음은 실습 node1에서 확인한 내용입니다.

# Settings by pg_auto_failover
shared_preload_libraries = pg_stat_statements
listen_addresses = '*'
max_wal_senders = 12
max_replication_slots = 12
wal_level = 'replica'
wal_log_hints = on
wal_sender_timeout = '30s'
hot_standby_feedback = on
hot_standby = on
synchronous_commit = on
logging_collector = on
log_lock_waits = on
ssl = on
wal_keep_size = '8 GB'

# basic tuning computed by pg_auto_failover
track_functions = pl
shared_buffers = '2983 MB'
work_mem = '24 MB'
maintenance_work_mem = '512 MB'
effective_cache_size = '8951 MB'
autovacuum_max_workers = 3
autovacuum_vacuum_scale_factor = 0.08
autovacuum_analyze_scale_factor = 0.02

(일부 줄을 생략했습니다.) 운영에 큰 영향을 주는 값은 다음과 같습니다.

  • wal_log_hints = on: pg_rewind 사용 조건. data checksums는 켜지 않음(data_checksums = off 확인)
  • wal_keep_size = '8 GB': 소스 primary_standby.c에 고정된 값. 디스크 용량 계획에 포함 필요
  • wal_sender_timeout = '30s': 네트워크 분리 때 primary가 standby 연결 끊김을 인식하는 시간(7.4)
  • hot_standby_feedback = on: standby 쿼리 때문에 primary의 vacuum이 지연될 수 있음

아래쪽 "basic tuning"은 소스 pgtuning.c 주석에서 "naive Postgres tuning"이라고 부르는 계산입니다. RAM이 8 GB 이하면 shared_buffers를 RAM의 1/4로 설정합니다. 64 GB 이하에서도 1/4로 설정하며, 그 이상은 16 GB나 32 GB로 고정합니다. RAM은 sysinfo(2)로 읽습니다. 실습 컨테이너에는 메모리 제한을 설정하지 않았습니다. Docker VM 전체 메모리(약 12 GB)의 1/4인 2983 MB가 설정되었습니다. sysinfo(2)는 cgroup 메모리 제한을 반영하지 않습니다. 따라서 메모리를 제한한 컨테이너에서는 값이 지나치게 크게 설정될 것으로 보입니다. 제한을 설정한 경우는 측정하지 않았습니다.

팁

이 튜닝 값은 postgresql-auto-failover.conf에 저장됩니다. keeper가 설정을 다시 적용하면 이 파일이 재생성되며 값도 다시 계산될 수 있습니다. 운영 값은 postgresql.conf 뒤쪽이나 ALTER SYSTEM으로 명시하는 편이 좋습니다. 노드마다 RAM이 다르면 shared_buffers도 노드마다 다르게 설정되기 때문입니다.

정리​

pg_autoctl create postgres 하나로 primary와 standby를 모두 만듭니다. 어느 역할이 될지는 monitor가 정합니다. --auth(또는 --skip-pg-hba)와 SSL 선택은 필수입니다. --name, --hostname, --dbname은 명시하는 편이 좋습니다. --auth scram-sha-256을 지정해도 monitor health check 규칙은 trust로 추가된다는 점을 확인해야 합니다. 자동으로 추가되는 HBA 규칙과 postgresql-auto-failover.conf는 편리합니다. 다만 IP로 기록되는 HBA 규칙과 8 GB wal_keep_size, 호스트 RAM 기준 튜닝은 운영 전에 확인해야 합니다.