본문으로 건너뛰기
김신건의 로그

[Kubernetes] Scheduling (Taints, Affinity, Topology Spread)

· 수정 · 📖 약 3분 · 1,050자/단어 #kubernetes #scheduling #affinity #taints #topology
Kubernetes Scheduling, k8s scheduling, Taints and Tolerations, Node Affinity, Pod Affinity, Pod Anti-Affinity, Topology Spread Constraints, kube-scheduler policy, 쿠버네티스 스케줄링, PodDisruptionBudget

정의

Kubernetes Scheduling 은 kube-scheduler 가 새 Pod 을 어느 노드에 배치할지 결정하는 과정입니다. 두 단계 (Filtering + Scoring), 여러 정책 (nodeSelector, Affinity, Taints/Tolerations, Topology Spread, PriorityClass) 을 조합해 세밀한 배치 제어를 제공합니다.

기본 흐름

flowchart LR
  P[새 Pod] --> F[Filtering]
  F -->|후보 노드| S[Scoring]
  S -->|최고 점수| N[선정 노드]

Filtering (predicates)

노드가 Pod 실행 조건 만족하는지 검사:

  • 리소스 여유 (CPU, memory)
  • nodeSelector / nodeAffinity 매치
  • Taints 를 tolerate
  • Volume affinity (AZ 매치)
  • Port 충돌 없음
  • 노드 상태 Ready

Scoring (priorities)

살아남은 노드에 점수 (0-100):

  • LeastRequested: request 여유 많은 노드 선호
  • BalancedResourceAllocation: CPU/memory 균형
  • NodeAffinity preferred: 선호도 매치
  • InterPodAffinity preferred
  • ImageLocality: 이미지 이미 있는 노드
  • TopologySpread: 균형 분산

nodeSelector (가장 단순)

apiVersion: v1
kind: Pod
metadata:
  name: gpu-workload
spec:
  nodeSelector:
    accelerator: nvidia
    disktype: ssd
  containers: [...]

노드에 라벨이 있어야 매치. 정확히 이 라벨을 가진 노드에만 배치.

단점: AND 만 지원. 유연성 낮음. 신규 코드는 Node Affinity 권장.

Node Affinity

requiredDuringScheduling (hard)

affinity:
  nodeAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
      nodeSelectorTerms:
        - matchExpressions:
            - key: topology.kubernetes.io/zone
              operator: In
              values: [us-east-1a, us-east-1b]
            - key: node-type
              operator: NotIn
              values: [spot]

만족 못 하면 스케줄 안 됨. IgnoredDuringExecution 은 실행 중 노드 라벨 바뀌어도 evict 안 함.

preferredDuringScheduling (soft)

affinity:
  nodeAffinity:
    preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 100
        preference:
          matchExpressions:
            - key: instance-type
              operator: In
              values: [m5.large]
      - weight: 50
        preference:
          matchExpressions:
            - key: zone
              operator: In
              values: [us-east-1a]

선호도. 완벽 매치 못 해도 스케줄됨.

Operators

  • In, NotIn: 값 목록
  • Exists, DoesNotExist: 라벨 존재 여부
  • Gt, Lt: 숫자 비교

Pod Affinity / Anti-Affinity

Pod Affinity (다른 Pod 옆에)

같은 노드/AZ 에 있는 다른 Pod 옆에 배치. 캐시 지역성, 통신 지연 최소화.

affinity:
  podAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchLabels:
            app: cache
        topologyKey: kubernetes.io/hostname   # 같은 노드

topologyKey: 어느 단위 (호스트, zone, region) 로 판단.

Pod Anti-Affinity (다른 Pod 피해)

같은 노드/AZ 에 없어야. HA 의 핵심.

affinity:
  podAntiAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchLabels:
            app: web
        topologyKey: kubernetes.io/hostname

app: web Pod 이 같은 노드에 있으면 스케줄 실패. Replica 를 여러 노드에 강제 분산.

AZ 분산:

topologyKey: topology.kubernetes.io/zone

각 AZ 에 최대 하나. 3 AZ + 3 replica 면 각 zone 1개.

주의: required anti-affinity 는 스케줄러가 O(N^2) 검사. 큰 클러스터에서 느림. 대안: Topology Spread.

Topology Spread Constraints

topologySpreadConstraints:
  - maxSkew: 1
    topologyKey: topology.kubernetes.io/zone
    whenUnsatisfiable: DoNotSchedule
    labelSelector:
      matchLabels:
        app: web

각 zone 의 Pod 수 차이 (skew) 가 maxSkew 이하가 되도록. app: web Pod 이 zone A 에 5개, B 에 4개인데 새 pod 추가하면 A 에는 못 감 (skew 2 초과).

whenUnsatisfiable:

  • DoNotSchedule (hard): 불만족이면 pending
  • ScheduleAnyway (soft): 조건 안 맞아도 스케줄

Anti-affinity 보다 성능 좋고 유연. HA + 균형 분산의 표준.

Taints and Tolerations

Taint 는 노드에 붙이는 “특정 Pod 만 허용” 표시. Toleration 은 Pod 이 taint 를 견딜 수 있다는 선언.

Taint 부여

kubectl taint nodes node1 dedicated=gpu:NoSchedule
kubectl taint nodes node1 spot=true:PreferNoSchedule
kubectl taint nodes node1 out-of-service:NoExecute

Effect

  • NoSchedule: 매치 안 되는 Pod 은 스케줄 안 됨 (기존 Pod 은 유지)
  • PreferNoSchedule: soft 버전
  • NoExecute: 매치 안 되는 기존 Pod evict + 새 Pod 안 옴

Toleration

tolerations:
  - key: dedicated
    operator: Equal
    value: gpu
    effect: NoSchedule
  - key: spot
    operator: Exists                # 값 무관, 키만 매치
    effect: PreferNoSchedule
  - key: out-of-service
    operator: Exists
    effect: NoExecute
    tolerationSeconds: 300           # evict 유예 (초)

관용

  • dedicated=team-x:NoSchedule: 특정 팀 전용 노드
  • nvidia.com/gpu:NoSchedule: GPU 노드 (Karpenter, GPU Operator 자동)
  • node.kubernetes.io/unreachable:NoExecute: 시스템 taint, unreachable 노드
  • node.kubernetes.io/not-ready:NoExecute: NotReady 노드

PodDisruptionBudget (PDB)

Voluntary disruption (Drain, PDB 존중 rolling update 등) 중 최소 실행 Pod 수 보장.

apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: web-pdb
spec:
  minAvailable: 2       # 항상 2개 이상 실행
  # 또는
  maxUnavailable: 1     # 최대 1개만 죽어도 됨
  selector:
    matchLabels:
      app: web

kubectl drain 시 PDB 위반될 pod 은 evict 안 함.

주의: PDB 는 voluntary 만 적용. Node crash, kernel OOM 등 involuntary 는 못 막음.

Priority & Preemption

높은 priority Pod 이 낮은 priority Pod 을 evict.

apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
  name: prod-critical
value: 1000000
description: "Production critical workloads"
spec:
  priorityClassName: prod-critical
  • System critical: system-cluster-critical (2 000 000 000), system-node-critical (2 000 001 000)
  • User: 0 ~ 1 000 000 000 권장

nodeName (강제 지정, 지양)

spec:
  nodeName: node1

스케줄러 우회. 노드 이름 하드코딩 => 확장성 없음. 개발/디버깅만.

스케줄러 확장

  • Scheduling Framework: 커스텀 plugin (필터, 스코어 등) 삽입
  • Multiple Schedulers: spec.schedulerName 으로 다른 스케줄러 선택
  • Volcano: 배치/ML 워크로드 스케줄러
  • Karpenter (AWS/Azure): 노드 프로비저닝 스케줄러 (kube-scheduler 보완)

실전 패턴

HA 웹앱 (3 replica, 3 AZ 분산)

spec:
  replicas: 3
  template:
    spec:
      topologySpreadConstraints:
        - maxSkew: 1
          topologyKey: topology.kubernetes.io/zone
          whenUnsatisfiable: DoNotSchedule
          labelSelector:
            matchLabels:
              app: web
      affinity:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
            - weight: 100
              podAffinityTerm:
                labelSelector:
                  matchLabels:
                    app: web
                topologyKey: kubernetes.io/hostname

zone 균등 + 같은 노드 회피 (soft).

GPU 워크로드 (전용 노드)

spec:
  nodeSelector:
    accelerator: nvidia-tesla-t4
  tolerations:
    - key: nvidia.com/gpu
      operator: Exists
      effect: NoSchedule
  containers:
    - name: trainer
      resources:
        limits:
          nvidia.com/gpu: 1

Spot 노드 (비용 절감)

spec:
  nodeSelector:
    node-type: spot
  tolerations:
    - key: spot
      operator: Exists
      effect: PreferNoSchedule

함정

WARNING

Anti-affinity required + 대규모 클러스터 = 스케줄러 성능 저하. Topology Spread 로 대체.

CAUTION

AZ 3개 + replica 4 개maxSkew: 1 이면 균등 분산 불가. 조합 수학 확인.

WARNING

Taint 잘못 걸면 시스템 pod 도 못 뜸. NoExecute 는 특히 위험. Test cluster 에서 검증.

IMPORTANT

PDB 는 rolling update 를 막을 수도 있음. 항상 maxUnavailable 이 replica 총합보다 작아야 rolling 가능.

CAUTION

nodeName 하드코딩 지양. Pod 이 오직 그 노드에 만. 노드 죽으면 재스케줄 없음.

관련 위키

이 글의 용어 (10개)
[K8s] DaemonSet: 모든 노드에 한 podkubernetes
정의 DaemonSet 은 클러스터의 각 노드에 정확히 1개의 Pod 을 보장하는 워크로드 리소스. 노드가 추가되면 자동으로 Pod 가 배포되고, 노드가 제거되면 자동으로 정리된…
[K8s] Deployment: ReplicaSet, rolling update, rollbackkubernetes
정의 Deployment = stateless 워크로드를 위한 컨트롤러. 내부적으로 ReplicaSet 관리 + rolling update / rollback. 사용 시나리오 |…
[K8s] Pod: 컨테이너의 최소 단위, sidecar, lifecyclekubernetes
정의 Pod = K8s 의 가장 작은 배포 단위. 1개 이상의 컨테이너 + 공유 네트워크 + 공유 스토리지. [!IMPORTANT] Pod 는 컨테이너의 wrapping 이 아니…
[K8s] StatefulSet: 순서 보장, 고유 ID, 영속 스토리지kubernetes
정의 StatefulSet = 상태 있는 워크로드를 위한 컨트롤러. Deployment 와의 차이: | 항목 | Deployment | StatefulSet | |---|---|…
[Kubernetes] Architecture (Control Plane + Node)kubernetes
정의 Kubernetes Architecture 는 Control Plane (제어) 과 Worker Node (실행) 두 계층으로 구성됩니다. Control Plane 은 원하…
[Kubernetes] Labels & Selectorskubernetes
정의 Labels 는 리소스에 붙이는 key-value 분류 태그 입니다. 사람과 컨트롤러가 리소스를 조직하고 선택할 때 사용합니다. Selectors 는 label 조합으로 대…
[Kubernetes] Namespacekubernetes
정의 Namespace 는 같은 물리 클러스터 안에서 리소스 (Pod, Service, ConfigMap 등) 를 논리적으로 격리 하는 단위입니다. 이름 충돌 회피, RBAC 스…
[Kubernetes] Persistent Volumes (PV / PVC / StorageClass)kubernetes
정의 Kubernetes Storage 계층 은 세 리소스로 구성됩니다. - PersistentVolume (PV): 실제 스토리지 (EBS, GCE PD, NFS, iSCSI …
[Kubernetes] Resource Management (Requests, Limits, QoS)kubernetes
정의 Kubernetes Resource Management 는 CPU, 메모리, ephemeral storage, hugepages 등의 리소스를 파드에 할당하고 제한하는 시스…
Kuberneteskubernetes
정의 Kubernetes (k8s) 는 컨테이너화된 애플리케이션의 배포, 스케일링, 관리 를 자동화하는 오픈소스 오케스트레이터입니다. Google 이 2014년 발표하고 2015…

💬 댓글

사이트 검색 / 명령어

검색

스크롤 = 확대/축소 · 드래그 = 이동 · 0 = 원래 크기 · ESC = 닫기