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

스케줄링

원문 보기 위키 갱신

스케줄링 (Scheduling)

쿠버네티스에서 스케줄링은 여러 기준에 따라 새 Pod를 가장 좋은 노드에 배치하는 프로세스를 말해요.

:::note[쿠버네티스 문서] 스케줄링에 관한 더 자세한 정보와 사용 가능한 모든 정책은 쿠버네티스 문서를 참조하세요. 이 페이지에서는 affinity, anti-affinity, node selector 같은 개념에 익숙하다고 가정해요. :::

CloudNativePG 클러스터의 인스턴스가 어떻게 스케줄링되어야 하는지는 클러스터 정의의 affinity 섹션을 통해 제어할 수 있어요. 이 섹션은 다음을 지원해요:

  • pod affinity/anti-affinity
  • node selector
  • tolerations

출처: 문서

본문

Pod Affinity와 Anti-Affinity

쿠버네티스는 affinity와 anti-affinity 규칙을 사용해 Pod가 어디에 스케줄링될지 제어하는 메커니즘을 제공해요. 이 규칙들은 이미 실행 중인 워크로드에 따라 Pod가 특정 노드에 스케줄링되어야 하는지(affinity) 특정 노드를 피해야 하는지(anti-affinity)를 지정할 수 있게 해줘요. 이 기능은 기술적으로 inter-pod affinity/anti-affinity라고 불러요.

기본적으로 CloudNativePG는 클러스터 인스턴스가 서로 다른 노드에 스케줄링되도록 선호하는 반면, pgBouncer 인스턴스는 같은 노드에서 실행될 수도 있어요.

예를 들어 다음 Cluster 사양이 있다고 해볼게요:

apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
  name: cluster-example
spec:
  instances: 3
  imageName: ghcr.io/cloudnative-pg/postgresql:18.6-system-trixie

  affinity:
    enablePodAntiAffinity: true # Default value
    topologyKey: kubernetes.io/hostname # Default value
    podAntiAffinityType: preferred # Default value

  storage:
    size: 1Gi

인스턴스 Pod에 적용된 affinity 구성은 다음과 같아요:

affinity:
  podAntiAffinity:
    preferredDuringSchedulingIgnoredDuringExecution:
      - podAffinityTerm:
          labelSelector:
            matchExpressions:
              - key: cnpg.io/cluster
                operator: In
                values:
                  - cluster-example
              - key: cnpg.io/podRole
                operator: In
                values:
                  - instance
          topologyKey: kubernetes.io/hostname
        weight: 100

이 설정으로 쿠버네티스는 충분한 리소스가 있다면 3노드 PostgreSQL 클러스터를 세 개의 서로 다른 노드에 선호적으로 스케줄링해요.

Pod Anti-Affinity 필수로 만들기

위에서 언급한 설정을 조정해서 기본 동작을 바꿀 수 있어요.

예를 들어 podAntiAffinityType을 required로 설정하면 preferredDuringSchedulingIgnoredDuringExecution 대신 requiredDuringSchedulingIgnoredDuringExecution을 강제해요.

하지만 이 엄격한 요구는 리소스가 부족하면 Pod가 pending 상태로 남을 수 있다는 점을 인지하세요. 특히 쿠버네티스 클러스터에서 자동 수평 확장을 위해 Cluster Autoscaler를 사용할 때 관련이 있어요.

:::note[Inter-pod Affinity와 Anti-Affinity] 더 자세한 내용은 쿠버네티스 문서를 참조하세요. :::

토폴로지 고려 사항

클라우드 환경에서는 topologyKey로 topology.kubernetes.io/zone을 사용해서 Pod가 단순히 노드가 아니라 서로 다른 가용 영역(availability zone)에 분산되도록 하는 것을 고려할 수 있어요. 더 많은 옵션은 Well-Known Labels, Annotations, and Taints를 참조하세요.

Anti-Affinity 정책 비활성화

필요하다면 enablePodAntiAffinity를 false로 설정해서 오퍼레이터가 생성한 anti-affinity 정책을 비활성화할 수 있어요.

커스텀 규칙으로 세밀하게 제어하기

더 정밀한 제어가 필요한 시나리오에서는 additionalPodAffinity와 additionalPodAntiAffinity 구성 속성으로 커스텀 pod affinity 또는 anti-affinity 규칙을 지정할 수 있어요. 이 커스텀 규칙들은 활성화된 경우 오퍼레이터가 생성한 규칙에 추가되거나, 오퍼레이터가 생성한 규칙이 비활성화된 경우 직접 사용돼요.

:::note additionalPodAntiAffinity 또는 additionalPodAffinity를 사용할 때는 Pod 사양이 기대하는 완전한 podAntiAffinity 또는 podAffinity 구조를 제공해야 해요. 다음 YAML 예시는 PostgreSQL 클러스터가 무엇이든 관계없이 워커 노드당 PostgreSQL 인스턴스 하나만 구성하는 방법을 보여줘요: :::

    additionalPodAntiAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: postgresql
            operator: Exists
            values: []
        topologyKey: "kubernetes.io/hostname"

nodeSelector를 통한 노드 선택

쿠버네티스는 nodeSelector가 Pod가 실행될 수 있는 노드를 선택하도록 키-값 쌍으로 정의된 레이블 목록을 제공하게 해요. 구체적으로, Pod가 스케줄링되고 실행되려면 노드가 표시된 각 키-값 쌍을 레이블로 가져야 해요.

마찬가지로 CloudNativePG는 affinity 섹션에서 nodeSelector를 정의하게 해주므로, 그 레이블을 가진 노드에서만 PostgreSQL 클러스터가 실행되도록 요청할 수 있어요.

Tolerations

쿠버네티스는 (taints를 통해) 노드가 그 taints를 명시적으로 허용(tolerate)하지 않는 모든 Pod를 격퇴할지 여부를 지정할 수 있게 해줘요.

따라서 특정 노드의 taints와 일치하는 워크로드에 적절한 tolerations 집합을 설정하면, 쿠버네티스 스케줄러는 워크로드를 어느 노드에 스케줄링할지 결정할 때 tainted 노드를 고려하게 돼요. Tolerations는 .spec.affinity.tolerations 섹션을 통해 클러스터의 모든 Pod에 대해 구성할 수 있으며, 이 섹션은 tolerations에 대한 일반적인 쿠버네티스 문법을 받아들여요.

:::note[Taints and Tolerations] taints와 tolerations에 대한 더 많은 정보는 쿠버네티스 문서에서 찾을 수 있어요. :::

PostgreSQL 워크로드 격리

:::info[Important] 진행하기 전에 문서의 "Architecture" 섹션을 읽었는지 확인하세요. :::

PostgreSQL을 쿠버네티스에 다양한 방식으로 배포할 수 있지만, 프로덕션 환경에서는 다음 핵심 원칙을 따르는 것을 권장해요:

  • 가용 영역 활용하기: 가능하면 같은 쿠버네티스 클러스터 안의 가용 영역(AZ)을 활용해서 PostgreSQL 인스턴스를 서로 다른 AZ에 분산해요.
  • 워커 노드 전용화하기: node-role.kubernetes.io/postgres 레이블과 taint를 통해 PostgreSQL 워크로드용 특정 워커 노드를 할당해요. 자세한 내용은 Reserving Nodes for PostgreSQL Workloads 섹션을 참조하세요.
  • 노드 중복 피하기: 같은 PostgreSQL 클러스터의 인스턴스가 같은 노드에서 실행되지 않도록 해요.

이전 섹션에서 자세히 설명했듯이, CloudNativePG는 pod anti-affinity, node selector, tolerations를 구성할 수 있는 유연성을 제공해요.

다음은 PostgreSQL Cluster가 postgres 노드에 배포되고 인스턴스가 서로 다른 노드에 분산되도록 보장하는 샘플 구성이에요:

  # <snip>
  affinity:
    enablePodAntiAffinity: true
    topologyKey: kubernetes.io/hostname
    podAntiAffinityType: required
    nodeSelector:
      node-role.kubernetes.io/postgres: ""
    tolerations:
    - key: node-role.kubernetes.io/postgres
      operator: Exists
      effect: NoSchedule
  # <snip>

단순해 보이지만 이 설정은 PostgreSQL 워크로드의 최적 분산과 격리를 보장해서, 프로덕션 환경의 성능과 안정성을 높여줘요.

더 알아보기 (Learn more)