10.2 메이저 업그레이드
patronictl에는 메이저 업그레이드 명령이 없다. pg_upgrade 실행은 Patroni 바깥의 작업이고, Patroni 쪽에는 업그레이드된 데이터 디렉토리를 새 클러스터로 다시 인식시키는 절차가 따라붙는다. pg_upgrade가 새 데이터 디렉토리를 initdb로 만들면서 PostgreSQL의 system identifier가 바뀌기 때문에, DCS에 남은 구 클러스터 상태를 지우지 않으면 Patroni가 보는 클러스터와 실제 데이터가 어긋난다.
전체 흐름
flowchart TD
A["전 노드 Patroni 정지"] --> B["primary에서 pg_upgrade"]
B --> C["patroni.yml 수정"]
C --> D["DCS initialize key 제거"]
D --> E["dynamic config 복원"]
E --> F["primary Patroni 시작"]
F --> G["standby 데이터 비우기"]
G --> H["standby Patroni 시작<br/>재복제 대기"]
절차 전체가 클러스터 정지를 전제로 한다. Patroni를 멈추는 시점부터 primary가 새 버전으로 서비스를 다시 시작할 때까지 쓰기가 중단되므로, pg_upgrade 소요 시간을 사전에 측정해 다운타임 창을 잡아야 한다.
Patroni 정지
전 노드에서 Patroni를 정지한다. 작업 도중 leader race나 자동 failover가 일어나지 않게 하기 위해서다.
primary에서 pg_upgrade
primary 노드에 새 버전 PostgreSQL 바이너리를 설치하고 pg_upgrade를 실행한다.
patroni.yml 수정
새 버전에 맞게 patroni.yml을 수정한다. 바이너리 경로(bin_dir)나 데이터 디렉토리 경로처럼 버전 번호가 들어간 값이 주 대상이다.
DCS 상태 제거
DCS에서 initialize key를 제거하거나, patronictl remove로 클러스터 상태 전체를 지운다.
dynamic configuration 복원
구 데이터 디렉토리의 patroni.dynamic.json을 새 데이터 디렉토리로 복사해 둔다. 클러스터를 다시 초기화할 때 기존 dynamic configuration이 유지된다. 선택 단계다.
primary에서 Patroni 시작
primary에서 Patroni를 시작한다. initialize key가 없으므로 Patroni는 이 노드의 데이터 디렉토리를 기준으로 클러스터를 새로 초기화한다.
standby 재구축
standby의 구 데이터 디렉토리는 비우고 재복제한다. 공식 문서는 “Running pg_upgrade on standby nodes is not supported by PostgreSQL"라고 명시한다. standby에 새 버전 바이너리를 설치하고 데이터 디렉토리를 비운 뒤 Patroni를 시작하면, replica 생성 경로(기본 pg_basebackup)로 다시 만들어진다.
복제 완료 대기
standby가 primary를 따라잡을 때까지 기다린다. patronictl list로 각 노드의 state를 확인한다.
pg_upgrade가 initdb로 새 system identifier를 만들기 때문에, DCS에 남은 구 클러스터 상태와 새 데이터 디렉토리는 더 이상 일치하지 않는다. 새로 시작하기 전에 initialize key 제거 또는 patronictl remove로 DCS 상태를 반드시 초기화한다.Kubernetes에서는: Spilo의 in-place upgrade
Kubernetes 환경이라면 Zalando Spilo 이미지의 inplace_upgrade.py가 참고 구현이다. Spilo 13 이상 이미지에 포함되어 있고, master pod 안에서 다음처럼 실행한다.
python3 /scripts/inplace_upgrade.py N # N = 클러스터 멤버 수Zalando postgres-operator를 쓰면 major_version_upgrade_mode 설정(기본 off, manual, full)으로 이 스크립트의 트리거를 제어한다. 대상 버전은 PGVERSION 환경변수 기반이다.
정리
메이저 업그레이드에서 Patroni가 대신해 주는 것은 없다. pg_upgrade와 바이너리 교체는 바깥에서 실행하고, DCS의 initialize key를 지워 새 system identifier의 클러스터로 다시 세우는 것이 절차의 뼈대다. standby는 pg_upgrade 대상이 아니므로 데이터 디렉토리를 비운 뒤 재복제로 맞춘다.