3.1 FSM 읽는 법
pg_auto_failover 문서는 상태 머신을 다음과 같이 요약합니다. 노드의 현재 상태는 그 노드가 할 수 있는 일을 명확히 보장합니다. 상태 자체는 아무 동작도 일으키지 않으며, 동작은 전이 중에 일어납니다. 이 문장을 로그를 읽는 규칙으로 바꾸면 세 가지입니다. 현재 상태와 목표 상태를 구분해야 합니다. monitor는 한 번에 한 단계만 진행합니다. 전이가 끝나야 다음 결정이 나옵니다.
현재 상태와 목표 상태
pg_autoctl show state의 마지막 두 열이 이 둘을 나타냅니다.
Name | Node | Host:Port | TLI: LSN | Connection | Reported State | Assigned State
------+-------+------------+----------------+--------------+---------------------+--------------------
node1 | 1 | node1:5432 | 3: 0/500C9E8 | read-write | wait_primary | wait_primary
node2 | 2 | node2:5432 | 2: 0/500C3E0 | read-write ! | primary | demoted
node1은 두 값이 같으므로 안정 상태입니다. node2는 monitor가 demoted를 지정했지만, keeper가 마지막으로 보고한 상태는 여전히 primary입니다. 이 출력은 node2 컨테이너를 kill한 직후의 결과라 node2는 상태를 보고할 수 없었습니다. Connection 열의 !는 monitor health check가 실패했음을 나타냅니다.
monitor는 보통 목표를 한 단계만 바꾸고 노드들이 수렴할 때까지 기다립니다. keeper가 전이에 실패하면 같은 전이를 반복합니다. 그동안 monitor도 다음 단계로 넘어가지 않습니다. 상태가 멈춘 것처럼 보이는 원인은 두 가지입니다. 특정 노드의 keeper가 전이를 끝내지 못했을 수 있습니다. 또는 monitor가 의도적으로 기다리고 있을 수 있습니다. 후자에는 timeout 대기, 아직 보고하지 않은 report_lsn 노드, 부족한 quorum 후보, WAL 지연 임계값 초과 등이 있습니다. keeper를 재시작하기 전에 이벤트 사유부터 확인합니다. FAQ도 이런 경우에는 health check의 성공 여부와 pg_autoctl run의 실행 여부를 먼저 확인하라고 안내합니다.
이벤트 로그 읽기
pg_autoctl show events는 pgautofailover.event 테이블을 출력합니다.
Event Time | Node | Current State | Assigned State | Comment
-------------------------------+--------+---------------------+---------------------+-----------
2026-09-28 05:09:18.382442+00 | 0/2 | primary | primary | Node node 2 "node2" (node2:5432) is marked as unhealthy by the monitor
2026-09-28 05:09:31.102998+00 | 0/1 | secondary | prepare_promotion | Setting goal state of node 2 "node2" (node2:5432) to draining and node 1 "node1" (node1:5432) to prepare_promotion after node 2 "node2" (node2:5432) became unhealthy.
2026-09-28 05:09:31.130043+00 | 0/1 | prepare_promotion | prepare_promotion | New state is reported by node 1 "node1" (node1:5432): "prepare_promotion"
Node 열의 0/2는 group 0의 node id 2를 뜻합니다. Comment는 세 종류로 나뉩니다.
| Comment 형태 | 의미 |
|---|---|
Setting goal state of ... to ... after ... | monitor의 결정. after 뒤가 결정 사유 |
New state is reported by ... | keeper가 전이를 끝내고 보고 |
... is marked as healthy/unhealthy by the monitor | health check 결과 변화 |
한 결정으로 두 노드의 목표를 함께 바꾸면 같은 시각에 두 줄이 기록됩니다. 위 예의 05:09:31.102998은 한 번의 결정입니다. node2를 draining으로, node1을 prepare_promotion으로 바꿨습니다. 장애 분석은 Setting goal state 줄만 시간순으로 추려 사유를 읽는 것부터 시작합니다. SQL에서는 description LIKE 'Setting goal state%'로 거르면 됩니다. NOT LIKE 'New state is reported%'로 거르면 health 변화와 같은 다른 이벤트도 함께 남습니다.
SELECT to_char(eventtime, 'HH24:MI:SS.MS'), nodename, reportedstate, goalstate, description
FROM pgautofailover.event
WHERE eventtime > now() - interval '10 min'
AND description NOT LIKE 'New state is reported%'
ORDER BY eventid;
상태 분류
v2.2 문서의 상태 목록을 역할별로 묶으면 다음과 같습니다.
| 분류 | 상태 | PostgreSQL |
|---|---|---|
| 초기 | init, single | single은 복제 없는 단독 primary |
| primary 계열 | wait_primary, primary, join_primary(폐기), apply_settings | 쓰기 가능 |
| primary 종료 계열 | draining, demote_timeout, demoted, prepare_maintenance | 중지 |
| standby 계열 | wait_standby, catchingup, secondary, report_lsn, fast_forward, join_secondary | standby |
| 승격 계열 | prepare_promotion, stop_replication | stop_replication에서 승격, 읽기 전용 |
| 운영 | wait_maintenance, maintenance, dropped | 상태별로 다름 |
문서는 애플리케이션이 read-write로 접속할 수 있는 상태로 single, wait_primary, primary, prepare_maintenance, apply_settings를 제시합니다. 문장에는 "여섯 개"라고 적혀 있지만 목록에는 다섯 개만 있습니다. 소스의 전이 표에 따르면 primary에서 prepare_maintenance로 가는 전이 함수는 PostgreSQL을 중지합니다. 따라서 이 노트에서는 prepare_maintenance를 종료 계열로 분류했습니다.
위 도식은 탄생과 2노드 failover에 사용하는 전이만 추린 것입니다. 전체 전이 목록은 소스 src/bin/pg_autoctl/fsm.c의 전이 표에 있습니다. 테스트 빌드에서는 PG_AUTOCTL_DEBUG=1 pg_autoctl do fsm gv 명령으로 Graphviz 그림을 만들 수 있다고 문서에 나옵니다.
현재 상태만 보고 판단하면 오류가 생기기 쉽습니다. reported = primary, assigned = demoted인 노드는 강등 명령을 받았지만 아직 실행 결과를 확인하지 못한 노드입니다. reported는 마지막으로 보고한 상태입니다. assigned는 아직 받거나 실행하지 않았을 수 있는 명령입니다. 따라서 이 노드는 전이가 끝날 때까지 실제로 쓰기를 받을 가능성이 있습니다. 반대로 두 값이 같아도 health check가 실패한다면 안전한 라우팅 대상이 아닙니다. 라우팅이나 알람 규칙에서는 두 값의 일치 여부와 health를 함께 확인해야 합니다.
정리
상태는 보장이고 전이는 동작입니다. 로그를 읽을 때는 Setting goal state 줄에서 monitor의 결정과 사유를 확인합니다. New state is reported 줄에서는 keeper가 실제로 도달한 시각을 확인합니다. 다음 장부터는 이 방법으로 탄생, failover, 선출, maintenance를 차례로 읽습니다.