부트스트랩(Bootstrap)
새 PostgreSQL 클러스터를 만드는 방법과 그 설계 근거를 살펴볼게요. 크게 initdb(처음부터), recovery(물리 기본 백업), pg_basebackup(라이브 클러스터 클로닝) 세 가지 방식이 있어요.
출처: 문서
본문
이 섹션은 새 PostgreSQL 클러스터를 만드는 데 사용할 수 있는 옵션과 그 설계 근거를 설명해요. 새 클러스터를 부트스트랩하는 주요 방법은 두 가지가 있어요:
- 처음부터 (
initdb) - 기존 PostgreSQL 클러스터에서, 직접(
pg_basebackup) 또는 물리적 기본 백업을 통한 간접(recovery) 방식으로
initdb 부트스트랩은 기존 PostgreSQL 클러스터에서 하나 이상의 데이터베이스를 가져오는 옵션도 제공해요. Kubernetes 외부에 있거나 다른 메이저 버전의 PostgreSQL을 실행 중이어도 돼요. 이 기능에 대한 더 자세한 정보는 "Importing Postgres databases" 섹션을 참고하세요.
:::info[Important] 기존 클러스터에서 부트스트랩하면 **복제 클러스터(replica cluster)**를 만들 수 있어요. 이는 지속적인 복구 상태에 남아 소스 클러스터와 동기화되고 읽기 전용 연결을 받아들이는 독립적인 PostgreSQL 클러스터예요. 자세한 내용은 Replica Cluster 섹션을 참고하세요. :::
:::warning
CloudNativePG는 postgres 사용자와 데이터베이스가 항상 존재할 것을 요구해요. 로컬 Unix Domain Socket을 사용해 peer 인증으로 postgres 사용자로서 postgres 데이터베이스에 연결해 클러스터의 관리 작업을 수행해야 해요.
postgres 사용자나 postgres 데이터베이스를 삭제하지 마세요!!!
:::
:::info
CloudNativePG는 백업 및 복구 작업의 증분 및 차등 복사를 위해 기본 스토리지 클래스가 지원하는 경우 Kubernetes 네이티브 VolumeSnapshot API 지원을 점진적으로 도입하고 있어요. 자세한 내용은 "Recovery from Volume Snapshot objects"를 참고하세요.
:::
bootstrap 섹션
bootstrap 메서드는 클러스터 사양의 bootstrap 섹션에 정의할 수 있어요. CloudNativePG는 현재 다음 부트스트랩 메서드를 지원해요:
initdb: 새 PostgreSQL 클러스터 초기화 (기본값)recovery: 기존 클러스터의 기본 백업에서 복원하고, 필요 시 사용 가능한 모든 WAL 파일 또는 특정 시점까지 재생해 PostgreSQL 클러스터 생성pg_basebackup: 스트리밍 복제 프로토콜을 통해pg_basebackup을 사용해 같은 메이저 버전의 기존 클러스터를 클로닝해 PostgreSQL 클러스터 생성. 이 방법은 데이터베이스를 CloudNativePG로 마이그레이션하는 데 특히 유용하지만, 모든 요구사항을 충족하는 것은 까다로울 수 있어요.pg_basebackup하위 섹션의 경고를 꼭 주의 깊게 검토하세요.
매니페스트에는 부트스트랩 메서드 하나만 지정할 수 있어요. 여러 부트스트랩 메서드를 정의하려고 하면 검증 오류가 발생해요.
initdb 메서드와 달리 recovery와 pg_basebackup은 다른 클러스터(오프라인 또는 온라인)를 기반으로 새 클러스터를 만들며 복제 클러스터를 띄우는 데 사용할 수 있어요. 둘 다 외부 클러스터(externalClusters)의 정의에 의존해요. 자세한 내용은 replica cluster 섹션을 참고하세요.
CloudNativePG 오퍼레이터가 recovery에 제공하는 백업 방법과 백업 스토리지 조합의 양이 많으므로, 각 방법에 대한 지침은 전용 "Recovery" 섹션을 참고하세요.
:::note[API reference]
자세한 내용은 "API reference for the bootstrap section을 참고하세요.
:::
externalClusters 섹션
클러스터 매니페스트의 externalClusters 섹션은 소스로 하나 이상의 PostgreSQL 클러스터에 대한 접근을 구성하는 데 사용할 수 있어요. 주요 사용 사례는 다음과 같아요:
- 데이터베이스 가져오기:
initdb부트스트랩 메서드의 일부로 논리적 백업 및 복원을 통한 데이터베이스 가져오기 중에 사용할 외부 소스를 지정. - 교차 리전 복제: 서로 다른 Kubernetes 클러스터 또는 기존 VM/베어메탈 환경으로 확장할 수 있는 물리적 복제를 사용하는 교차 리전 PostgreSQL 클러스터 정의.
- 물리적 기본 백업에서 복구: 물리적 기본 백업을 참조해 PostgreSQL 클러스터를 전체적으로 또는 특정 시점(Point-In-Time)에 복구.
:::info
지속적인 개발이 externalClusters의 기능을 확장해 향후 릴리스에서 논리적 복제 및 외부 서버(foreign server) 같은 추가 사용 사례를 수용할 거예요.
:::
부트스트랩과 관련해 externalClusters는 pg_basebackup 메서드 또는 recovery 메서드의 소스 PostgreSQL 클러스터를 정의하는 데 사용할 수 있어요. 외부 클러스터는 다음을 가져야 해요:
-
source옵션으로 참조할 외부 클러스터를 식별하는 이름 -
다음 중 적어도 하나:
- 스트리밍 연결에 대한 정보
- **복구 오브젝트 스토어(recovery object store)**에 대한 정보. 이는 Barman Cloud 호환 오브젝트 스토어로 다음을 포함해요:
- WAL 아카이브 (Point In Time Recovery에 필요)
- Postgres 클러스터의 물리적 기본 백업 카탈로그
:::note 복구 오브젝트 스토어는 보통 Barman Cloud가 관리하는 AWS S3, Azure Blob Storage, 또는 Google Cloud Storage 소스예요. :::
스트리밍 연결만 정의되면 소스는 pg_basebackup 메서드에 사용할 수 있어요. 복구 오브젝트 스토어만 정의되면 소스는 recovery 메서드에 사용할 수 있어요. 둘 다 정의되면 두 부트스트랩 메서드 중 하나를 선택할 수 있어요. 다음 표는 옵션을 요약해요:
| Content of externalClusters | pg_basebackup | recovery |
|---|---|---|
| Only streaming | ✓ | |
| Only object store | ✓ | |
| Streaming and object store | ✓ | ✓ |
또한 pg_basebackup 또는 전체 recovery 시점의 경우 클러스터는 복제 클러스터 모드에 적격이에요. 즉 클러스터가 스트리밍, PostgreSQL의 restore_command를 통한 WAL 시핑, 또는 둘 중 하나를 통해 소스에서 지속적으로 공급받는다는 뜻이에요.
:::note[API reference]
자세한 내용은 "API reference for the externalClusters section을 참고하세요.
:::
패스워드 파일
externalClusters 항목 내에 패스워드가 제공되면 CloudNativePG는 각 인스턴스의 /controller/external/NAME/pgpass에 위치한 PostgreSQL 패스워드 파일을 자율적으로 관리해요.
이 접근 방식은 CloudNativePG가 연결 문자열에 패스워드를 노출하지 않고 외부 서버와 안전하게 연결을 설정할 수 있게 해줘요. 대신 연결은 passfile 연결 파라미터를 통해 앞서 언급한 파일을 안전하게 참조해요.
빈 클러스터 부트스트랩 (initdb)
initdb 부트스트랩 메서드는 처음부터 새 PostgreSQL 클러스터를 만드는 데 사용돼요. 달리 지정하지 않으면 기본값이에요.
다음 예시는 initdb 구성의 전체 구조를 포함해요:
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: 1Gi
위 부트스트랩 예시는:
- PostgreSQL 네이티브
initdb명령을 사용해 새PGDATA폴더 생성 app이라는 비특권(unprivileged) 사용자 생성app-secret시크릿의 값으로 후자(app)의 패스워드 설정 (username이owner와 같은 이름인지 확인)app사용자가 소유한app이라는 데이터베이스 생성
convention over configuration 패러다임 덕분에 오퍼레이터가 기본 데이터베이스 이름(app)과 기본 애플리케이션 사용자 이름(데이터베이스 이름과 동일)을 선택하게 하고, PostgreSQL의 수퍼유저와 애플리케이션 사용자 모두에 대해 보안 패스워드를 무작위 생성하게 할 수 있어요.
대안으로 패스워드를 직접 생성해 시크릿으로 저장하고 위의 예시처럼 PostgreSQL 클러스터에서 사용할 수 있어요.
제공되는 시크릿은 kubernetes.io/basic-auth 타입의 사양을 따라야 해요. 결과적으로 시크릿의 username은 (애플리케이션 시크릿의 경우) owner와 일치해야 하고, 수퍼유저의 경우 postgres와 일치해야 해요.
다음은 basic-auth 시크릿의 예시예요:
apiVersion: v1
data:
username: YXBw
password: cGFzc3dvcmQ=
kind: Secret
metadata:
name: app-secret
type: kubernetes.io/basic-auth
애플리케이션 데이터베이스는 애플리케이션 데이터를 저장하는 데 사용해야 하는 데이터베이스예요. 애플리케이션은 애플리케이션 데이터베이스를 소유한 사용자로 클러스터에 연결해야 해요.
:::info[Important] 추가 사용자를 만들어야 한다면 "Declarative database role management"을 참고하세요. :::
데이터베이스 이름을 제공하지 않으면 오퍼레이터는 관례에 따라 진행해 app 데이터베이스를 만들고 defaulting webhook을 사용해 클러스터 정의에 추가해요. 데이터베이스를 소유한 사용자는 기본적으로 데이터베이스 이름이 돼요.
애플리케이션 사용자는 오퍼레이터가 내부적으로 사용하지 않아요. 오퍼레이터는 수퍼유저에 의존해 클러스터를 원하는 상태와 정합성 조정해요.
initdb에 옵션 전달하기
PostgreSQL 데이터 디렉터리는 initdb PostgreSQL 명령을 사용해 초기화돼요.
CloudNativePG는 initdb의 동작을 커스터마이즈해 기본 로케일 구성과 데이터 체크섬 같은 설정을 수정할 수 있게 해줘요.
:::warning
CloudNativePG는 PostgreSQL의 로케일 지원에 대한 현재 진행 중이고 중요한 개선 사항 때문에 로케일 관련 옵션에 대해 initdb의 직접 프록시로만 동작해요. PostgreSQL 문서를 따라 올바른 옵션을 제공하고 부트스트랩 프로세스가 성공적으로 완료되는지 확인하는 것은 사용자 책임이에요.
:::
initdb 명령에 커스텀 옵션을 포함하려면 다음 파라미터를 사용할 수 있어요:
builtinLocale
: builtinLocale에 값이 설정되면 CloudNativePG는 이를 initdb의 --builtin-locale 옵션에 전달해요. 이 옵션은 PostgreSQL 문서의 "Locale Support"에 정의된 대로 내장 로케일을 제어해요 (기본값: empty). 이 옵션은 localeProvider가 builtin으로 설정되어야 합니다. PostgreSQL 17부터 사용 가능해요.
dataChecksums
: 데이터 체크섬은 달리 조용히 지나칠 수 있는 데이터 페이지의 손상을 감지하는 데 도움을 줘요. 데이터 체크섬이 기본으로 활성화된 PostgreSQL 18부터 dataChecksums를 false로 설정하면 CloudNativePG가 initdb에 --no-data-checksums 옵션을 전달해 비활성화해요. PostgreSQL 18 이전 버전에서는 dataChecksums를 true로 설정하면 CloudNativePG가 initdb에 --data-checksums 옵션을 전달해 활성화해요. 설정하지 않으면 사용 중인 PostgreSQL 버전의 initdb 기본값이 적용돼요.
encoding
: encoding에 값이 설정되면 CloudNativePG는 이를 initdb의 --encoding 옵션에 전달하며, 이는 템플릿 데이터베이스의 인코딩을 선택해요 (기본값: UTF8).
icuLocale
: icuLocale에 값이 설정되면 CloudNativePG는 이를 initdb의 --icu-locale 옵션에 전달해요. 이 옵션은 PostgreSQL 문서의 "Locale Support"에 정의된 대로 ICU 로케일을 제어해요 (기본값: empty). 이 옵션은 localeProvider가 icu로 설정되어야 합니다. PostgreSQL 15부터 사용 가능해요.
icuRules
: icuRules에 값이 설정되면 CloudNativePG는 이를 initdb의 --icu-rules 옵션에 전달해요. 이 옵션은 PostgreSQL 문서의 "Locale Support"에 정의된 대로 ICU 로케일을 제어해요 (기본값: empty). 이 옵션은 localeProvider가 icu로 설정되어야 합니다. PostgreSQL 16부터 사용 가능해요.
locale
: locale에 값이 설정되면 CloudNativePG는 이를 initdb의 --locale 옵션에 전달해요. 이 옵션은 PostgreSQL 문서의 "Locale Support"에 정의된 대로 로케일을 제어해요. 기본적으로 locale 파라미터는 비어 있어요. 이 경우 LANG 같은 환경 변수가 로케일을 결정하는 데 사용돼요. 이 변수들은 컨테이너 이미지마다 다를 수 있어 일관되지 않은 동작을 초래할 수 있음을 유의하세요.
localeCollate
: localeCollate에 값이 설정되면 CloudNativePG는 이를 initdb의 --lc-collate 옵션에 전달해요. 이 옵션은 PostgreSQL 문서의 "Locale Support"에 정의된 대로 정렬 순서(LC_COLLATE 하위 범주)를 제어해요 (기본값: C).
localeCType
: localeCType에 값이 설정되면 CloudNativePG는 이를 initdb의 --lc-ctype 옵션에 전달해요. 이 옵션은 PostgreSQL 문서의 "Locale Support"에 정의된 대로 정렬 순서(LC_CTYPE 하위 범주)를 제어해요 (기본값: C).
localeProvider
: localeProvider에 값이 설정되면 CloudNativePG는 이를 initdb의 --locale-provider 옵션에 전달해요. 이 옵션은 PostgreSQL 문서의 "Locale Support"에 정의된 대로 로케일 프로바이더를 제어해요 (기본값: empty, PostgreSQL에서 libc를 의미). PostgreSQL 15부터 사용 가능해요.
walSegmentSize
: walSegmentSize에 값이 설정되면 CloudNativePG는 이를 initdb의 --wal-segsize 옵션에 전달해요 (기본값: 설정 안 됨 — PostgreSQL에 의해 16 메가바이트로 정의).
:::note
CloudNativePG가 initdb 부트스트랩 중 구현하는 유일한 두 로케일 옵션은 LC_COLLATE와 LC_TYPE 하위 범주에 대한 것이에요. 나머지 로케일 하위 범주는 PostgreSQL 구성에서 lc_messages, lc_monetary, lc_numeric, lc_time 파라미터를 사용해 직접 구성할 수 있어요.
:::
다음 예시는 데이터 체크섬을 활성화하고 기본 인코딩을 LATIN1로 설정해요:
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: 1Gi
:::warning
CloudNativePG는 options 하위 섹션을 사용해 initdb 호출 동작을 커스터마이즈하는 또 다른 방법을 지원해요. 하지만 오퍼레이터의 동작을 깨뜨릴 수 있는 옵션(--auth 또는 -d 같은)이 있으므로, 이 기법은 deprecated이며 향후 API 버전에서 제거될 거예요.
:::
초기화 후 쿼리 실행
클러스터가 생성되고 구성된 직후에 한 번 실행될 커스텀 쿼리 목록을 지정할 수 있어요. 이 쿼리들은 수퍼유저(postgres)로 다음 세 가지 다른 데이터베이스에 대해 이 특정 순서로 실행돼요:
postgres데이터베이스 (postInit섹션)template1데이터베이스 (postInitTemplate섹션)- 애플리케이션 데이터베이스 (
postInitApplication섹션)
이 각 섹션에 대해 CloudNativePG는 커스텀 쿼리를 지정하는 두 가지 방법을 제공하며, 다음 순서로 실행돼요:
- 클러스터 정의의 SQL 쿼리 목록 (
postInitSQL,postInitTemplateSQL,postInitApplicationSQLstanza) - 각각 실행할 SQL 스크립트를 포함하는 시크릿 및/또는 ConfigMap 목록 (
postInitSQLRefs,postInitTemplateSQLRefs,postInitApplicationSQLRefsstanza). 시크릿이 ConfigMap보다 먼저 처리돼요.
각 목록의 오브젝트는 순차적으로 처리돼요.
:::warning
쿼리가 수퍼유저로 실행되어 전체 클러스터를 방해할 수 있으므로 postInit, postInitTemplate, postInitApplication 옵션을 극도로 주의해서 사용하세요. 그 쿼리 중 하나의 오류는 부트스트랩 단계를 중단시켜 클러스터를 불완전한 상태로 남기고 수동 개입이 필요하게 됩니다.
:::
:::note
이 쿼리들은 보안상의 이유로 오퍼레이터가 발행한 연결이 고정된 search_path를 고정하더라도 표준 "$user", public search_path로 실행돼요. 자세한 내용은 Schema resolution and search_path hardening을 참고하세요. search_path와 무관하게 만들려면 오브젝트 참조를 스키마로 한정하세요.
:::
:::info[Important]
postInitSQLRefs, postInitTemplateSQLRefs, postInitApplicationSQLRefs에 지정된 ConfigMap 또는 시크릿 안에 항목이 존재하는지 확인하세요. 그렇지 않으면 부트스트랩이 실패해요. 그 SQL 파일 중 하나라도 오류가 있으면 부트스트랩 단계가 성공적으로 완료되지 못해요.
:::
다음 예시는 postInitSQL stanza의 일부로 단일 SQL 쿼리를 실행해요:
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
아래 예시는 postInitApplicationSQLRefs에 의존해 초기화 후 애플리케이션 데이터베이스에서 실행할 쿼리를 포함하는 시크릿과 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: 1Gi
:::note
SQL 스크립트 내에서 각 SQL 문은 PostgreSQL 의미론에 따라 서버에서 단일 exec로 실행돼요. 주석은 포함할 수 있지만 psql 같은 내부 명령은 포함할 수 없어요.
:::
다른 클러스터에서 부트스트랩
CloudNativePG는 같은 메이저 버전의 다른 클러스터에서 시작해 클러스터를 부트스트랩할 수 있게 해줘요. 이 작업은 스트리밍 복제(pg_basebackup)로 소스 클러스터에 직접 연결하거나, 기존 물리적 기본 백업(recovery)을 통해 간접적으로 수행할 수 있어요.
소스 클러스터는 externalClusters 섹션에 정의되어야 하며, name으로 식별돼요(원본 클러스터와 같은 name을 사용할 것을 권장해요).
:::info[Important]
기본적으로 recovery 메서드는 externalClusters 섹션의 클러스터 name을 오브젝트 스토어 내 백업 데이터의 메인 폴더를 찾는 데 엄격하게 사용해요. 이 이름은 보통 서버 이름으로 예약돼요. 백업 플러그인은 다른 이름을 지정할 방법을 제공해요. 예를 들어 Barman Cloud Plugin은 serverName 파라미터를 제공해요(기본적으로 외부 클러스터 정의의 name 값에 할당).
:::
백업에서 부트스트랩 (recovery)
CloudNativePG 오퍼레이터가 recovery를 위해 제공하는 다양한 백업 방법과 백업 스토리지 옵션 조합을 고려해, 각 방법에 대한 자세한 지침은 전용 "Recovery" 섹션을 참고하세요.
라이브 클러스터에서 부트스트랩 (pg_basebackup)
pg_basebackup 부트스트랩 모드는 유효한 스트리밍 복제 연결을 사용해 CloudNativePG가 관리하는 기존 바이너리 호환 PostgreSQL 인스턴스(source)의 정확한 물리적 복사본으로 새 클러스터(target)를 만들 수 있게 해줘요. 소스 인스턴스는 PostgreSQL 서버의 프라이머리 또는 스탠바이일 수 있어요. PostgreSQL 물리적 복제의 장단점이 완전히 적용되므로 아래 요구사항 섹션을 철저히 검토하는 것이 중요해요.
이 방법의 주요 사용 사례는 다음과 같아요:
- 주기적으로 (일별, 주별) 재생성해야 하는 리포팅 및 비즈니스 인텔리전스 클러스터
- 라이브 데이터를 포함하고 주기적인 재생성(일별, 주별, 월별)과 익명화가 필요한 테스트 데이터베이스
- 독립형 복제 클러스터의 신속한 스핀업
- CloudNativePG 클러스터를 다른 네임스페이스나 Kubernetes 클러스터로의 물리적 마이그레이션
:::info[Important] Kubernetes 외부의 기존 PostgreSQL 클러스터를 CloudNativePG로 마이그레이션하는 데 물리적 복제에 기반한 이 방법을 사용하지 마세요. 모든 요구사항이 충족되고 작업이 철저히 테스트되었다고 완전히 확신하는 경우가 아니라면요. CloudNativePG 커뮤니티는 이러한 사용 사례에 이 접근 방식을 권장하지 않으며, 논리적 가져오기(import)를 사용할 것을 권장해요. 물리적 복제의 모든 요구사항이 CloudNativePG와 원활하게 동작하는 방식으로 충족되는 경우는 극히 드물어요. :::
:::warning 현재 구현에서 이 방법은 소스 PostgreSQL 인스턴스를 클로닝해 스냅샷을 만들어요. 클로닝 프로세스가 끝나면 새 클러스터가 즉시 시작돼요. 자세한 내용은 "Current limitations"를 참고하세요. :::
recovery 부트스트랩 메서드와 유사하게, 클로닝 작업이 완료되면 오퍼레이터는 첫 번째 인스턴스부터 대상 클러스터의 완전한 소유권을 갖게 돼요. 여기에는 CloudNativePG가 요구하는 특정 구성 파라미터 오버라이드, 수퍼유저 패스워드 재설정, streaming_replica 사용자 생성, 복제본 관리 등이 포함돼요. 결과 클러스터는 소스 인스턴스와 독립적으로 동작해요.
:::info[Important] 대상과 소스 인스턴스 사이의 네트워크 연결 구성은 특정 컨텍스트와 환경에 크게 의존하므로 CloudNativePG 문서의 범위 밖이에요. :::
대상 인스턴스의 스트리밍 복제 클라이언트는 pg_basebackup이 투명하게 관리하며, 소스 인스턴스에서 다음 방법 중 하나로 인증할 수 있어요:
두 인증 방법 모두 아래에 자세히 설명돼요.
요구사항
pg_basebackup 부트스트랩 메서드에는 다음 요구사항이 적용돼요:
- 대상과 소스는 같은 하드웨어 아키텍처여야 해요
- 대상과 소스는 같은 PostgreSQL 메이저 버전이어야 해요
- 대상과 소스는 같은 테이블스페이스여야 해요
- 소스는 이 일회성 작업에 대상의 접근을 허용하기 위해 백업용 walsender 하나와 WAL 스트리밍용 하나를 최소한 제공하도록 충분한
max_wal_senders로 구성되어야 해요 - 소스와 대상 사이의 네트워크는 대상 인스턴스가 소스 인스턴스의 PostgreSQL 포트에 연결할 수 있게 구성되어야 해요
- 소스에는
REPLICATION LOGIN권한이 있는 역할이 있어야 하며, 가급적 TLS를 통해(아래 "About the replication user" 참고)pg_hba.conf에서 대상 인스턴스의 이 역할 연결을 받아들여야 해요 - 대상은
REPLICATION LOGIN권한이 있는 역할로 소스 PostgreSQL 인스턴스에 성공적으로 연결할 수 있어야 해요
:::note[Seealso]
자세한 내용은 PostgreSQL 문서의 Warm Standby의 "Planning" 섹션, pg_basebackup 페이지, 그리고 "High Availability, Load Balancing, and Replication" 장을 참고하세요.
:::
복제 사용자에 대해
요구사항 섹션에서 설명했듯이, 소스 인스턴스에 SUPERUSER 또는 가급적 REPLICATION 권한만 가진 사용자가 필요해요.
소스 데이터베이스가 CloudNativePG로 생성된 경우 streaming_replica 사용자를 재사용하고 클라이언트 TLS 인증서 인증을 활용할 수 있어요(기본적으로 streaming_replica의 유일한 허용 연결 방법이에요).
Kubernetes 외부를 포함한 다른 모든 경우에는 REPLICATION 권한이 있는 사용자가 이미 있는지 확인하거나 아래 지침에 따라 새로 만드세요.
소스 시스템의 postgres 사용자로 다음을 실행하세요:
createuser -P --replication streaming_replica
프롬프트에서 패스워드를 입력하고 나중을 위해 저장하세요. 대상 인스턴스의 시크릿에 추가해야 하기 때문이에요.
:::note
이름은 중요하지 않지만, 단순함을 위해 streaming_replica를 사용할게요. 다음 섹션의 지침을 조정하면 원하는 대로 자유롭게 변경할 수 있어요.
:::
사용자 이름/패스워드 인증
CloudNativePG가 pg_basebackup 부트스트랩과 함께 지원하는 첫 번째 인증 방법은 사용자 이름과 패스워드 일치를 기반으로 해요.
절차를 시작하기 전에 다음 정보가 있는지 확인하세요:
- 호스트 이름 또는 IP 주소와 TCP 포트로 식별되는 소스 인스턴스의 위치
- 복제 사용자 이름 (단순함을 위해
streaming_replica) - 패스워드
소스 PostgreSQL 인스턴스의 pg_hba.conf 파일에 다음과 유사한 줄을 추가해야 할 수 있어요:
# A more restrictive rule for TLS and IP of origin is recommended
host replication streaming_replica all md5
다음 매니페스트는 externalClusters 배열에 source-db로 정의된 외부 PostgreSQL 클러스터를 클로닝하기 위해 pg_basebackup 부트스트랩 메서드를 사용해 target-db라는 새 PostgreSQL 18.6 클러스터를 만들어요. 보시다시피 source-db 정의는 source-db.foo.com 호스트를 가리키고 패스워드가 source-db-replica-user 시크릿의 password 키에 저장된 streaming_replica 사용자로 연결해요.
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: target-db
spec:
instances: 3
imageName: ghcr.io/cloudnative-pg/postgresql:18.6-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
클로닝 작업이 동작하려면 같은 PostgreSQL 버전(우리의 경우 18.6)을 포함한 모든 요구사항이 충족되어야 해요.
TLS 인증서 인증
CloudNativePG가 pg_basebackup 부트스트랩과 함께 지원하는 두 번째 인증 방법은 TLS 클라이언트 인증서를 기반으로 해요. 보안 관점에서 권장되는 접근 방식이에요.
다음 예시는 같은 Kubernetes 클러스터의 기존 PostgreSQL 클러스터(cluster-example)를 클로닝해요.
:::note 이 예시는 Kubernetes 클러스터 외부에 있는 인스턴스에도 쉽게 적용할 수 있어요. :::
매니페스트는 cluster-example 외부 클러스터에서 pg_basebackup 메서드로 부트스트랩되는 cluster-clone-tls라는 새 PostgreSQL 18.6 클러스터를 정의해요. 호스트는 같은 클러스터의 읽기/쓰기 서비스로 식별되며, streaming_replica 사용자는 제공된 키, 인증서, 인증 기관 정보(각각 cluster-example-replication과 cluster-example-ca 시크릿) 덕분에 인증돼요.
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: cluster-clone-tls
spec:
instances: 3
imageName: ghcr.io/cloudnative-pg/postgresql:18.6-system-trixie
bootstrap:
pg_basebackup:
source: cluster-example
storage:
size: 1Gi
externalClusters:
- name: cluster-example
connectionParameters:
host: cluster-example-rw.default.svc
user: streaming_replica
sslmode: verify-full
sslKey:
name: cluster-example-replication
key: tls.key
sslCert:
name: cluster-example-replication
key: tls.crt
sslRootCert:
name: cluster-example-ca
key: ca.crt
애플리케이션 데이터베이스 구성
initdb와 recovery 부트스트랩 메서드의 경우와 마찬가지로, 라이브 클러스터에서 부트스트랩하는 클러스터의 애플리케이션 데이터베이스도 구성할 수 있게 지원해요. 새 클러스터가 복제 클러스터로 생성되면(복제 모드 활성화) 애플리케이션 데이터베이스 구성은 건너뛰어져요.
:::info[Important]
Cluster가 복구 모드에 있는 동안에는 카탈로그를 포함한 데이터베이스 변경이 허용되지 않아요. 이 제한에는 역할 오버라이드도 포함되며, Cluster가 프라이머리로 전환될 때까지 지연돼요. 복구 단계 동안 역할은 소스 클러스터에 정의된 대로 유지돼요.
:::
아래 예시는 라이브 클러스터에서 부트스트랩한 후 app 데이터베이스를 소유자 app과 제공된 시크릿 app-secret에 저장된 패스워드로 구성해요.
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
[...]
spec:
bootstrap:
pg_basebackup:
database: app
owner: app
secret:
name: app-secret
source: cluster-example
위 구성으로 다음 작업은 복구가 완료된 후에만 일어나요:
app데이터베이스가 없으면 생성.app사용자가 없으면 생성.app사용자가app데이터베이스의 소유자가 아니면 소유권을app사용자에게 부여.- 시크릿의
username값이owner값과 일치하면 애플리케이션 사용자(이 경우app사용자)의 패스워드를 시크릿의password값으로 업데이트.
현재 제한 사항
스냅샷 복사
pg_basebackup 메서드는 PostgreSQL 기본 백업의 형태로 소스 인스턴스의 스냅샷을 찍어요. 백업 시작부터 백업의 올바른 종료까지 쓰여진 모든 트랜잭션은 두 번째 연결을 사용해 대상 인스턴스로 스트리밍돼요(pg_basebackup의 --wal-method=stream 옵션 참고).
백업이 완료되면 새 인스턴스는 새 타임라인에서 시작되어 소스와 분기돼요. 이런 이유로 대상 데이터베이스로 마이그레이션하기 전에 소스 데이터베이스에 대한 모든 쓰기 작업을 중지할 것을 권장해요.
이 제한은 대상 클러스터가 복제 클러스터로 정의되지 않은 경우에만 적용된다는 점을 유의하세요.
:::info[Important] 마이그레이션을 시도하기 전에 절차와 애플리케이션을 모두 테스트해야 해요. 특히 프로덕션에서 애플리케이션의 다운타임을 체계적으로 측정하기 위해 마이그레이션 절차를 필요한 만큼 여러 번 실행하는 것이 근본적으로 중요해요. :::