본문으로 건너뛰기
12.2 PostgreSQL 메이저 업그레이드

12.2 PostgreSQL 메이저 업그레이드

PostgreSQL은 메이저 버전이 바뀌면 내부 데이터 저장 포맷이 달라진다. 그래서 minor 업데이트처럼 이미지만 갈아 끼워서는 안 되고, 데이터 디렉토리를 새 포맷으로 변환하는 절차가 필요하다. CloudNativePG는 이 변환을 세 방식으로 지원한다. logical dump/restore, logical replication, 그리고 pg_upgrade를 쓰는 물리 업그레이드다. 이 절은 그중 클러스터를 잠시 멈추고 제자리에서 올리는 offline in-place 업그레이드를 다룬다.

방아쇠는 단순하다. 클러스터에 지정한 operand 이미지를 더 높은 메이저 버전으로 바꾸면 operator가 업그레이드가 필요하다고 판단하고, pg_upgrade로 데이터 디렉토리를 변환한다.

spec:
  imageName: ghcr.io/cloudnative-pg/postgresql:18-minimal-trixie

image catalog를 쓰는 클러스터라면 catalog의 major 버전을 올려도 같은 결과가 된다.

    flowchart TD
  TRIGGER["이미지 major 상향"] --> DOWN["전체 Pod 종료"]
  DOWN --> REC["이전 버전 기록<br/>pgDataImageInfo"]
  REC --> JOB["major-upgrade Job"]
  JOB --> PGU["pg_upgrade --link"]
  PGU --> PRI["primary 재기동"]
  PRI --> RECLONE["replica 재복제"]
  

업그레이드 흐름

operator가 새 메이저 이미지를 감지하면 다음 순서로 진행한다.

### 전체 종료 데이터 일관성을 위해 클러스터의 모든 Pod가 종료된다. 이 시점부터 업그레이드가 끝날 때까지 primary·replica 모두 접속 불가다. ### 이전 버전 기록 직전 PostgreSQL 버전을 `.status.pgDataImageInfo`에 남긴다. 롤백 판단의 기준이 된다. ### 업그레이드 Job 실행 `-major-upgrade` 이름의 Job이 생성된다. 이 Job은 바이너리와 데이터 파일의 정합성을 확인하고, `PGDATA`·WAL·tablespace용 새 디렉토리를 만든 뒤 `pg_upgrade`를 `--link` 옵션으로 실행하고, 원본 디렉토리를 변환된 것으로 교체한다. ### primary 재기동, replica 재복제 업그레이드가 끝나면 primary Pod가 새 버전으로 재기동된다. replica의 PVC는 폐기되고, 업그레이드된 primary로부터 다시 clone된다.
replica 재복제는 데이터베이스가 크면 오래 걸린다. 큰 클러스터일수록 업그레이드 뒤 replica가 다시 붙어 HA가 회복되기까지의 시간을 넉넉히 잡는다.

전제와 제약

  • 같은 OS 배포판 사이만 — 이미지의 기반 OS가 같아야 한다. 예를 들어 bullseye에서 bookworm 이미지로는 메이저 업그레이드를 할 수 없다.
  • extension 호환성은 직접 확인 — CloudNativePG는 extension 호환성을 관리하지 않는다. source·target 이미지의 extension이 업그레이드 경로를 지원하는지 미리 검증한다.
  • PostgreSQL 17.0–17.5 버그max_slot_wal_keep_size-1이 아니면 업그레이드가 실패하는 알려진 문제가 있다. 17.6 이상으로 먼저 올리거나, 업그레이드 동안만 이 값을 -1로 둔다.

롤백

업그레이드가 실패하면 클러스터 설정의 이미지를 이전 메이저 버전으로 되돌린다. operator가 롤백을 감지해 실패한 업그레이드 Job을 자동으로 지우고, 원래 버전으로 클러스터를 재기동한다. 데이터 손실은 없다.

백업과 WAL archive 주의

pg_upgrade는 새 System ID를 만들고 timeline을 1로 리셋한다. 이 때문에 몇 가지가 뒤엉킨다.

  • 새 timeline 1 파일이 기존 클러스터의 timeline 1 파일과 충돌한다.
  • WAL·백업 archive에 버전이 섞인다.
메이저 버전 경계를 넘는 point-in-time recovery(PITR)는 불가능하다. 업그레이드 이전에 받은 백업으로는 업그레이드 이후 시점으로 복구할 수 없다. 업그레이드 직후 새 baseline 백업을 반드시 받는다.

archive가 섞이지 않게 하려면 이미지와 함께 archive 경로를 분리한다. Barman Cloud plugin이라면 imageNameserverName을 같이 바꿔, 옛 archive를 보존하면서 새 클러스터가 별도 경로에 쓰도록 한다.

spec:
  imageName: ghcr.io/cloudnative-pg/postgresql:18-minimal-trixie
  plugins:
    - name: plugin-barman-cloud
      enabled: true
      parameters:
        destinationPath: s3://my-bucket/
        serverName: cluster-example-pg18   # 이전엔 -pg16

업그레이드 후 작업

  • 모든 데이터베이스에 ANALYZE를 실행한다. pg_upgrade는 optimizer 통계를 넘기지 않으므로, 통계가 빌 때까지 실행 계획이 나빠질 수 있다.
  • extension 갱신이 필요하면 operator 로그에서 update_extensions.sql 스크립트 경로를 확인하고, postgres superuser로 실행한다.

정리

  • 이미지의 major 버전을 올리면 operator가 pg_upgrade 기반 offline 업그레이드를 시작
  • 흐름: 전체 종료 → 버전 기록 → major-upgrade Job(pg_upgrade --link) → primary 재기동 → replica 재복제
  • 업그레이드 내내 클러스터 전체가 다운 — 다운타임을 감당할 수 있을 때만 선택
  • 전제: 같은 OS 배포판, extension 호환성 사전 검증
  • 실패 시 이미지를 되돌리면 operator가 자동 롤백
  • 업그레이드는 timeline을 리셋 — 직후 새 baseline 백업 필수, 경계 넘는 PITR 불가
  • 끝나면 ANALYZE로 통계 재수집

다음 절에서는 공간 데이터를 다루는 PostGIS 확장을 CloudNativePG에서 쓰는 법을 본다.