9.2 모니터링
pg_auto_failover의 상태 정보는 모두 monitor의 PostgreSQL 테이블에 있습니다. 전용 exporter는 없지만 SQL로 조회할 수 있습니다. 따라서 기존 PostgreSQL 모니터링 도구의 custom query로 지표를 만들 수 있습니다. 이 장에서는 조회할 테이블과 채널, 경보 조건을 정리합니다.
무엇을 어디서 보나
pgautofailover.node
v2.2 스키마의 주요 컬럼은 다음과 같습니다.
| 컬럼 | 뜻 |
|---|---|
reportedstate, goalstate | keeper가 보고한 현재 상태, monitor가 정한 목표 상태 |
reporttime | keeper가 마지막으로 node_active()를 호출한 시각 |
health, healthchecktime | monitor health check 결과(-1 unknown, 0 bad, 1 good)와 시각 |
reportedlsn, reportedtli | 보고된 LSN과 timeline |
reportedrepstate | 보고된 복제 상태(quorum, async 등) |
statechangetime | 마지막 상태 변경 시각 |
candidatepriority, replicationquorum | 복제 설정 |
실습에서 조회한 결과는 다음과 같습니다.
nodeid | nodename | goalstate | reportedstate | health | candidatepriority | replicationquorum | reportedlsn
--------+----------+-----------+---------------+--------+-------------------+-------------------+-------------
1 | node1 | primary | primary | 1 | 50 | t | 0/9055360
2 | node2 | secondary | secondary | 1 | 50 | t | 0/9055360
3 | node3 | secondary | secondary | 1 | 50 | t | 0/9055360
경보 기준 예시
아래 쿼리는 monitor의 pg_auto_failover DB에서 실행합니다. 임계값은 예시입니다. 기본 설정에서는 failover 한 번에 50초 안팎이 걸렸습니다(7.1). 전이 중 발생하는 일시적인 불일치를 경보로 처리하지 않도록 임계값을 이보다 길게 설정합니다.
-- 1. 목표 상태와 현재 상태가 오래 다른 노드: FSM이 진행하지 못함
select nodename, reportedstate, goalstate, now() - statechangetime as stuck_for
from pgautofailover.node
where reportedstate <> goalstate
and now() - statechangetime > interval '2 minutes';
-- 2. keeper 보고가 끊긴 노드
select nodename, now() - reporttime as silent_for
from pgautofailover.node
where now() - reporttime > interval '30 seconds';
-- 3. health check 실패
select nodename, health, healthchecktime
from pgautofailover.node
where health <> 1;
-- 4. primary가 wait_primary에 머묾: 동기 복제가 꺼졌고 자동 failover도 불가
-- standby 합류나 failover 직후에도 잠깐 나타나므로 시간 조건을 둔다
select nodename, now() - statechangetime as degraded_for
from pgautofailover.node
where reportedstate = 'wait_primary' and goalstate = 'wait_primary'
and now() - statechangetime > interval '2 minutes';
-- 5. 후보로 설정된 건강한 standby 수 (group 0 기준)
-- 실제 승격 여부는 WAL 차이, timeline, WAL 원본 가용성도 본다
select count(*) filter (where reportedstate = 'secondary' and goalstate = 'secondary'
and candidatepriority > 0 and health = 1) as candidates
from pgautofailover.node
where formationid = 'default' and groupid = 0;
4번은 이 도구에서 특히 중요합니다. wait_primary는 서비스를 제공할 수 있지만 데이터가 한 벌뿐인 상태입니다. 7.5 실측 결과처럼 이 상태에서 primary까지 잃으면 자동 승격이 일어나지 않습니다.
event 테이블
pgautofailover.event에는 monitor가 내린 결정과 보고가 사유 문장과 함께 기록됩니다. 경보가 울렸을 때 가장 먼저 확인할 곳입니다.
select to_char(eventtime, 'HH24:MI:SS.MS') as t, nodename, reportedstate, goalstate, description
from pgautofailover.event
where eventtime > now() - interval '10 minutes'
order by eventid;
pg_autoctl show events --count 20도 같은 테이블을 읽습니다. event 테이블은 계속 커집니다. 따라서 오래된 행을 지우는 작업이 필요한지 확인해야 합니다. v2.2 문서에는 보존 기간 설정이 없습니다.
NOTIFY 채널
운영 문서에 따르면 monitor는 모든 상태 결정을 state 채널로 NOTIFY합니다. 로그 메시지는 log 채널로 NOTIFY합니다. state payload는 formation, groupId, nodeId, name, host, port, reportedState, goalState, health를 담은 JSON입니다(v2.2 notifications.c).
psql "postgres://autoctl_node@monitor:5432/pg_auto_failover?sslmode=require" <<'SQL'
LISTEN state;
SELECT pg_sleep(60);
SQL
NOTIFY는 연결이 끊긴 동안 발생한 메시지를 보존하지 않습니다. 알림을 놓치면 안 된다면 event 테이블을 eventid부터 이어서 읽는 방식도 함께 사용합니다.
데이터 노드 쪽 확인
primary에서 pg_stat_replication의 sync_state를 확인하면 monitor가 설정한 동기 복제가 실제로 적용됐는지 확인됩니다. ANY N (...) 형식이므로 값은 quorum으로 나옵니다.
select application_name, state, sync_state from pg_stat_replication;
show synchronous_standby_names;
pgautofailover_standby_2|streaming|quorum
ANY 1 (pgautofailover_standby_2)
postgres_exporter 같은 도구는 custom query 파일에 위 SQL을 넣어 gauge로 내보내면 됩니다. monitor 쿼리는 monitor에서 수집합니다. pg_stat_replication은 각 데이터 노드에서 수집합니다. 이 노트에서는 exporter 연동을 실측하지 않았습니다.
정리
pg_auto_failover 모니터링의 대상은 monitor의 node 테이블입니다. 목표 상태와 현재 상태의 장기 불일치, keeper 보고 중단, health 실패를 경보 조건으로 설정합니다. wait_primary 지속 여부와 후보로 설정된 건강한 standby 수도 경보 조건으로 설정합니다. 이렇게 하면 대부분의 이상을 먼저 감지하게 됩니다. 원인은 event 테이블과 로그에서 확인합니다.