PostgreSQL repmgr 스플릿브레인 복구 가이드
PostgreSQL repmgr HA 환경에서 네트워크 단절이나 장애 처리 미흡으로 인해 두 노드가 동시에 primary role을 가지는 스플릿브레인(split-brain) 상황이 발생할 수 있습니다. 이 글은 이미 두 노드 모두 primary 상태가 되어버린 환경에서, 한 노드를 기준 Primary로 확정하고 나머지 노드를 pg_rewind + repmgr standby register로 되살리는 절차를 정리한 기술 가이드입니다.
1️⃣ 장애 상황 및 증상 정리
| 환경 | PostgreSQL + repmgr 기반 2노드 HA(Primary 1대, Standby 1대 구성) |
|---|---|
| 장애 유형 | 네트워크 단절 또는 장애 조치 과정에서 두 노드가 모두 Primary로 승격된 스플릿브레인(split-brain) 상태 |
| 사용자 시도 | repmgr standby register -f /home/petagres/repmgr.conf --force 로 Secondary를 강제로 standby로 등록하려 했으나 실패 |
| 핵심 증상 |
- repmgr cluster show 에서 두 노드 모두 primary로 표시- standby register / clone / rewind 명령이 기대대로 동작하지 않음 - 접근 방향에 따라 타임라인과 WAL LSN이 서로 다른 상태로 분기 |
단순히
repmgr standby register --force 만으로는 스플릿브레인 상태가 해결되지 않습니다.이유는 다음과 같습니다.
- 각 노드는 로컬 데이터 디렉터리와 repmgr 메타 테이블 기준으로 자신을 primary라고 인식하고 있음
- repmgr은 실제 인스턴스가 primary로 동작 중인 노드를 강제로 standby로 등록하지 않도록 설계
- 서로 다른 타임라인 / LSN을 가진 상태에서는 pg_rewind 같은 정합성 작업이 선행되지 않으면 안전한 스탠바이 전환이 불가능
2️⃣ 전체 복구 전략 개요
스플릿브레인 복구의 핵심 전략은 다음 두 가지입니다.
- 한 노드만 절대적인 Primary로 확정한다. (가장 최신 WAL LSN을 가진 노드)
- 나머지 노드를 완전히 내려서, pg_rewind로 Primary와 데이터를 맞춘 뒤 standby clone + register로 다시 붙인다.
즉, “내가 임의로 secondary로 지정하고 싶다”가 아니라, WAL LSN 기준으로 누가 최신인지 먼저 결정한 뒤, 그 기준에 맞춰 나머지를 되돌리는 절차가 필요합니다.
3️⃣ 1단계 – 진짜 Primary 노드 선택 (LSN 기준)
psql -U postgres -c "SELECT pg_wal_lsn_diff(pg_current_wal_lsn(), '0/0');"
또는 보다 자세히 보고 싶다면:
psql -U postgres -c "SELECT pg_current_wal_lsn();"
repmgr cluster show
- 여기서는 두 노드 모두
primary로 나올 수 있으므로, role 출력만 믿지 말고 LSN 값을 기준으로 최신 노드를 선택합니다.
일반적으로 더 큰 LSN 값을 가진 노드가 더 많은 트랜잭션을 반영한 상태이므로, 이 노드를 살릴 Primary로 확정합니다.
4️⃣ 2단계 – Standby로 만들 서버 중지
이제 “Secondary(standby로 만들) 노드”를 정했다면, 그 서버에서 PostgreSQL 서비스를 완전히 중지합니다.
# OS에 따라 서비스 명칭이 다를 수 있음
sudo systemctl stop postgresql-15
# 또는
sudo systemctl stop postgresql
이 시점에서 secondary 노드는 더 이상 트랜잭션을 받아서는 안 됩니다. (추가 변경이 생기면 rewind 기준이 꼬일 수 있음)
5️⃣ 3단계 – repmgr 메타데이터 정리
standby로 만들 노드에서는 repmgr 입장에서 자신을 primary로 기록해 둔 정보를 먼저 정리해야 합니다.
repmgr cluster show
② 해당 노드 unregister
repmgr standby unregister --node-id=<SECONDARY_NODE_ID> --force
- 이 작업은 repmgr 메타 테이블에서 “이 노드는 더 이상 primary/standby로 간주하지 않는다” 라고 지워주는 단계입니다.
6️⃣ 4단계 – pg_rewind 로 데이터 정합성 맞추기
스플릿브레인 해결의 핵심은 pg_rewind 입니다. 이미 분기된 타임라인을 선택한 Primary 노드의 히스토리에 맞게 secondary를 되돌려야 합니다.
pg_rewind \
--target-pgdata=/var/lib/pgsql/15/data \
--source-server="host=<PRIMARY_IP> user=repmgr dbname=repmgr"
--target-pgdata: 되돌릴 대상(secondary)의 데이터 디렉터리--source-server: 기준이 되는 Primary 서버의 접속 정보
FATAL: WAL log hints are disabled→ wal_log_hints = on 필요- 또는 data checksums 활성화 필요(클러스터 초기화 시 결정)
# postgresql.conf (Primary)
wal_log_hints = on
# 설정 후 Primary 재시작
sudo systemctl restart postgresql-15
7️⃣ 5단계 – repmgr를 통한 standby clone (필요 시)
환경에 따라 pg_rewind 로 충분히 정리되기도 하지만, 스플릿브레인 이후 설정이 꼬여 있거나 재구성이 더 깔끔한 경우 repmgr standby clone 으로 전체를 다시 받는 것이 안전합니다.
repmgr standby clone --force /home/petagres/repmgr.conf
- recovery 관련 설정(
primary_conninfo등)은 repmgr가 자동으로 생성합니다. - 기존 데이터 디렉터리를 덮어쓰는 구조이므로, 꼭 Primary 선택이 올바른지 확인 후 실행해야 합니다.
8️⃣ 6단계 – PostgreSQL 기동 및 standby register
secondary 노드의 데이터 정리가 끝났다면 서비스를 다시 올립니다.
sudo systemctl start postgresql-15
# 서비스 상태 확인
sudo systemctl status postgresql-15
이제 repmgr 관점에서 해당 노드를 standby 로 다시 등록합니다.
repmgr standby register -f /home/petagres/repmgr.conf
- 이전에는 노드가 primary 로 동작 중이어서 register 가 거부되거나 noop 이었지만, 이제는 standby 모드 + Primary 에 연결된 상태이므로 정상 동작합니다.
9️⃣ 7단계 – 최종 클러스터 상태 확인
repmgr cluster show
정상적인 출력 예시는 다음과 같습니다.
ID | Name | Role | Status | Upstream | Connection
----+--------+---------+-----------+----------+-----------
1 | node1 | primary | running | |
2 | node2 | standby | running | node1 | conninfo...
이 상태라면 스플릿브레인 상황은 해소되었고, 하나의 Primary와 하나의 Standby 구조로 되돌아온 것입니다.
🔍 왜 standby register --force 만으로는 안 되는가?
repmgr standby register --force 만으로 해결되지 않는 이유는 구조적으로 다음과 같습니다.
- 현재 노드가 PostgreSQL 입장에서 primary 모드로 동작 중이면, repmgr은 standby 등록을 거부합니다.
- repmgr은 단순 설정 파일이 아니라, 데이터 디렉터리의
pg_control정보를 함께 참고하여 그 인스턴스가 primary 인지 standby 인지를 판별합니다. - split-brain 이후에는 서로 다른 타임라인과 WAL LSN을 가지게 되므로, pg_rewind 같은 정합성 맞추기 작업 없이 standby로 강제 등록하는 것은 데이터 손상을 야기할 수 있습니다.
따라서,
pg_rewind 없이, 그리고 해당 인스턴스를 실제로 standby 모드로 바꾸지 않은 상태에서는repmgr standby register --force 만으로는 스플릿브레인을 해결할 수 없습니다.
🔐 7️⃣ 기본 오류 대응 4단계 (공통 보안 관점 체크리스트)
DB 스플릿브레인 복구와 별개로, 서비스 장애·구성 꼬임이 발생했을 때 항상 함께 점검해야 할 공통 보안 체크리스트입니다.
- 외부 노출 여부 확인 - DB 포트(예: 5432)가 불필요하게 외부(인터넷)에 노출되어 있지 않은지 확인 - 방화벽 / 보안 그룹 / 로드밸런서 설정 재점검
- 역할(서비스) 비활성화 - 장애 노드, 잘못 승격된 노드의 서비스 중지 - 장애 처리 중인 노드에 대한 모니터링 알람 일시 조정
- 포트·접속 차단 - 관리 중인 구간 외부에서의 직접 DB 접속 차단 - 필요 시 임시 ACL 정책 적용 (Jump 서버나 Bastion만 허용)
- 로그 모니터링 및 사후 분석 - PostgreSQL 로그, repmgr 로그, 시스템 로그(journal)를 함께 분석 - 동일 증상이 재발하지 않도록 장애 재현 & 재발 방지 대책 수립
'지식 공유 > DBMS' 카테고리의 다른 글
| [ORACLE] ORA-00257 Archive Error & ORA-15041 RECO Disk Full 장애 (1) | 2025.11.17 |
|---|---|
| [ORACLE] 19c·23ai TDE란? 개념, 적용 방법, 활용 범위 (1) | 2025.11.17 |
| [ORACLE] 11g to 19c Non-CDB 마이그레이션 (expdp/impdp) (1) | 2025.11.17 |
| [ORACLE] 11g · 12c · 19c · 21c Silent 모드 설치 가이드 (1) | 2025.11.17 |
| [ORACLE] DBCA 설치 2% 멈춤 · ORA-27124 해결 가이드 (0) | 2025.11.17 |
