6.2 switchover와 promotion
계획된 primary 교체에는 세 가지 명령이 있습니다. pg_autoctl perform switchover, pg_autoctl perform failover, pg_autoctl perform promotion입니다. 앞의 두 명령은 이름만 다를 뿐 같은 동작을 합니다. v2.2 운영 문서는 두 명령이 "synonyms, or aliases"라고 명시합니다. 계획된 교체인지 장애 대응인지는 monitor가 판단합니다. 클라이언트 명령이 아니라 현재 primary의 건강 상태를 기준으로 판단합니다. perform promotion은 승격할 노드를 직접 지정한다는 점만 다릅니다.
명령이 하는 일
명령은 monitor의 SQL 함수를 호출해 목표 상태를 바꿉니다. 이어서 state 채널을 LISTEN하며 알림을 표 형태로 출력합니다. 실제 작업 조율은 monitor와 keeper가 담당합니다. 따라서 명령의 대기 시간(--wait, 기본 60초)이 지나도 전이는 백그라운드에서 계속됩니다.
switchover 실측
2노드 구성에서 writer를 실행한 상태로 측정했습니다.
docker compose exec -T app bash /lab/scripts/writer.sh 30 > w.log &
docker compose exec monitor pg_autoctl perform switchover
05:27:10 | node1 | 1 | node1:5432 | primary | draining
05:27:10 | node2 | 2 | node2:5432 | secondary | prepare_promotion
05:27:10 | node2 | 2 | node2:5432 | prepare_promotion | stop_replication
05:27:10 | node1 | 1 | node1:5432 | primary | demote_timeout
05:27:11 | node2 | 2 | node2:5432 | stop_replication | wait_primary
05:27:11 | node1 | 1 | node1:5432 | demote_timeout | demoted
05:27:12 | node1 | 1 | node1:5432 | demoted | catchingup
05:27:15 | node1 | 1 | node1:5432 | catchingup | secondary
05:27:15 | node2 | 2 | node2:5432 | wait_primary | primary
perform switchover returned in 5.5s
writer: 122 ok, 5 FAIL, longest gap between ok starts 1.35s
| 구간 | 측정값 |
|---|---|
| 명령 반환 | 5.5초 |
| 실패한 INSERT | 5건 (옛 primary의 Connection refused) |
| 성공한 INSERT 사이 최장 간격 | 1.35초 |
장애 failover는 50초 넘게 걸리지만 switchover는 1초대에 끝납니다. 이는 기존 primary가 살아 있기 때문입니다. monitor가 demote_timeout을 지정하면 기존 primary의 keeper가 PostgreSQL을 멈춥니다. keeper가 정지를 보고하면 monitor는 즉시 다음 단계로 넘어갑니다. primary_demote_timeout 30초를 모두 기다리는 경우는 기존 primary가 응답하지 않을 때뿐입니다(7.1).
새 primary는 wait_primary에 도달하면 쓰기를 받습니다. 이 시점에는 standby가 아직 없으므로 동기 복제가 꺼져 있습니다. 기존 primary가 secondary까지 따라잡으면 monitor는 새 primary를 primary로 올립니다. 이어서 동기 복제를 다시 켭니다. 실습에서는 05:27:11부터 05:27:15까지 약 4초 동안 비동기 구간이 있었습니다.
perform promotion
특정 노드를 승격하려면 perform promotion을 사용합니다. 3노드 구성에서 node3의 candidate priority를 0으로 설정한 상태로 node1을 지정했습니다.
docker compose exec monitor pg_autoctl perform promotion --name node1
05:39:25 | node3 | 0/3 | node3:5432 | secondary | secondary
05:39:25 | node1 | 0/1 | node1:5432 | wait_primary | primary
05:39:25 | node1 | 0/1 | node1:5432 | primary | primary
returned 4.0s
v1.5.2 CHANGELOG에 따르면 candidate priority가 0인 노드도 수동 promotion은 허용됩니다(#661). 자동 failover 후보에서만 제외된다는 뜻입니다. 이 동작은 문서와 CHANGELOG로만 확인했습니다. 실습에서는 priority 0 노드를 승격하지 않았습니다.
v2.2-4.pgdg13+1에서 perform switchover와 perform promotion은 진행 표 앞에 다음과 같은 ERROR를 몇 줄 출력합니다.
ERROR Monitor ERROR: invalid input syntax for type integer: "about state changes in f"
ERROR SQL query: SELECT * FROM pgautofailover.get_nodes($1, $2) ORDER BY node_id
WARN Failed to get_nodes() on the monitor
알림 표시용 노드 목록을 가져오는 호출에 group 인자가 잘못 전달되는 문제로 보입니다. 실습의 모든 switchover와 promotion은 정상적으로 완료되었습니다.
실행 전 확인
switchover는 standby가 secondary 상태일 때만 의미가 있습니다. standby가 catchingup이면 승격 후보가 없습니다. 따라서 monitor는 전환을 진행하지 않습니다. 실행 전에 다음을 확인합니다.
pg_autoctl show state # 모든 노드가 reported = assigned
pg_autoctl show settings # 후보가 될 노드의 candidate priority > 0
switchover 중 애플리케이션은 1~2초 동안 연결에 실패합니다. 이 시간이 늘어나지 않도록 드라이버가 multi-host URI와 target_session_attrs=read-write로 재접속해야 합니다(8.1).
정리
perform switchover와 perform failover는 같은 명령입니다. monitor가 상황에 맞게 작업을 조율합니다. 기존 primary가 살아 있으면 demote를 기다리지 않습니다. 따라서 쓰기 공백은 1.35초에 그쳤습니다. 특정 노드를 승격하려면 perform promotion --name을 사용합니다.