12.1 Logical Replication
physical replication이 WAL을 그대로 흘려보내 클러스터 전체를 바이트 단위로 복제한다면, logical replication은 테이블 단위의 변경을 논리적으로 골라 다른 데이터베이스로 보낸다. 복제 기준은 대개 primary key 같은 replication identity다. 덕분에 서로 다른 PostgreSQL 메이저 버전 사이에서도 복제가 되고, 필요한 테이블만 선택적으로 흘려보낼 수 있다. 온라인 마이그레이션, 무중단에 가까운 메이저 업그레이드, 데이터 분산, 실시간 분석 같은 곳에 쓴다.
PostgreSQL은 이 기능을 publish/subscribe 모델로 제공한다. 데이터를 내보내는 쪽이 publication을, 받아 적용하는 쪽이 subscription을 만든다. CloudNativePG는 이 둘을 각각 Publication·Subscription이라는 Kubernetes 리소스(CRD)로 감싸, 매니페스트로 선언해 관리하도록 한다. psql로 CREATE PUBLICATION을 직접 실행하는 대신 리소스를 apply하면 operator가 대상 클러스터에 반영한다.
flowchart TD
subgraph PUB["Publisher 클러스터"]
PT["원본 테이블"]
PUBCRD["Publication CRD"]
end
subgraph SUB["Subscriber 클러스터"]
SUBCRD["Subscription CRD"]
ST["대상 테이블"]
end
PT --> PUBCRD
PUBCRD -->|"변경 스트림"| SUBCRD
SUBCRD --> ST
EXT["externalClusters<br/>접속 정보"] -.-> SUBCRD
Publication
publication은 복제할 변경의 원천이다. 어느 클러스터의 어느 데이터베이스에서, 어떤 테이블을 대상으로 삼을지 지정한다.
apiVersion: postgresql.cnpg.io/v1
kind: Publication
metadata:
name: freddie-publisher
spec:
cluster:
name: freddie
dbname: app
name: publisher
target:
allTables: true핵심 필드는 다음과 같다.
spec.cluster.name— publication을 만들 대상 클러스터spec.dbname— publication이 생성되는 데이터베이스spec.name— PostgreSQL 안에서의 publication 이름spec.target— 포함할 테이블·변경 범위
target.allTables: true는 데이터베이스의 모든 테이블을 대상으로 삼는다. 일부만 고르려면 target.objects로 스키마나 개별 테이블을 나열한다.
spec:
target:
objects:
- tablesInSchema: portal
- table:
name: users
schema: accesspublicationReclaimPolicy는 Publication 리소스를 지웠을 때 PostgreSQL 쪽 publication을 어떻게 할지 정한다. 기본값 retain은 DB 객체를 남기고, delete는 함께 제거한다.
Subscription
subscription은 publication을 소비하는 쪽이다. publisher 데이터베이스에 접속해 변경을 받아 자기 테이블에 적용한다.
apiVersion: postgresql.cnpg.io/v1
kind: Subscription
metadata:
name: freddie-to-king-subscription
spec:
cluster:
name: king
dbname: app
name: subscriber
externalClusterName: freddie
publicationName: publisherspec.externalClusterName은 publisher를 가리키는데, 이 이름은 subscriber 클러스터 매니페스트의 externalClusters에 정의돼 있어야 한다. 접속 host·user·dbname을 여기서 준다.
externalClusters:
- name: freddie
connectionParameters:
host: freddie-rw.default.svc
user: postgres
dbname: appsubscription도 subscriptionReclaimPolicy로 삭제 동작을 retain(기본)·delete 중에 고른다.
import bootstrap을 schemaOnly: true로 써서 원본의 테이블 정의만 먼저 복사해 두는 방식이 정석이다.활용 예: 메이저 업그레이드
logical replication의 대표 활용은 서로 다른 버전 사이 마이그레이션이다. 아래는 PostgreSQL 16 클러스터 freddie에서 PostgreSQL 18 클러스터 king으로 데이터를 옮기는 흐름이다.
한계와 주의
logical replication은 몇 가지를 복제하지 않는다. 스키마와 DDL 명령, sequence 값, large object가 그렇다. 대응은 다음과 같다.
- 스키마 —
importbootstrap의schemaOnly: true로 테이블 정의를 먼저 복사한다. - sequence —
cnpg플러그인으로 원본 값에 맞춰 동기화한다.
kubectl cnpg subscription sync-sequences king --subscription=subscriber이 밖에 알아 둘 제약이다.
spec.cluster필드는 생성 후 변경 불가다. 다른 클러스터에서 관리하려면 리소스를 새로 만든다.- read-only replica cluster에서는
Publication·Subscription을 지워도 finalizer만 풀릴 뿐 실제 DB 객체는 primary cluster가 제거한다.reclaimPolicy: delete여도 그렇다.
정리
- logical replication은 테이블 단위 논리 복제 — 버전이 달라도, 일부 테이블만도 가능
- CloudNativePG는
Publication·SubscriptionCRD로 pub/sub를 선언적으로 관리 - subscriber는 스키마를 미리 갖춰야 한다 —
import+schemaOnly: true - 스키마·sequence·large object는 복제 대상이 아니다 — 별도 조치 필요
- failover 대비로 logical decoding slot synchronization를 켜 데이터 유실을 막는다
다음 절에서는 클러스터 전체를 잠시 멈추고 PostgreSQL 메이저 버전을 올리는 offline in-place 업그레이드를 본다.