7.3 monitor 장애
monitor는 복제본이 없는 단일 인스턴스입니다. 이 때문에 "monitor가 죽으면 서비스도 죽는가"라는 질문을 가장 자주 받습니다. 답은 서비스는 계속되지만 결정은 멈춘다는 것입니다. 이 장에서는 세 단계로 확인했습니다. monitor만 멈추고, monitor가 멈춘 동안 primary를 죽이고, 마지막으로 monitor를 되살립니다.
1단계: monitor만 중지
3노드(node1 primary, node2와 node3 secondary)가 모두 건강한 상태에서 writer.sh를 40초 동안 실행했습니다. 실행 중에 docker compose stop monitor를 실행했습니다.
| 항목 | 측정값 |
|---|---|
| monitor 중지 시각 | 05:33:25.098 |
| 40초 동안 성공한 INSERT | 166건 |
| 실패한 INSERT | 0건 |
| 성공 INSERT 간 최장 간격 | 0.33초 |
primary keeper 로그에는 monitor에 접속하지 못한다는 경고가 반복됩니다. 동시에 standby가 연결되어 있으므로 네트워크 분리가 아니라고 판단한 로그도 남습니다.
05:33:57 11 WARN We lost the monitor, but still have a standby: we're not in a network partition, continuing.
05:33:59 11 WARN Failed to connect to "postgres://autoctl_node@monitor:5432/pg_auto_failover?sslmode=require", retrying until the server is ready
05:33:59 11 WARN Lost connection.
streaming replication은 PostgreSQL 간의 연결이며 monitor를 거치지 않습니다. synchronous_standby_names도 primary에 이미 설정되어 있습니다. 따라서 커밋은 평소처럼 standby의 확인을 받습니다.
2단계: monitor가 없는 동안 primary kill
monitor를 멈춘 상태에서 05:34:17.522에 primary node1을 kill하고 45초를 기다렸습니다.
node2 in_recovery=t
node3 in_recovery=t
두 standby 모두 recovery 상태를 유지했습니다. 승격을 결정할 주체가 없으므로 어떤 standby도 promote하지 않습니다. keeper는 monitor에 목표 상태를 묻지 못했다는 오류만 남깁니다.
05:35:02 11 ERROR Failed to connect to monitor database at "postgres://autoctl_node@monitor:5432/pg_auto_failover?sslmode=require", see above for details
05:35:02 11 ERROR Failed to get the goal state from the monitor
3단계: monitor 재시작
05:35:04.079에 monitor를 다시 시작했습니다. 새 primary가 쓰기 가능한 상태가 되기까지 46.3초가 걸렸습니다.
pgautofailover.startup_grace_period(기본 10000ms)는 monitor의 PostgreSQL이 시작한 뒤 일정 시간 동안 failover를 막습니다. 이름과 달리 데이터 노드가 아닌 monitor의 기동 시각을 기준으로 합니다. v2.2 소스의 IsUnhealthy()는 PgStartTime과 현재 시각의 차가 이 값을 넘어야 true를 반환합니다. 재시작 직후 monitor에는 모든 노드의 마지막 보고 시각이 오래된 것으로 보입니다. 이 유예가 없으면 기동 직후 불필요한 failover를 시작할 수 있습니다.
이후 과정은 7.1의 3노드 흐름과 같습니다. report_lsn으로 후보를 선정하고, stop_replication 이후 primary_demote_timeout 30초를 기다립니다. 45.7초 가운데 약 30초가 이 대기 시간입니다.
monitor가 없는 동안 할 수 없는 일
v2.2 FAQ는 monitor가 새 목표 상태를 지정하는 경우를 네 가지로 설명합니다. 새 노드 등록, 자동 또는 수동 failover, maintenance 전환, 복제 설정 변경입니다. monitor가 멈추면 이 네 가지가 모두 불가능합니다.
pg_autoctl perform switchover,perform failover,perform promotionpg_autoctl enable maintenance,disable maintenancepg_autoctl set node candidate-priority,replication-quorum,set formation number-sync-standbys- 새 노드
pg_autoctl create postgres,drop node - secondary 장애 시
wait_primary전환. 2노드에서 monitor와 secondary를 함께 잃으면 primary의 커밋이 계속 멈춥니다. keeper의 네트워크 분리 검사는 현재 상태가primary일 때만 실행됩니다. 따라서 secondary를 먼저 잃어 이미wait_primary인 노드는 자체 강등 절차를 시작하지 않습니다(v2.2service_keeper.c).
마지막 항목은 7.2의 반대 상황입니다. 동기 복제를 끄는 결정도 monitor가 내리기 때문입니다.
monitor와 standby를 동시에 잃으면 primary는 스스로 멈출 수 있습니다. keeper의 is_network_healthy()는 monitor에 접속하지 못하고 pg_stat_replication에도 standby 연결이 없는 상태를 확인합니다. 이 상태가 network_partition_timeout(기본 20초)을 넘으면 네트워크 분리로 판단하고 demote_timeout으로 전환합니다. primary에서는 "monitor와 standby가 죽었다"는 상황과 "내가 고립되었다"는 상황을 구분할 수 없기 때문입니다. 이 조합은 이 노트에서 실측하지 않았습니다. 판단 근거는 v2.2 src/bin/pg_autoctl/service_keeper.c와 7.4의 고립 실험입니다.
정리
monitor는 데이터 경로가 아니라 control plane의 단일 장애점입니다. monitor를 멈춘 40초 동안 쓰기 실패는 0건이었습니다. 그러나 그동안 primary가 죽으면 어떤 standby도 승격하지 않습니다. monitor가 돌아온 뒤에도 유예와 demote 대기로 46초가 더 걸렸습니다. monitor의 가용성이 곧 failover의 가용성입니다. monitor 복구 절차는 6.6에서 다룹니다.