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 |
--monitor | monitor URI. autoctl_node 사용자와 pg_auto_failover DB를 가리켜야 함 | PG_AUTOCTL_MONITOR |
--name | monitor에 표시되는 노드 이름 | 자동 |
--hostname | 다른 노드와 monitor가 이 노드에 접속할 주소 | monitor 연결 기준 자동 계산 |
--dbname | 애플리케이션용 데이터베이스. 없으면 생성 | --username 값, 없으면 postgres |
--auth | replication, 애플리케이션용 HBA 규칙의 인증 방식. monitor health check용 pgautofailover_monitor 규칙은 이 값과 무관하게 trust | 없음(--skip-pg-hba가 없으면 필수) |
--pg-hba-lan | 감지한 LAN CIDR 전체에서 --dbname 접속 허용 | 꺼짐 |
--skip-pg-hba | HBA 편집 생략, 필요한 규칙은 로그에 출력 | 꺼짐 |
--candidate-priority | 승격 우선순위(0~100) | 50 |
--replication-quorum | 동기 복제 quorum 참여 여부 | true |
--maximum-backup-rate | pg_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 기준 튜닝은 운영 전에 확인해야 합니다.