본문으로 건너뛰기

6.3 maintenance

커널 업데이트나 하드웨어 점검을 위해 노드를 내려야 할 때는 먼저 maintenance 상태로 전환합니다. maintenance 상태의 노드는 monitor가 관리 대상에서 잠시 제외합니다. 따라서 노드를 멈춰도 failover나 복제 설정 변경이 발생하지 않습니다. 명령은 pg_autoctl enable maintenance와 pg_autoctl disable maintenance 두 개입니다. 대상이 secondary인지 primary인지에 따라 monitor가 수행하는 상태 전이가 다릅니다.

secondary를 maintenance로​

2노드 구성에서 secondary를 maintenance로 전환하면 primary는 동기 복제를 처리할 standby를 잃습니다. 그래서 monitor는 먼저 primary를 wait_primary로 바꿔 동기 복제를 끕니다. secondary는 wait_maintenance에서 기다립니다. primary가 wait_primary에 도달해야 secondary가 maintenance 상태가 됩니다. 순서를 반대로 하면 standby를 멈추는 순간 primary의 모든 커밋이 중단됩니다. 이 흐름은 v2.2 운영 문서의 출력 예시에서 확인했습니다.

3노드 구성에서는 다른 quorum standby가 남아 있으므로 primary를 변경할 필요가 없습니다. 실습에서 node3를 maintenance로 전환했을 때 primary는 그대로 primary였습니다.

docker compose exec node3 pg_autoctl enable maintenance
Time | Name | Node | Host:Port | Current State | Assigned State
---------+-------+-------+------------+---------------------+--------------------
05:38:18 | node3 | 3 | node3:5432 | secondary | maintenance
05:38:18 | node3 | 3 | node3:5432 | maintenance | maintenance
returned in 0.5s
Name | Node | Host:Port | TLI: LSN | Connection | Reported State | Assigned State
------+-------+------------+----------------+--------------+---------------------+--------------------
node1 | 1 | node1:5432 | 7: 0/903F8F0 | read-write | primary | primary
node2 | 2 | node2:5432 | 7: 0/9000000 | read-only | secondary | secondary
node3 | 3 | node3:5432 | 7: 0/903F8F0 | none | maintenance | maintenance

두 가지를 주의해서 살펴볼 필요가 있습니다. 첫째, maintenance에 진입한 뒤에도 node3의 PostgreSQL은 실행 중이었습니다(pg_is_in_recovery()가 true로 응답). secondary의 maintenance는 PostgreSQL을 멈추는 명령이 아닙니다. PostgreSQL을 멈춰도 되는 상태로 전환하는 명령입니다. 실제 정지는 운영자가 수행합니다. 반면 primary의 enable maintenance --allow-failover를 실행하면 keeper가 checkpoint 후 PostgreSQL을 직접 멈춥니다. 또한 standby로 돌아올 수 있도록 설정을 준비합니다(v2.2 fsm_transition.c의 fsm_stop_postgres_for_primary_maintenance). 둘째, primary의 synchronous_standby_names는 여전히 'ANY 1 (pgautofailover_standby_2, pgautofailover_standby_3)'였습니다. node2가 실행 중이므로 커밋은 중단되지 않습니다. 하지만 maintenance 중에 node2까지 잃으면 커밋이 중단될 것으로 예상됩니다. 이 조합은 실습하지 않았습니다.

해제하면 catchingup을 거쳐 secondary로 돌아옵니다.

05:38:20 | node3 | 3 | node3:5432 | catchingup | secondary
05:38:20 | node3 | 3 | node3:5432 | secondary | secondary
disable returned in 1.4s

primary를 maintenance로​

primary는 항상 하나 있어야 합니다. 따라서 primary를 maintenance로 전환하려면 먼저 failover가 필요합니다. --allow-failover 없이 실행하면 명령이 거부됩니다(v2.2 문서 예시).

$ pg_autoctl enable maintenance
WARN Enabling maintenance on a primary causes a failover
FATAL Please use --allow-failover to allow the command proceed

3노드 구성에서 writer를 실행한 상태로 다음 명령을 수행했습니다.

docker compose exec node1 pg_autoctl enable maintenance --allow-failover
05:38:26 | node2 | 2 | node2:5432 | secondary | report_lsn
05:38:26 | node3 | 3 | node3:5432 | secondary | report_lsn
05:38:27 | node2 | 2 | node2:5432 | report_lsn | prepare_promotion
05:38:27 | node1 | 1 | node1:5432 | maintenance | maintenance
returned in 1.7s
writer: 105 ok, 11 FAIL, longest gap between ok starts 3.74s

standby가 둘이므로 monitor는 report_lsn으로 두 standby의 WAL 위치를 수집한 뒤 node2를 선택했습니다. 명령은 1.7초 만에 반환됐고, 쓰기 공백은 3.74초였습니다. 이 명령은 이전 primary가 maintenance를 보고하는 시점에 반환됩니다. 새 primary의 승격은 그 뒤에도 진행 중일 수 있습니다. 따라서 서비스 복구 여부는 show state에서 별도로 확인합니다. 새 노드의 Reported와 Assigned가 모두 primary인지 확인해야 합니다. 같은 구성의 switchover(1.35초, 2노드)보다 시간이 더 걸린 이유는 report_lsn 단계가 한 번 더 수행되기 때문으로 보입니다. 해제하면 이전 primary는 catchingup을 거쳐 secondary로 돌아왔습니다.

경고

maintenance는 monitor가 해당 노드를 관리하지 않겠다는 선언입니다. maintenance 상태의 노드는 failover 후보가 아닙니다. 2노드에서 secondary를 maintenance로 전환한 동안 primary가 중단되면 자동 승격이 일어나지 않습니다. 작업 시간을 짧게 계획하고, 가능하면 3노드 이상에서 한 노드씩 진행합니다.

권장 순서​

  1. pg_autoctl show state로 모든 노드가 안정 상태인지 확인합니다.
  2. secondary부터 enable maintenance 후 PostgreSQL과 OS 작업을 합니다.
  3. disable maintenance로 복귀시키고 secondary 도달을 확인합니다.
  4. 마지막으로 primary에서 enable maintenance --allow-failover를 실행합니다.

정리​

maintenance는 노드를 안전하게 멈출 수 있는 상태로 전환하는 절차입니다. 2노드에서는 primary를 wait_primary로 먼저 전환합니다. 3노드에서는 남은 quorum standby로 동기 복제를 유지합니다. primary의 maintenance는 failover를 동반합니다. 실습에서는 3.74초의 쓰기 공백이 발생했습니다.