4.1 Bootstrap: 클러스터 초기화
Bootstrap은 CloudNativePG가 Cluster 리소스를 받아 첫 primary 인스턴스의 데이터 디렉토리를 채우는 초기화 단계다. spec.bootstrap 섹션에 어떤 방식으로 데이터를 마련할지 선언하면, Operator가 그에 맞춰 PGDATA를 준비하고 나머지 replica는 그 primary로부터 복제해 채운다.
방식은 세 가지이며, 한 매니페스트에는 하나만 지정할 수 있다.
- initdb — 빈 데이터 디렉토리에서 완전히 새 클러스터를 만든다. 기본이자 가장 흔한 방식이다.
- recovery — 기존 물리 base backup에서 복원한다. 특정 시점으로 되돌리는 point-in-time recovery도 가능하다.
- pg_basebackup — 지금 돌고 있는 다른 PostgreSQL 인스턴스를 streaming replication으로 물리 복제해 온다.
flowchart TD
START["Cluster 생성"]
BS{"bootstrap 방식"}
INIT["initdb"]
REC["recovery"]
PBB["pg_basebackup"]
NEW["빈 PGDATA 새로 생성"]
BACKUP["object store<br/>base backup 복원"]
CLONE["원본 인스턴스<br/>물리 복제"]
READY["primary 기동"]
START --> BS
BS -->|새 클러스터| INIT --> NEW --> READY
BS -->|백업에서| REC --> BACKUP --> READY
BS -->|라이브 복제| PBB --> CLONE --> READY
postgres superuser와 데이터베이스가 항상 존재한다고 전제한다. Operator는 Unix Domain Socket의 peer authentication으로 postgres 유저에 접속해 관리 작업을 수행하기 때문이다. 이 유저와 데이터베이스는 절대 삭제하면 안 된다.initdb: 새 클러스터 만들기
initdb는 PostgreSQL 기본 명령인 initdb를 그대로 호출해 새 PGDATA를 만든다. 이 과정에서 Operator는 다음을 자동으로 처리한다.
- 새 PGDATA 디렉토리 생성
- 권한 없는 애플리케이션 유저(기본 이름
app) 생성 - Secret에서 읽은 비밀번호 설정
- 그 유저가 소유하는 애플리케이션 데이터베이스 생성
가장 기본적인 형태는 다음과 같다.
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: cluster-example-initdb
spec:
instances: 3
bootstrap:
initdb:
database: app
owner: app
secret:
name: app-secret
storage:
size: 1Gidatabase는 만들 애플리케이션 DB 이름, owner는 그 소유자 유저, secret은 소유자 비밀번호가 담긴 Secret이다. secret을 생략하면 Operator가 무작위 비밀번호로 Secret을 자동 생성한다.
자격 증명 Secret
애플리케이션 유저와 superuser의 비밀번호는 kubernetes.io/basic-auth 타입 Secret으로 전달한다.
apiVersion: v1
kind: Secret
metadata:
name: app-secret
type: kubernetes.io/basic-auth
data:
username: YXBw
password: cGFzc3dvcmQ=Secret의 username은 애플리케이션 자격 증명이면 owner 값과, superuser 자격 증명이면 postgres와 일치해야 한다.
data 아래 값은 base64로 인코딩한다. 위 예의 YXBw는 app, cGFzc3dvcmQ=는 password를 인코딩한 값이다. 쿠버네티스 Secret은 인코딩일 뿐 암호화가 아니므로, RBAC로 접근을 제한하고 필요하면 별도 암호화(예: sealed-secrets)를 함께 쓴다.initdb 옵션
initdb 호출에 넘길 옵션을 매니페스트에서 그대로 지정할 수 있다.
| 옵션 | 용도 |
|---|---|
dataChecksums | data page checksum 활성화 (I/O 손상 감지) |
encoding | template DB 인코딩 (기본 UTF8) |
locale | 전체 locale 동작 |
localeCollate | LC_COLLATE (기본 C) |
localeCType | LC_CTYPE (기본 C) |
localeProvider | locale provider (libc 또는 icu, PG 15+) |
icuLocale | ICU locale (PG 15+, localeProvider: icu 필요) |
icuRules | ICU collation 규칙 (PG 16+) |
builtinLocale | builtin locale (PG 17+) |
walSegmentSize | WAL segment 크기 |
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: cluster-example-initdb
spec:
instances: 3
bootstrap:
initdb:
database: app
owner: app
dataChecksums: true
encoding: 'LATIN1'
storage:
size: 1Giinitdb에 그대로 전달하는 프록시 역할만 한다. 값이 잘못되면 초기화가 실패하므로, PostgreSQL 문서 기준으로 조합을 확인하고 넣는다.초기화 직후 SQL 실행
클러스터 초기화가 끝난 뒤 superuser 권한으로 SQL을 자동 실행할 수 있다. 실행 대상 DB에 따라 세 지점이 있다.
- postInitSQL —
postgres데이터베이스에 실행 - postInitTemplateSQL —
template1데이터베이스에 실행 - postInitApplicationSQL — 애플리케이션 데이터베이스에 실행
각 지점은 SQL 문을 직접 나열하거나(postInitSQL 등), Secret·ConfigMap에 담긴 스크립트를 참조(postInitSQLRefs 등)할 수 있다.
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: cluster-example-initdb
spec:
instances: 3
bootstrap:
initdb:
database: app
owner: app
dataChecksums: true
localeCollate: 'en_US'
localeCType: 'en_US'
postInitSQL:
- CREATE DATABASE angus
storage:
size: 1Gi외부 스크립트를 참조하는 형태는 다음과 같다. 각 목록에서 Secret이 ConfigMap보다 먼저 처리된다.
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: cluster-example-initdb
spec:
instances: 3
bootstrap:
initdb:
database: app
owner: app
postInitApplicationSQLRefs:
secretRefs:
- name: my-secret
key: secret.sql
configMapRefs:
- name: my-configmap
key: configmap.sql
storage:
size: 1Gisearch_path인 "$user", public으로 실행되므로, 객체를 참조할 때는 스키마를 명시해 search_path에 의존하지 않게 한다.recovery: 백업에서 복원
recovery 방식은 기존 물리 base backup에서 클러스터를 복원하며, 필요하면 특정 시점으로 되돌리는 point-in-time recovery도 지원한다. 백업 저장소(object store), snapshot, WAL archiving과 엮이는 부분이 많아, 백업·복구 절차와 함께 다루는 것이 자연스럽다.
이 방식의 상세는 Part VII. 백업과 복구에서 별도로 설명한다. 여기서는 recovery가 bootstrap의 한 방식이라는 점만 짚어 둔다.
pg_basebackup: 라이브 클러스터 복제
pg_basebackup은 지금 돌고 있는 다른 PostgreSQL 인스턴스를 streaming replication으로 물리 복제해 그대로 사본을 만든다. 원본은 primary든 standby든 상관없다.
주로 다음 상황에 쓴다.
- 리포팅·BI 클러스터를 주기적으로(매일·매주) 새로 만들 때
- 테스트 DB를 주기적으로 재생성하고 익명화할 때
- 독립 replica 클러스터를 빠르게 띄울 때
- namespace나 쿠버네티스 클러스터를 넘어 물리 마이그레이션할 때
요구 조건
물리 복제이므로 원본과 대상이 다음을 만족해야 한다.
- 동일한 하드웨어 아키텍처
- 동일한 PostgreSQL major 버전
- 동일한 tablespace 구성
- 원본의
max_wal_senders가 충분할 것 (백업용 1 + WAL streaming용 1, 최소 2) - 대상→원본 방향으로 PostgreSQL 포트 접속이 열려 있을 것
- 원본에
REPLICATION LOGIN권한을 가진 role이 있고,pg_hba.conf가 대상의 접속을 허용할 것
원본에서 복제 유저는 다음처럼 만든다.
createuser -P --replication streaming_replica인증 방식
비밀번호 인증과 TLS 인증서 인증 두 가지가 있다. 운영 환경에서는 TLS 인증서 방식을 권장한다.
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: target-db
spec:
instances: 3
imageName: ghcr.io/cloudnative-pg/postgresql:18.4-system-trixie
bootstrap:
pg_basebackup:
source: source-db
storage:
size: 1Gi
externalClusters:
- name: source-db
connectionParameters:
host: source-db.foo.com
user: streaming_replica
password:
name: source-db-replica-user
key: password원본 pg_hba.conf에는 다음 항목이 필요하다(가능하면 TLS를 강제하는 형태로).
host replication streaming_replica all md5externalClusters는 외부 PostgreSQL 원본에 접근하는 방법을 정의하는 섹션으로, 복제 정보(streaming connection)나 recovery용 object store 정보를 담는다. bootstrap의 source가 이 목록의 name을 참조한다.
애플리케이션 DB 설정과 제약
복제가 끝난 뒤(replica 클러스터가 아닌 경우) 애플리케이션 DB를 설정할 수 있다.
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
spec:
bootstrap:
pg_basebackup:
database: app
owner: app
secret:
name: app-secret
source: cluster-example복제 후 Operator는 app 데이터베이스와 유저가 없으면 만들고, 소유권을 부여하고, Secret의 비밀번호로 갱신한다.
pg_basebackup은 그 시점의 스냅샷을 뜨는 방식이다. 백업 중 생성된 WAL은 대상으로 streaming되지만, 완료 순간 대상은 새 timeline으로 갈라져 원본과 독립한다. 따라서 마이그레이션 목적이라면 대상으로 전환하기 전에 원본의 모든 쓰기를 멈춰야 한다(replica 클러스터에는 해당 없음). 실제 전환 전에 절차와 애플리케이션을 반드시 테스트해 다운타임을 측정한다.정리
- bootstrap 방식은
initdb·recovery·pg_basebackup세 가지, 한 매니페스트에 하나만 initdb는 새 클러스터,recovery는 백업 복원,pg_basebackup은 라이브 물리 복제postgressuperuser·DB는 Operator 운영의 전제 — 삭제 금지- 자격 증명은
kubernetes.io/basic-authSecret으로,username은owner또는postgres와 일치 pg_basebackup은 동일 아키텍처·major 버전·tablespace가 전제이며, 전환 전 쓰기 중단과 테스트가 필수
다음 절(4.2)에서는 이미 운영 중인 기존 PostgreSQL을 논리 백업으로 가져오는 방법을 본다.