본문으로 건너뛰기

2.2 Custom Resource 지도

앞 절에서 Cluster 하나로 PostgreSQL 클러스터를 선언한다고 했다. 그런데 CloudNativePG를 실제로 운영하면 Backup, ScheduledBackup, Pooler, Database처럼 Cluster가 아닌 리소스도 여럿 만나게 된다. 이 절은 그 리소스들이 Cluster와 어떤 관계인지 한 장에 정리한다. 세부 사용법은 각 Part에서 다루므로, 여기서는 "무엇이 무엇을 가리키고, 무엇이 무엇을 소유하는가"만 본다.

원칙은 하나다. 중심은 Cluster다. 대부분의 Custom Resource는 spec.cluster.name으로 Cluster를 가리키는 연관 리소스이고, 카탈로그와 ObjectStore 두 종류만 반대로 Cluster가 가리킨다. 어느 리소스든 spec.cluster.name이 있으면 "이 Cluster에 속한 것"이라는 뜻이다.

참조와 소유는 다르다​

Kubernetes에서 리소스 사이의 관계는 두 종류로 나뉘고, 이 둘을 구분해야 삭제 동작이 예측된다.

  • 참조(reference): 한 리소스의 spec이 다른 리소스의 이름을 적는 것. Backup.spec.cluster.name이 Cluster 이름을 적는 식이다. 참조 대상이 지워져도 참조하는 쪽이 자동으로 지워지지는 않는다. 그 뒤 동작은 컨트롤러마다 다르다.
  • 소유(ownerReference): metadata.ownerReferences로 부모를 지정하는 것. 부모가 지워지면 Kubernetes garbage collector가 자식을 함께 지운다. Operator가 Cluster로부터 만든 Pod, PVC, Service, Secret이 이 관계다.

소유 관계가 생기는 것은 Operator가 무언가를 대신 만들어 줄 때다. Custom Resource끼리는 대부분 참조만 있다. 아래 지도에서 실선은 소유, 점선은 참조다. ScheduledBackup에서 Backup으로 가는 점선만 예외인데, 생성은 하지만 소유 여부가 설정에 달려 있어 점선으로 그렸다.

화살표 방향은 "누가 누구 이름을 적는가"다. Backup은 자기 spec.cluster에 Cluster 이름을 적으므로 Backup에서 Cluster로 향하고, Cluster는 자기 imageCatalogRef에 카탈로그 이름을 적으므로 Cluster에서 카탈로그로 향한다. 노란색 하나(ClusterImageCatalog)만 namespace에 속하지 않는 전역 리소스다.

리소스별 한 줄 요약​

리소스API group범위Cluster와의 관계자세한 절
Clusterpostgresql.cnpg.ionamespace중심. 인스턴스 수, 이미지, 스토리지, 설정, bootstrap이 모두 여기Part IV~
Backuppostgresql.cnpg.ionamespacespec.cluster로 참조. 백업 1회 실행 요청. 복원에 필요한 메타데이터가 status에 남음7.1
ScheduledBackuppostgresql.cnpg.ionamespacespec.cluster로 참조. cron 주기로 Backup을 생성7.1
Poolerpostgresql.cnpg.ionamespacespec.cluster로 참조. 앞단에 PgBouncer Deployment와 Service를 생성8.5
Databasepostgresql.cnpg.ionamespacespec.cluster로 참조. database, schema, extension을 선언9.3
DatabaseRolepostgresql.cnpg.ionamespacespec.cluster로 참조. role을 Cluster 밖에서 선언(1.30 신규)9.2
Publication / Subscriptionpostgresql.cnpg.ionamespacespec.cluster로 참조. logical replication의 발행과 구독. Subscription의 원본 접속 정보는 Cluster의 externalClusters에 둠12.1
ImageCatalogpostgresql.cnpg.ionamespaceCluster가 imageCatalogRef로 참조. major → 이미지 매핑3.2
ClusterImageCatalogpostgresql.cnpg.io전역같은 스키마, 모든 namespace가 공유3.2
ObjectStorebarmancloud.cnpg.ionamespaceCluster가 plugins[].parameters.barmanObjectName으로 참조. CloudNativePG 본체가 아니라 Barman Cloud 플러그인이 설치하는 CRD7.1, 2.5

ObjectStore만 API group이 다르다는 점을 기억해 두면 좋다. kubectl get crd에서 barmancloud.cnpg.io가 보이지 않으면 플러그인이 설치되지 않은 것이고, 이 리소스를 참조하는 Cluster는 백업을 시작하지 못한다.

ScheduledBackup과 Backup 사이의 소유​

ScheduledBackup은 cron마다 Backup을 만든다. 만들기는 하지만 그 Backup을 누가 소유할지는 고정되어 있지 않고 backupOwnerReference로 정한다. 그래서 지도에서도 이 화살표는 점선이다.

  • none: 소유자 없음. ScheduledBackup을 지워도 Backup은 남는다
  • self: ScheduledBackup이 소유. ScheduledBackup을 지우면 Backup도 함께 지워진다
  • cluster: Cluster가 소유. Cluster를 지우면 Backup도 함께 지워진다

volume snapshot 백업이라면 여기에 한 층이 더 붙는다. Backup이 만든 VolumeSnapshot의 소유자는 snapshotOwnerReference가 따로 정한다(7.1). 즉 "무엇을 지우면 무엇이 따라 지워지는가"는 리소스 종류마다 설정으로 정하는 것이고, 기본값은 대체로 "남긴다" 쪽이다.

1.30에서 바뀐 것: cluster 참조는 불변​

1.30부터 Database, Pooler, Publication, Subscription, ScheduledBackup의 cluster 필드는 만든 뒤 바꿀 수 없다. 리소스를 다른 Cluster로 옮기고 싶으면 수정하지 말고 새 리소스를 만든다. 매니페스트를 수정해 kubectl apply하면 검증 단계에서 거부된다.

노트

Cluster를 지우면 소유 관계인 Pod, PVC, Service, Secret이 함께 정리된다. 데이터가 담긴 PVC도 포함된다. PVC가 지워진 뒤 실제 PV와 스토리지 데이터가 남는지는 StorageClass의 reclaim policy가 정하므로, CloudNativePG 밖의 설정이다. 그래서 Cluster 삭제 전에는 최근 Backup이 있는지, 그 Backup이나 VolumeSnapshot의 소유자가 cluster로 되어 있어 함께 사라지지는 않는지 확인한다. Pod만 내리고 PVC를 남기고 싶다면 삭제가 아니라 hibernation(11.4)이다.

한 번에 확인하기​

한 namespace에 어떤 리소스가 있는지 확인하는 명령이다. DatabaseRole은 1.30 이상에서만 존재한다.

kubectl get cluster,backup,scheduledbackup,pooler,database,databaserole,publication,subscription -n <namespace>
kubectl get clusterimagecatalog
kubectl get objectstore -n <namespace> # Barman Cloud 플러그인 설치 시

정리​

  • Cluster가 중심이고 대부분의 Custom Resource는 spec.cluster.name으로 Cluster를 참조하는 연관 리소스다. 카탈로그와 ObjectStore만 반대로 Cluster가 참조한다.
  • 참조는 삭제를 전파하지 않고 소유(ownerReference)는 전파한다. Operator가 만든 Pod, PVC, Service, Secret은 Cluster가 소유한다.
  • Custom Resource끼리의 소유는 backupOwnerReference, snapshotOwnerReference처럼 설정으로 정하며 기본은 남기는 쪽이다.
  • ObjectStore는 플러그인의 CRD라 API group이 다르고, 1.30부터 곁가지 리소스의 cluster 참조는 불변이다.