본문 바로가기
WIKI 기술 지식 베이스

오퍼레이터 구성

원문 보기 위키 갱신

오퍼레이터 구성 (Operator configuration)

CloudNativePG 오퍼레이터의 기본 동작을 어떻게 커스터마이즈하는지 알려 드릴게요. 상속할 라벨/어노테이션 정의, 기본 PostgreSQL 이미지 변경, 추가 풀 시크릿, 오퍼레이터 로그 레벨 등은 ConfigMap/Secret으로 제어할 수 있어요.

출처: 문서

본문

CloudNativePG 오퍼레이터는 표준 디플로이먼트 매니페스트에서 설치되며, '컨벤션 오버 컨피규레이션(convention over configuration)' 패러다임을 따릅니다. 대부분의 경우 이 방식으로 충분하지만, 다음과 같이 기본 동작을 변경하고 싶은 시나리오가 있을 수 있어요:

  • 오퍼레이터가 생성하는 모든 리소스가 상속받도록, 클러스터 리소스에 설정된 어노테이션과 라벨을 정의
  • PostgreSQL의 기본 이미지를 다른 것으로 설정하거나 추가 풀 시크릿(pull secret)을 정의

기본적으로 오퍼레이터는 cnpg-system 네임스페이스에 cnpg-controller-manager라는 Kubernetes Deployment로 설치돼요.

:::note 아래 예시에서는 오퍼레이터 디플로이먼트의 기본 이름과 네임스페이스를 가정해요. :::

오퍼레이터의 동작은 오퍼레이터 디플로이먼트와 같은 네임스페이스에 있고 이름이 cnpg-controller-manager-config인 ConfigMap/Secret을 통해 커스터마이즈할 수 있어요.

:::info[Important] 구성 ConfigMap/Secret의 변경은 오퍼레이터가 자동으로 감지하지 않으므로, (아래 설명처럼) 리로드가 필요해요. 게다가 변경 사항은 구성이 리로드된 후에 생성된 리소스에만 적용돼요. :::

:::info[Important] 오퍼레이터는 먼저 ConfigMap 값을 처리하고, 그 다음에 Secret 값을 처리해요. 따라서 두 곳 모두에 파라미터가 정의되어 있으면 Secret의 값이 사용돼요. :::

사용 가능한 옵션 (Available options)

오퍼레이터는 ConfigMap/Secret에 정의된 다음 환경 변수를 찾아봐요:

Name Description
CERTIFICATE_DURATION 생성된 인증서의 수명을 일 단위로 결정해요. 기본값은 90이에요.
CLUSTERS_ROLLOUT_DELAY 오퍼레이터 업그레이드 중 서로 다른 클러스터들의 롤아웃 사이에 대기하는 시간(초)이에요. 이 설정은 클러스터 간 업그레이드 시점을 제어해서, 펼쳐 놓아 시스템 영향을 줄여요. 기본값은 0이며 이는 PostgreSQL 클러스터 업그레이드 사이에 지연이 없음을 의미해요.
CREATE_ANY_SERVICE true로 설정하면 클러스터용 -any 서비스를 생성해요. 기본값은 false예요.
DRAIN_TAINTS 노드 드레인(drain)의 지표로 해석해야 하는 테인트(taint) 키를 지정해요. 기본적으로는 kubectl, Cluster Autoscaler, Karpenter가 흔히 적용하는 테인트인 node.kubernetes.io/unschedulable, ToBeDeletedByClusterAutoscaler, karpenter.sh/disrupted, karpenter.sh/disruption을 포함해요.
ENABLE_INSTANCE_MANAGER_INPLACE_UPDATES true로 설정하면 오퍼레이터 업데이트 후 인스턴스 매니저의 인플레이스(in-place) 업데이트를 활성화해서 클러스터의 롤링 업데이트를 피해요 (기본값 false).
ENABLE_WEBHOOK_NAMESPACE_SUFFIX true로 설정하면 오퍼레이터가 -<OPERATOR_NAMESPACE> 접미사가 붙은 이름(예: cnpg-mutating-webhook-configuration-cnpg-team-a, cnpg-validating-webhook-configuration-cnpg-team-a) 아래에서 MutatingWebhookConfiguration과 ValidatingWebhookConfiguration을 찾아봐요. 같은 클러스터에서 여러 네임스페이스 오퍼레이터 인스턴스를 실행할 때 이름 충돌을 피하려면 이 옵션을 사용하세요. 오퍼레이터는 접미사가 붙은 구성을 생성하지 않아요. 이 플래그를 활성화해 오퍼레이터를 시작하기 전에 직접 만들어야 해요. 이 플래그가 활성화된 상태에서 OPERATOR_NAMESPACE가 설정되지 않으면 오퍼레이터는 시작을 거부해요. 기본값은 false예요.
EXPIRING_CHECK_THRESHOLD 인증서가 만료 예정으로 식별되는 기준을 일 단위로 결정해요. 기본값은 7이에요.
INCLUDE_PLUGINS 클러스터의 리컨실리에이션에 항상 포함될 플러그인의 쉼표로 구분된 목록이에요.
INHERITED_ANNOTATIONS Cluster 메타데이터에 정의되면 파드를 포함한 모든 생성 리소스에 상속될 어노테이션 이름 목록이에요.
INHERITED_LABELS Cluster 메타데이터에 정의되면 파드를 포함한 모든 생성 리소스에 상속될 라벨 이름 목록이에요.
INSTANCES_ROLLOUT_DELAY 오퍼레이터 업그레이드 중 같은 클러스터 내 개별 PostgreSQL 인스턴스들의 롤아웃 사이에 대기하는 시간(초)이에요. 기본값은 0이며 같은 PostgreSQL 클러스터의 인스턴스 업그레이드 사이에 지연이 없음을 의미해요.
KUBERNETES_CLUSTER_DOMAIN Kubernetes 클러스터 내 서비스 FQDN의 도메인 접미사를 정의해요. 설정하지 않으면 기본값은 "cluster.local"이에요.
MANAGE_WEBHOOK_CONFIGURATIONS true(기본값)로 설정하면 오퍼레이터가 자체 CA 번들을 MutatingWebhookConfiguration과 ValidatingWebhookConfiguration에 주입해요. CA 번들이 cert-manager의 CA 인젝터나 GitOps와 같은 외부에서 주입되는 경우 false로 설정하세요. 이는 웹훅 서빙 인증서와는 별개이며, 오퍼레이터는 자체 PKI를 소유할 때 항상 그 인증서를 관리해요.
METRICS_CERT_DIR 오퍼레이터 메트릭스 서버의 TLS 인증서가 저장되는 디렉토리예요. 설정하면 포트 8080의 메트릭스 엔드포인트에 TLS를 활성화해요. 디렉토리에는 표준 Kubernetes TLS 시크릿 규칙을 따르는 tls.crt와 tls.key 파일이 있어야 해요. 설정하지 않으면 메트릭스 서버는 TLS 없이 동작해요 (기본 동작).
MONITORING_QUERIES_CONFIGMAP 오퍼레이터 네임스페이스에 있는, 생성된 모든 클러스터에 적용할 기본 쿼리 세트(queries 키 아래에 지정)를 담은 ConfigMap의 이름이에요.
MONITORING_QUERIES_SECRET 오퍼레이터 네임스페이스에 있는, 생성된 모든 클러스터에 적용할 기본 쿼리 세트(queries 키 아래에 지정)를 담은 Secret의 이름이에요.
OPERATOR_IMAGE_NAME 파드를 부트스트랩하는 데 사용되는 오퍼레이터 이미지 이름. 설치 시 지정된 이미지가 기본값이에요.
PGBOUNCER_IMAGE_NAME 새 풀러에 기본적으로 사용되는 PgBouncer 이미지 이름. 오퍼레이터에 지정된 버전이 기본값이에요.
POSTGRES_IMAGE_NAME 새 클러스터에 기본적으로 사용되는 PostgreSQL 이미지 이름. 오퍼레이터에 지정된 버전이 기본값이에요.
PULL_SECRET_NAME 오퍼레이터 네임스페이스에 정의되고 이미지를 다운로드하는 데 사용될 추가 풀 시크릿 이름이에요.
STANDBY_TCP_USER_TIMEOUT 스탠바이 인스턴스에서 프라이머리로의 리플리케이션 연결에 대한 TCP_USER_TIMEOUT 소켓 옵션을 밀리초 단위로 정의해요. 기본값은 5000(5초)이에요. 시스템 기본값을 사용하려면 0으로 설정하세요.
WATCH_NAMESPACE 오퍼레이터가 리소스를 감시해야 하는 네임스페이스를 지정해요. 여러 네임스페이스는 쉼표로 구분해 지정할 수 있어요. 설정하지 않으면 오퍼레이터는 모든 네임스페이스를 감시해요 (클러스터-와이드 모드).

:::warning CloudNativePG는 현재 같은 클러스터에서 여러 오퍼레이터를 실행하는 것을 지원하지 않아요. ENABLE_WEBHOOK_NAMESPACE_SUFFIX와 WATCH_NAMESPACE를 사용한 네임스페이스 디플로이먼트로 이를 구현할 수는 있지만, 여러 오퍼레이터는 여전히 같은 공유 CRD 세트를 사용해요. 여러 동시 실행 오퍼레이터에 걸쳐 하위 호환되는 업그레이드를 보장할 수 없어요. :::

INHERITED_ANNOTATIONS와 INHERITED_LABELS의 값은 경로형 와일드카드를 지원해요. 예를 들어 example.com/* 값은 example.com/one과 example.com/two 두 값을 모두 일치시켜요.

PULL_SECRET_NAME 파라미터로 추가 풀 시크릿 이름을 지정하면, 오퍼레이터는 생성되는 모든 PostgreSQL 클러스터에 대해 풀 시크릿을 만들기 위해 그 시크릿을 사용해요. 그 시크릿은 <cluster-name>-pull로 이름이 붙여져요.

오퍼레이터가 PULL_SECRET_NAME 시크릿을 찾는 네임스페이스는 오퍼레이터를 설치한 곳이에요. 오퍼레이터가 그 시크릿을 찾지 못하면 구성 파라미터를 무시해요.

오퍼레이터 컨피그 맵 정의하기 (Defining an operator config map)

아래 예시는 나중에 배포되는 어떤 Cluster 객체가 생성하는 리소스가 상속할 라벨/어노테이션 이름을 정의하고, 인스턴스 매니저의 인플레이스 업데이트를 활성화하고, 업그레이드를 펼쳐 놓음으로써 오퍼레이터의 동작을 커스터마이즈해요.

apiVersion: v1
kind: ConfigMap
metadata:
  name: cnpg-controller-manager-config
  namespace: cnpg-system
data:
  CLUSTERS_ROLLOUT_DELAY: '60'
  ENABLE_INSTANCE_MANAGER_INPLACE_UPDATES: 'true'
  INHERITED_ANNOTATIONS: categories
  INHERITED_LABELS: environment, workload, app
  INSTANCES_ROLLOUT_DELAY: '10'

오퍼레이터 시크릿 정의하기 (Defining an operator secret)

아래 예시는 나중에 배포되는 어떤 Cluster 객체가 생성하는 리소스가 상속할 라벨/어노테이션 이름을 정의하고, 인스턴스 매니저의 인플레이스 업데이트를 활성화하고, 업그레이드를 펼쳐 놓음으로써 오퍼레이터의 동작을 커스터마이즈해요.

apiVersion: v1
kind: Secret
metadata:
  name: cnpg-controller-manager-config
  namespace: cnpg-system
type: Opaque
stringData:
  CLUSTERS_ROLLOUT_DELAY: '60'
  ENABLE_INSTANCE_MANAGER_INPLACE_UPDATES: 'true'
  INHERITED_ANNOTATIONS: categories
  INHERITED_LABELS: environment, workload, app
  INSTANCES_ROLLOUT_DELAY: '10'

오퍼레이터를 재시작해 구성 리로드하기 (Restarting the operator to reload configs)

변경 사항이 적용되려면 컨피그 맵을 리로드하기 위해 오퍼레이터 파드를 다시 만들어야 해요. 매니페스트를 사용해 Kubernetes에 오퍼레이터를 설치했다면 다음 명령으로 할 수 있어요:

kubectl rollout restart deployment \
    -n cnpg-system \
    cnpg-controller-manager

일반적으로, 특정 네임스페이스가 주어졌을 때 다음 명령으로 오퍼레이터 파드를 삭제할 수 있어요:

kubectl delete pods -n [NAMESPACE_NAME_HERE] \
  -l app.kubernetes.io/name=cloudnative-pg

:::warning 커스터마이즈는 오퍼레이터 디플로이먼트를 리로드한 후에 생성된 Cluster 리소스에만 적용돼요. :::

위 예시를 따르면, Cluster 정의에 categories 어노테이션과 environment, workload, app 라벨 중 하나라도 있으면, 이들은 디플로이먼트가 생성하는 모든 리소스에 상속돼요.

어드미션 웹훅 없이 기본값 적용 및 검증하기 (Defaulting and validation without admission webhooks)

CloudNativePG는 보통 어드미션 웹훅을 통해 리소스에 기본값을 적용하고 검증해요. 웹훅이 설치되지 않았거나 일시적으로 응답할 수 없을 때, 오퍼레이터는 폴백으로서 리컨실리에이션 중에 동일한 기본값 적용과 검증을 수행해요.

리소스가 검증에 실패하면 리컨실리에이션이 멈추고 그 이유가 리소스 상태에 표시돼요: Cluster와 Backup은 각각 Invalid cluster definition과 invalid backup definition 단계로 이동하고, Pooler와 ScheduledBackup은 .status.error에 보고해요. 상태에는 문제가 있는 필드 경로만 나열되고, 필드 값을 포함할 수 있는 전체 검증 오류는 오퍼레이터 로그에만 기록돼요. 스펙을 수정하면 오류가 지워지고 리컨실리에이션이 재개돼요.

리컨실리에이션 중 수행되는 검증은 어드미션 웹훅과 마찬가지로 cnpg.io/validation: disabled 어노테이션을 존중해요.

프로파일링 도구 (Profiling tools)

오퍼레이터는 localhost:6060에 pprof HTTP 서버를 노출할 수 있어요. 이를 활성화하려면 오퍼레이터 디플로이먼트를 편집하고 컨테이너 args에 --pprof-server=true 플래그를 추가하세요:

kubectl edit deployment -n cnpg-system cnpg-controller-manager

예를 들어 args 목록에 --pprof-server=true를 추가하세요:

      containers:
      - args:
        - controller
        - --leader-elect
        - --config-map-name=cnpg-controller-manager-config
        - --secret-name=cnpg-controller-manager-config
        - --log-level=info
        - --pprof-server=true # 관련 줄
        command:
        - /manager

저장하면 디플로이먼트가 롤아웃되고 새 파드에서 pprof 서버가 활성화돼요.

:::info[Important] pprof 서버는 포트 6060에서 일반 HTTP만 서빙해요. :::

로컬 머신에서 pprof 엔드포인트에 접근하려면 포트 포워딩을 사용하세요:

kubectl port-forward -n cnpg-system deploy/cnpg-controller-manager 6060
curl -sS http://localhost:6060/debug/pprof/
go tool pprof http://localhost:6060/debug/pprof/profile?seconds=30

브라우저에서 http://localhost:6060/debug/pprof/로 pprof에 접근할 수도 있어요.

:::warning 위 예시의 kubectl port-forward는 로컬 테스트 전용이에요. 이 기능을 프로덕션에 노출하는 올바른 방법이 아니에요. pprof를 민감한 디버깅 인터페이스로 취급하고 절대 공개적으로 노출하지 마세요. 원격으로 접근해야 한다면 적절한 네트워크 정책과 접근 제어로 보호하세요. :::