본문으로 건너뛰기

5.4 Scheduling

Kubernetes scheduler는 Pod를 어느 노드에 올릴지 자동으로 정합니다. 대개는 맡겨 두면 되지만, PostgreSQL 같은 데이터베이스는 배치에 신경 써야 합니다. primary와 replica가 같은 노드에 몰려 있으면 그 노드 하나가 죽는 순간 클러스터 전체가 흔들립니다. CloudNativePG는 .spec.affinity 아래에서 pod anti-affinity, nodeSelector, toleration을 설정해 이런 배치를 통제합니다.

pod anti-affinity 기본 동작​

CNPG는 별도 설정이 없어도 인스턴스를 서로 다른 노드에 나눠 배치하려 합니다. 기본값은 다음과 같습니다.

  • enablePodAntiAffinity: true
  • topologyKey: kubernetes.io/hostname
  • podAntiAffinityType: preferred

이 설정은 같은 클러스터의 인스턴스끼리 서로를 피하는 preferredDuringSchedulingIgnoredDuringExecution 규칙을 생성합니다.

preferred vs required​

anti-affinity를 얼마나 강하게 강제할지가 podAntiAffinityType으로 갈립니다.

유형동작위험
preferred (기본)최대한 분산하되, 여의치 않으면 같은 노드에도 배치없음
required규칙을 강제해 조건을 못 맞추면 Pod를 pending으로 둠자원 부족 시 pending 지속

required로 두면 노드가 부족할 때 Pod가 뜨지 못하고 계속 pending에 머뭅니다. 특히 Cluster Autoscaler를 함께 쓸 때 주의해야 합니다.

경고

podAntiAffinityType: required는 "반드시 서로 다른 노드에"를 강제합니다. 노드 수가 인스턴스 수보다 적거나 자원이 모자라면 Pod가 스케줄되지 못해 pending으로 남습니다. 가용 노드 여유가 확실할 때만 required를 선택합니다.

가용 영역 단위 분산​

클라우드 환경에서는 노드 단위보다 availability zone 단위로 분산하는 편이 낫습니다. topologyKey를 kubernetes.io/hostname 대신 topology.kubernetes.io/zone으로 바꾸면 Pod가 서로 다른 가용 영역에 흩어집니다.

nodeSelector, taint, toleration​

특정 노드에만 PostgreSQL을 올리려면 두 장치를 함께 씁니다.

  • nodeSelector: .spec.affinity 아래에 key-value 라벨을 지정해, 그 라벨을 가진 노드에만 Pod를 배치합니다. "여기에만 올려라"라는 조건입니다.
  • taint·toleration: taint는 노드가 "특정 조건을 견디는(tolerate) Pod만 받겠다"고 거는 표식이고, toleration은 Pod가 그 taint를 견딘다는 선언입니다. 데이터베이스 전용 노드를 만들어 다른 워크로드가 침범하지 못하게 할 때 씁니다.

전용 노드에 클러스터를 격리하는 구성은 다음과 같습니다.

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

이 설정은 postgres 전용 노드에만 PostgreSQL을 올리고(nodeSelector + toleration), 인스턴스들을 서로 다른 노드에 강제 분산합니다(required anti-affinity).

규칙 비활성화·커스터마이징​

enablePodAntiAffinity: false로 두면 Operator가 만드는 anti-affinity 정책을 끕니다. 기본 규칙을 보완하거나 대체하는 커스텀 규칙이 필요하면 additionalPodAffinity·additionalPodAntiAffinity를 씁니다. 아래 예시는 모든 클러스터를 통틀어 워커 노드당 PostgreSQL 인스턴스를 하나만 허용합니다.

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

additionalPodAntiAffinity는 CNPG가 자동 생성하는 규칙에 더해 적용됩니다. 기본 규칙을 완전히 대체하려면 enablePodAntiAffinity: false로 자동 규칙을 끈 뒤 커스텀 규칙만 남기는 편이 예측하기 쉽습니다.

여기까지가 스토리지와 리소스 파트입니다. PVC와 WAL 볼륨 분리로 데이터를 안전하게 담고, requests/limits와 QoS로 자원을 확보하며, tablespace로 데이터를 나누고, affinity·taint로 Pod를 원하는 노드에 배치하는 흐름을 짚었습니다. 이 네 가지는 운영 환경 클러스터를 설계할 때 함께 맞물려 결정됩니다.