본문으로 건너뛰기

9.2 모니터링

pg_auto_failover의 상태 정보는 모두 monitor의 PostgreSQL 테이블에 있습니다. 전용 exporter는 없지만 SQL로 조회할 수 있습니다. 따라서 기존 PostgreSQL 모니터링 도구의 custom query로 지표를 만들 수 있습니다. 이 장에서는 조회할 테이블과 채널, 경보 조건을 정리합니다.

무엇을 어디서 보나​

pgautofailover.node​

v2.2 스키마의 주요 컬럼은 다음과 같습니다.

컬럼뜻
reportedstate, goalstatekeeper가 보고한 현재 상태, monitor가 정한 목표 상태
reporttimekeeper가 마지막으로 node_active()를 호출한 시각
health, healthchecktimemonitor 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 테이블과 로그에서 확인합니다.