콘텐츠로 이동
Study NotePostgreSQL

Cluster·스토리지·배치 읽기

결론부터
인스턴스 수뿐 아니라 각 인스턴스가 놓일 노드와 볼륨의 장애 범위를 함께 설계한다.

DB 인스턴스가 세 개라도 같은 물리 장비나 같은 고장 나는 스토리지에 모이면 함께 멈출 수 있다. 이 페이지는 작은 Cluster를 읽으면서 어떤 전제가 필요한지 확인한다.

이 장에서 처음 나오는 말3개
PVCPersistentVolumeClaim
Pod가 사용할 영구 저장 공간을 요청하는 Kubernetes 리소스.
StorageClass
볼륨의 프로비저닝·확장·회수 정책 등을 연결하는 스토리지 설정.
장애 영역Failure domain
한 번의 장애로 함께 영향을 받을 수 있는 노드·랙·전원·스토리지 등의 범위.

아래는 공식 문서와 대조한 구성 예제이며 이 덱 작성 시 실제 Kubernetes 배포 검증은 하지 않았다. 로컬 SQL 실습과 별도로 다음 조건을 갖춘 실습 Kubernetes에서 사용한다.

  • 공식 설치 안내에 따라 지원 조합의 CNPG operator와 CRD를 설치한다. 설치 스크립트와 보안 패치는 원문에서 확인한다.
  • kubectl cnpg 플러그인은 공식 안내에 따라 준비한다.
  • 아래 required anti-affinity를 만족할 서로 다른 스케줄 가능 노드 3개와 필요한 CPU·메모리·볼륨을 확보한다.
  • db-lab은 예시 StorageClass 이름이다. kubectl get storageclass로 실제 이름·reclaimPolicy를 확인하고 바꾼다.
  • 이미지 registry 접근과, operator가 pg-study namespace를 관리할 수 있는 범위를 확인한다.
터미널 창
kubectl config current-context
kubectl get crd clusters.postgresql.cnpg.io
kubectl get nodes
kubectl get storageclass
kubectl cnpg version

기존 업무 클러스터를 실습 대상으로 착각하지 않도록 context를 먼저 확인한다.

작업 폴더에 cluster.yaml로 저장하고 StorageClass를 맞춘다. PostgreSQL 이미지 태그는 검토일에 존재를 확인한 예이며 업그레이드 시 새 패치와 이미지 digest를 확인한다.

apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: study-pg
namespace: pg-study
spec:
instances: 3
imageName: ghcr.io/cloudnative-pg/postgresql:18.6-standard-trixie
bootstrap:
initdb:
database: studydb
owner: study_app
storage:
storageClass: db-lab
size: 10Gi
resources:
requests:
cpu: "500m"
memory: 512Mi
limits:
memory: 1Gi
affinity:
enablePodAntiAffinity: true
podAntiAffinityType: required
topologyKey: kubernetes.io/hostname

자원 크기는 동작 구조를 읽는 실습 예시다. 실제 데이터량·연결 수·쿼리 부하를 측정해 조정한다. (빠른 시작, 자원 관리)

터미널 창
kubectl create namespace pg-study
kubectl apply --dry-run=server -f cluster.yaml
kubectl apply -f cluster.yaml
kubectl cnpg status -n pg-study study-pg
kubectl get pods,pvc,services -n pg-study

서버 dry-run은 API 수용 여부를 확인할 뿐 스토리지·이미지·복제의 실제 성공을 보장하지 않는다. 인스턴스 3개가 준비되고 primary 하나와 standby 둘로 구성되는지 상태를 확인한다. initdb로 만든 앱 계정의 Secret은 기본적으로 study-pg-app이다. 내용을 출력해 문서나 로그에 남기지 않는다. (초기화)

같은 10Gi를 공유하는 것이 아니다

섹션 제목: “같은 10Gi를 공유하는 것이 아니다”

storage.size: 10Gi는 인스턴스별 데이터 PVC 요청이다. 세 인스턴스라면 그만큼 각각 공간이 필요하다. 각 볼륨에 데이터를 복제하는 것은 PostgreSQL이다. 공유 디스크 하나를 세 Pod가 동시에 쓰는 설계가 아니다. walStorage는 WAL을 별도 볼륨에 둘 때 쓰며, 분리 자체가 백업이나 별도 장애 영역을 보장하지 않는다. (스토리지)

local PV는 노드 장애 때 다른 노드에 같은 데이터로 붙일 수 있는지 제약이 있다. DB replica 승격과 원래 볼륨 복구는 별개의 작업이다. 볼륨을 자동 확장할 수 있는지도 StorageClass와 스토리지 제공자의 지원을 확인한다.

기본 선호 배치만으로는 서로 다른 노드를 강제하지 않는다. 이 예제는 required이므로 노드가 부족하면 일부 Pod가 Pending인 것이 정책에 맞는 결과다. 테스트를 위해 이를 완화했다면 가용성 평가의 전제가 달라진다. 노드가 달라도 같은 물리 서버의 VM이면 물리 장비 장애에 함께 영향을 받을 수 있다. (스케줄링)

관리 진단으로 다음 SQL을 실행하면 primary에서 false를 기대한다. 이것은 앱 자격증명·Service 경로의 검증과 별개다.

터미널 창
kubectl cnpg psql -n pg-study study-pg -- -d studydb -c 'SELECT pg_is_in_recovery();'

이 Cluster는 뒤의 백업·복원 예제에서도 사용한다. 모두 끝난 뒤에만 지운다.

터미널 창
kubectl delete -n pg-study cluster study-pg
kubectl get pvc -n pg-study

삭제 전에 필요한 데이터를 보관한다. 종속 리소스 삭제와 남은 PV의 처리는 ownerReference·회수 정책을 확인한다. 오브젝트 스토리지의 백업 보관은 별도의 수명주기다.