인증서(Certificates)
CloudNativePG는 TLS 인증서를 네이티브로 지원하도록 설계됐어요. 오퍼레이터가 자동으로 인증서를 관리하는 방식과, cert-manager 같은 별도 컴포넌트로 인증서를 직접 제공하는 방식을 나눠서 설명할게요.
출처: 문서
본문
CloudNativePG는 TLS 인증서를 네이티브로 지원하도록 설계됐어요. 클러스터를 설정하려면 오퍼레이터가 필요로 하는 것:
- 서버 인증 기관(CA) 인증서
- 서버 CA가 서명한 서버 TLS 인증서
- 클라이언트 CA 인증서
- 클라이언트 CA가 생성한 스트리밍 복제(streaming replication) 클라이언트 인증서
:::note 클러스터에서 사용하는 모든 시크릿과 그 만료 날짜는 클러스터의 status에서 찾을 수 있어요. :::
CloudNativePG는 TLS 인증서에 관해 매우 유연해요. 주로 두 가지 모드로 동작해요:
- 오퍼레이터 관리(Operator managed) – 인증서가 완전 자동화된 방식으로 오퍼레이터 내부에서 관리되고, CloudNativePG가 만든 CA로 서명돼요.
- 사용자 제공(User provided) – 인증서가 오퍼레이터 외부에서 생성되고 시크릿으로 클러스터 정의에 가져와져요. CloudNativePG는 cert-manager와 통합돼요. (Cert-manager 예시 참고)
인증서의 일부만 CNPG 외부에서 생성하는 하이브리드 접근 방식도 선택할 수 있어요.
:::note
오퍼레이터와 인스턴스는 DNS 이름을 무시하고 CA에 대해서만 서버 인증서를 검증해요. 이는 클러스터 내 통신에 사용되는 <cluster>-rw 서비스에 대해 사용자 제공 인증서에 DNS 이름이 포함되지 않는 것이 일반적이기 때문이에요.
:::
:::note 위에 나열된 CA 관리 인증서 외에도 오퍼레이터는 인스턴스 매니저의 상태 포트에 인증하기 위해 메모리에서 생성한 자체 서명 클라이언트 인증서도 사용해요. 이 인증서는 클라이언트 CA가 서명한 것이 아니에요. 인스턴스 매니저는 공개 키 지문을 고정(pinning)해 이를 신뢰해요. Operator-to-instance authentication을 참고하세요. :::
오퍼레이터 관리 모드(Operator-Managed Mode)
기본적으로 오퍼레이터는 클라이언트와 서버 인증서를 모두 발급하는 단일 인증 기관(CA)을 자동으로 생성해요. 이 인증서들은 오퍼레이터가 지속적으로 관리하며, 만료 7일 전에 자동 갱신돼요(90일 유효 기간 내).
:::info
CERTIFICATE_DURATION과 EXPIRING_CHECK_THRESHOLD 환경 변수를 구성해 이 기본 동작을 조정할 수 있어요. 자세한 지침은 Operator Configuration을 참고하세요.
:::
:::info[Important] 인증서 갱신은 단순한 리로드 연산으로 충분하므로 PostgreSQL 서버에 다운타임을 초래하지 않아요. 하지만 CloudNativePG가 제어하지 않는 사용자 관리 인증서는 갱신 프로세스에 따라 다시 발급되어야 해요. :::
인증서를 생성할 때 오퍼레이터는 Kubernetes 클러스터의 DNS 영역이 기본적으로 cluster.local로 설정되어 있다고 가정해요. 이 동작은 KUBERNETES_CLUSTER_DOMAIN 환경 변수를 설정해 커스터마이즈할 수 있어요. 편리한 대안은 오퍼레이터의 구성 기능을 사용하는 거예요.
서버 인증서
서버 CA 시크릿
오퍼레이터는 자체 서명 CA를 생성해 다음 키를 포함하는 generic 시크릿에 저장해요:
ca.crt– 서버 인증서를 검증하는 데 사용되는 CA 인증서로, 클라이언트의 연결 문자열에서sslrootcert로 사용돼요.ca.key– 서버 SSL 인증서를 자동으로 서명하는 데 사용되는 키.
서버 TLS 시크릿
오퍼레이터는 생성된 자체 서명 CA를 사용해 서버 TLS 인증서를 서명해요. 이 인증서는 kubernetes.io/tls 타입의 시크릿에 저장되고 인스턴스가 ssl_cert_file과 ssl_key_file로 사용하도록 구성돼요. 이 접근 방식은 클라이언트가 자신의 신원을 검증하고 안전하게 연결할 수 있게 해줘요.
서버 대체 DNS 이름
기본 이름 외에도 생성된 서버 TLS 시크릿의 일부로 DNS 서버 대체 이름을 지정할 수 있어요.
클라이언트 인증서
클라이언트 CA 시크릿
기본적으로 서버 CA와 같은 자체 서명 CA가 사용돼요. 공개 부분은 모든 인스턴스에 ssl_ca_file로 전달되어 그 CA가 서명한 클라이언트 인증서를 검증할 수 있어요. 개인 키는 같은 시크릿에 저장되고 kubectl cnpg 플러그인이 생성한 클라이언트 인증서를 서명하는 데 사용돼요.
클라이언트 streaming_replica 인증서
오퍼레이터는 생성된 자체 서명 CA를 사용해 streaming_replica 사용자용 클라이언트 인증서를 서명하고 kubernetes.io/tls 타입의 시크릿에 저장해요. 프라이머리 인스턴스에 안전하게 연결할 수 있도록 이 인증서는 복제본의 연결 문자열에서 sslcert와 sslkey로 전달돼요.
사용자 제공 인증서 모드
서버 인증서
필요하다면 cert-manager 같은 별도 컴포넌트로 생성한 두 서버 인증서를 제공할 수도 있어요. 클러스터에 커스텀 서버 TLS 인증서를 사용하려면 다음 파라미터를 지정해야 해요:
serverTLSSecret– 서버 TLS 인증서를 포함하는kubernetes.io/tls타입 시크릿의 이름. 표준tls.crt와tls.key키를 모두 포함해야 해요.serverCASecret–ca.crt키를 포함하는 시크릿의 이름.
:::note 오퍼레이터는 여전히 클라이언트 인증서와 관련된 두 시크릿을 생성하고 관리해요. :::
:::note
오퍼레이터와 인스턴스는 DNS 이름을 무시하고 CA에 대해서만 서버 인증서를 검증해요. 이는 클러스터 내 통신에 사용되는 <cluster>-rw 서비스에 대해 사용자 제공 인증서에 DNS 이름이 포함되지 않는 것이 일반적이기 때문이에요.
:::
:::note
인스턴스가 ConfigMap과 시크릿을 리로드하게 하려면 여기에 cnpg.io/reload 키의 레이블을 추가할 수 있어요. 그렇지 않으면 kubectl cnpg reload 하위 명령으로 인스턴스를 리로드해야 해요.
:::
예시
다음 파일이 있다고 가정해 볼게요:
server-ca.crt– 서버 TLS 인증서를 서명한 CA의 인증서.server.crt– 서버 TLS 인증서의 인증서.server.key– 서버 TLS 인증서의 개인 키.
CA 인증서를 포함하는 시크릿 만들기:
kubectl create secret generic my-postgresql-server-ca \
--from-file=ca.crt=./server-ca.crt
TLS 인증서로 시크릿 만들기:
kubectl create secret tls my-postgresql-server \
--cert=./server.crt --key=./server.key
그 시크릿들을 참조하는 PostgreSQL 클러스터 만들기:
kubectl apply -f - <<EOF
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: cluster-example
spec:
instances: 3
certificates:
serverCASecret: my-postgresql-server-ca
serverTLSSecret: my-postgresql-server
storage:
storageClass: standard
size: 1Gi
EOF
새 클러스터는 TLS 연결에 제공한 서버 인증서를 사용해요.
Cert-manager 예시
이 간단한 예시는 cert-manager를 사용해 자체 서명 CA를 설정하고 필요한 TLS 서버 인증서를 생성하는 방법을 보여줘요:
---
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: selfsigned-issuer
spec:
selfSigned: {}
---
apiVersion: v1
kind: Secret
metadata:
name: my-postgres-server-cert
labels:
cnpg.io/reload: ""
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: my-postgres-server-cert
spec:
secretName: my-postgres-server-cert
usages:
- server auth
dnsNames:
- cluster-example-lb.internal.mydomain.net
- cluster-example-rw
- cluster-example-rw.default
- cluster-example-rw.default.svc
- cluster-example-r
- cluster-example-r.default
- cluster-example-r.default.svc
- cluster-example-ro
- cluster-example-ro.default
- cluster-example-ro.default.svc
issuerRef:
name: selfsigned-issuer
kind: Issuer
group: cert-manager.io
Cert-manager는 my-postgres-server-cert라는 시크릿을 만들어요. 여기에는 필요한 모든 파일이 포함되며 다음과 같이 클러스터에서 참조할 수 있어요:
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: cluster-example
spec:
instances: 3
certificates:
serverTLSSecret: my-postgres-server-cert
serverCASecret: my-postgres-server-cert
storage:
size: 1Gi
cert-manager를 사용해 서버와 클라이언트 CA 및 인증서를 모두 관리하는 완전한 예시는 cluster-example-cert-manager.yaml 배포 매니페스트에서 찾을 수 있어요.
클라이언트 인증서
필요하다면 cert-manager나 HashiCorp vault 같은 별도 컴포넌트로 생성한 두 클라이언트 인증서를 제공할 수도 있어요. 클러스터의 클라이언트 인증서를 검증하는 데 커스텀 CA를 사용하려면 다음 파라미터를 지정해야 해요:
replicationTLSSecret–streaming_replica사용자용 클라이언트 인증서를 포함하는kubernetes.io/tls타입 시크릿의 이름. 표준tls.crt와tls.key키를 모두 포함해야 해요.clientCASecret– 클라이언트 인증서를 검증하는 데 사용할 CA의ca.crt키를 포함하는 시크릿의 이름.
:::note 오퍼레이터는 여전히 서버 인증서와 관련된 두 시크릿을 생성하고 관리해요. :::
:::note
클러스터가 클라이언트 CA 시크릿 키를 제어하지 않으므로, 더 이상 kubectl cnpg certificate로 클라이언트 인증서를 생성할 수 없어요.
:::
:::note
인스턴스가 ConfigMap과 시크릿을 자동으로 리로드하게 하려면 여기에 cnpg.io/reload 키의 레이블을 추가할 수 있어요. 그렇지 않으면 kubectl cnpg reload 하위 명령으로 인스턴스를 리로드해야 해요.
:::
streaming_replica 클라이언트 인증서 커스터마이즈하기
일부 환경에서는 회사 정책이나 다른 보안 우려(예: 여러 클러스터가 공유하는 CA) 때문에 common name이 streaming_replica인 인증서를 생성하지 못할 수 있어요. 이런 경우 사용자 매핑 기능을 사용해 다른 common name을 가진 인증서로 streaming_replica 사용자로 인증할 수 있게 할 수 있어요.
이 설정을 구성하려면 cnpg_streaming_replica라는 사전 정의된 맵에 pg_ident.conf 항목을 추가해요.
예를 들어 common name이 streaming-replica.cnpg.svc.cluster.local인 인증서로 streaming_replica 인증을 활성화하려면 클러스터 정의에 다음을 추가하세요:
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: cluster-example
spec:
postgresql:
pg_ident:
- cnpg_streaming_replica streaming-replica.cnpg.svc.cluster.local streaming_replica
오퍼레이터가 pg_ident.conf를 관리하는 방법에 대한 자세한 내용은 문서의 "PostgreSQL Configuration" 페이지를 참고해 주세요.
Cert-manager 예시
이 간단한 예시는 cert-manager를 사용해 자체 서명 CA를 설정하고 필요한 TLS 서버 인증서를 생성하는 방법을 보여줘요:
---
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: selfsigned-issuer
spec:
selfSigned: {}
---
apiVersion: v1
kind: Secret
metadata:
name: my-postgres-client-cert
labels:
cnpg.io/reload: ""
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: my-postgres-client-cert
spec:
secretName: my-postgres-client-cert
usages:
- client auth
commonName: streaming_replica
issuerRef:
name: selfsigned-issuer
kind: Issuer
group: cert-manager.io
Cert-manager는 필요한 모든 파일을 포함하는 my-postgres-client-cert라는 시크릿을 만들어요. 다음과 같이 클러스터에서 참조할 수 있어요:
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: cluster-example
spec:
instances: 3
certificates:
clientCASecret: my-postgres-client-cert
replicationTLSSecret: my-postgres-client-cert
storage:
size: 1Gi
cert-manager를 사용해 서버와 클라이언트 CA 및 인증서를 모두 관리하는 완전한 예시는 cluster-example-cert-manager.yaml 배포 매니페스트에서 찾을 수 있어요.