4.4 systemd, 파일 배치, pg_autoctl config
pg_autoctl run은 PostgreSQL을 자식 프로세스로 실행하고 keeper 루프를 구동하는 단일 프로세스 트리입니다. 따라서 systemd에는 PostgreSQL 서비스가 아니라 pg_autoctl 서비스 하나만 등록합니다. 이 장에서는 unit 파일을 만드는 방법을 설명합니다. 또한 pg_autoctl이 사용하는 세 종류의 파일 위치와 설정 파일을 조회하고 변경하는 pg_autoctl config 명령을 정리합니다.
프로세스 구조
실습 로그에서도 같은 구조를 확인할 수 있습니다. supervisor가 두 서비스를 실행하고, postgres 서비스가 PostgreSQL을 실행합니다.
05:05:42 7 INFO Started pg_autoctl postgres service with pid 9
05:05:42 9 INFO /usr/bin/pg_autoctl do service postgres --pgdata /var/lib/pgaf/data -v
05:05:42 7 INFO Started pg_autoctl node-active service with pid 10
systemd unit
pg_autoctl show systemd는 현재 노드에 맞는 unit 파일을 출력합니다. 다음은 실습 node1의 출력입니다.
[Unit]
Description = pg_auto_failover
[Service]
WorkingDirectory = /var/lib/postgresql
Environment = 'PGDATA=/var/lib/pgaf/data'
User = postgres
ExecStart = /usr/bin/pg_autoctl run
Restart = always
StartLimitBurst = 0
ExecReload = /usr/bin/pg_autoctl reload
[Install]
WantedBy = multi-user.target
v2.2 설치 문서는 이 출력을 파일로 저장하고 서비스를 활성화하는 명령도 함께 안내합니다.
pg_autoctl -q show systemd --pgdata /var/lib/postgresql/17/main \
| sudo tee /etc/systemd/system/pgautofailover.service
sudo systemctl daemon-reload
sudo systemctl enable --now pgautofailover
ExecReload는 v1.5.1에서 추가되었습니다. v2.2 문서의 예시 출력에는 이 줄이 없습니다. ExecStart 경로도 /usr/lib/postgresql/17/bin/pg_autoctl로 나옵니다. 실습 패키지는 /usr/bin/pg_autoctl을 출력했습니다. 따라서 문서의 예시를 복사하지 않고 각 노드에서 출력한 결과를 사용합니다.
Debian의 postgresql@17-main 같은 기본 서비스가 같은 PGDATA를 관리해서는 안 됩니다. 그러면 두 서비스가 PostgreSQL을 동시에 실행하려 할 수 있습니다. 또한 failover 후 standby로 복귀해야 할 이전 primary를 systemd가 primary로 기동할 위험이 있습니다. 4.1의 create_main_cluster = false 설정은 이 상황을 방지합니다.
파일 세 종류
pg_autoctl은 XDG Base Directory 규칙을 따릅니다. PGDATA 경로는 하위 디렉터리 이름으로 사용합니다.
| 파일 | 기준 디렉터리 | 기본값 | 내용 |
|---|---|---|---|
설정 pg_autoctl.cfg | XDG_CONFIG_HOME | ~/.config | monitor URI, 노드 이름, PostgreSQL 경로, timeout |
상태 pg_autoctl.state, pg_autoctl.init | XDG_DATA_HOME | ~/.local/share | keeper가 마지막으로 받은 목표 상태, 초기화 진행 상태 |
pid pg_autoctl.pid | XDG_RUNTIME_DIR | 없으면 /tmp | 실행 중인 supervisor pid |
실습 이미지는 두 XDG 변수를 볼륨 내부로 지정했습니다. 다음은 pg_autoctl show file의 출력입니다.
File | Path
--------+----------------
Config | /var/lib/pgaf/config/pg_autoctl/var/lib/pgaf/data/pg_autoctl.cfg
State | /var/lib/pgaf/share/pg_autoctl/var/lib/pgaf/data/pg_autoctl.state
Init | /var/lib/pgaf/share/pg_autoctl/var/lib/pgaf/data/pg_autoctl.init
Pid | /tmp/pg_autoctl/var/lib/pgaf/data/pg_autoctl.pid
상태 파일은 PGDATA와 함께 보존해야 합니다. PGDATA만 백업하거나 옮기고 상태 파일을 남겨 두면 keeper는 자신의 역할을 알지 못한 채 기동합니다. 반대로 pid 파일은 재부팅 후 남아 있으면 안 됩니다. 실습에서는 /tmp가 컨테이너 레이어에 남아 있었습니다. 이 때문에 재시작한 keeper가 같은 pid를 받자 FATAL pg_autoctl is already running with pid 6로 종료했습니다. compose에서 /tmp를 tmpfs로 바꿔 해결했습니다(9.4).
pg_autoctl config
설정 파일은 INI 형식입니다. pg_autoctl config get으로 전체 설정을 확인하거나 특정 항목을 읽습니다. 다음은 실습 node1의 출력 일부입니다.
[pg_autoctl]
role = keeper
monitor = postgres://autoctl_node@monitor:5432/pg_auto_failover?sslmode=require
formation = default
group = 0
name = node1
hostname = node1
[postgresql]
pgdata = /var/lib/pgaf/data
dbname = appdb
port = 5432
[replication]
maximum_backup_rate = 100M
backup_directory = /var/lib/pgaf/backup/node_1
[timeout]
network_partition_timeout = 20
prepare_promotion_catchup = 30
prepare_promotion_walreceiver = 5
postgresql_restart_failure_timeout = 20
postgresql_restart_failure_max_retries = 3
listen_notifications_timeout = 0
[timeout] 섹션은 keeper에서 사용하는 타이머입니다. monitor의 pgautofailover.* GUC와 별개이며 각 노드에서 따로 설정합니다.
| 항목 | 기본값 | 의미 (v2.2 문서 기준) |
|---|---|---|
network_partition_timeout | 20초 | primary가 monitor와 standby 모두와 통신이 끊긴 후 스스로 멈추기까지 기다리는 시간 |
prepare_promotion_catchup | 30초 | 이름은 승격 후보가 WAL을 따라잡도록 기다리는 시간이지만 v2.2 문서에는 "소스에서 현재 쓰이지 않는다"고 명시 |
postgresql_restart_failure_timeout | 20초 | PostgreSQL이 종료되었을 때 재시작을 시도하는 시간 한도 |
postgresql_restart_failure_max_retries | 3 | 같은 상황에서 재시작을 시도하는 횟수 |
backup_directory는 pg_basebackup이 데이터를 먼저 저장하는 임시 위치입니다. 복사가 끝나면 PGDATA로 rename합니다. 따라서 원자적으로 변경하려면 PGDATA와 같은 파일시스템에 있어야 합니다.
값을 변경할 때는 config set을 사용합니다. 실행 중인 서비스에는 reload를 보냅니다.
pg_autoctl config set timeout.network_partition_timeout 30
pg_autoctl config set replication.password 'h4ckm3m0r3' # keeper 가 upstream 에 보낼 비밀번호만 설정
pg_autoctl config check
pg_autoctl reload
문서에서는 [postgresql] 섹션을 pg_autoctl이 자동으로 채우므로 직접 변경하지 말라고 명시합니다. pg_autoctl.group도 등록할 때 monitor에서 받은 값이므로 변경하지 않습니다. replication.password는 keeper가 upstream에 접속할 때 사용할 비밀번호입니다. PostgreSQL의 pgautofailover_replicator 역할 비밀번호를 변경하지는 않습니다. upstream에서 ALTER USER pgautofailover_replicator PASSWORD ...를 별도로 실행해야 합니다. 또한 두 번째 노드에서 첫 pg_basebackup을 실행하기 전에는 PGPASSWORD나 .pgpass로 비밀번호를 제공해야 합니다(8.3). 이 값은 설정 파일에 평문으로 남습니다. 따라서 문서는 ~/.pgpass 사용도 함께 권장합니다.
정리
systemd에는 pg_autoctl run 하나만 등록합니다. unit 파일은 pg_autoctl show systemd의 출력을 사용합니다. 설정은 XDG_CONFIG_HOME, 상태는 XDG_DATA_HOME에 있습니다. pid는 XDG_RUNTIME_DIR 또는 /tmp에 있습니다. 상태 파일은 PGDATA와 함께 보존합니다. pid 파일은 재부팅할 때 비워지는 위치에 둡니다. keeper의 timeout은 pg_autoctl config로 노드마다 관리합니다.