Kubernetes Taints &

Taints와 Tolerations가 해결하는 문제: 노드에 Pod를 “밀어내는” 메커니즘

Kubernetes 스케줄러는 기본적으로 모든 노드에 Pod를 배치할 수 있다. 하지만 GPU 노드에 일반 워크로드가 올라가거나, 마스터 노드에 애플리케이션 Pod가 스케줄되면 안 되는 경우가 있다. Taint는 노드에 “이 노드는 특별하다”는 표식을 남기고, 해당 Taint를 Toleration으로 “견딜 수 있는” Pod만 스케줄되도록 하는 메커니즘이다.

Kubernetes 공식 문서는 Taints를 “노드가 특정 Pod 집합을 거부할 수 있게 하는 것”으로 정의한다. Node Affinity가 Pod를 특정 노드에 끌어당기는(attract) 것이라면, Taints는 Pod를 노드에서 밀어내는(repel) 것이다. 이 글에서는 Taint의 세 가지 Effect, Toleration 매칭 규칙, 그리고 운영 패턴을 공식 문서 기반으로 정리한다.

Taint의 구조: Key=Value:Effect

# 노드에 Taint 추가
kubectl taint nodes node1 dedicated=gpu:NoSchedule

# Taint 확인
kubectl describe node node1 | grep Taints
# Taints: dedicated=gpu:NoSchedule

# Taint 제거 (끝에 - 붙이기)
kubectl taint nodes node1 dedicated=gpu:NoSchedule-
Effect 동작 이미 실행 중인 Pod 사용 시점
NoSchedule Toleration 없는 Pod 스케줄 거부 영향 없음 (계속 실행) 전용 노드 분리 (GPU, DB)
PreferNoSchedule 가능하면 스케줄 회피 (강제 아님) 영향 없음 소프트 분리 (다른 노드가 있으면 그쪽 우선)
NoExecute 스케줄 거부 + 기존 Pod 축출(evict) 축출됨 (Toleration 없으면) 노드 유지보수, 장애 노드 격리

Toleration 문법: Pod가 Taint를 견디는 선언

# Pod (또는 Deployment) spec에 tolerations 추가
apiVersion: apps/v1
kind: Deployment
metadata:
  name: gpu-worker
spec:
  template:
    spec:
      tolerations:
      - key: "dedicated"
        operator: "Equal"
        value: "gpu"
        effect: "NoSchedule"
      containers:
      - name: worker
        image: gpu-worker:latest

operator: Equal vs Exists

operator 매칭 조건 value 필요 예시
Equal (기본) key, value, effect 모두 일치 key: "dedicated", value: "gpu", effect: "NoSchedule"
Exists key만 일치 (value 무시) key: "dedicated", operator: "Exists", effect: "NoSchedule"

와일드카드 Toleration

# 특정 key의 모든 value와 effect를 견딤
tolerations:
- key: "dedicated"
  operator: "Exists"          # value 생략 → 모든 value 매칭
                               # effect 생략 → 모든 effect 매칭

# 모든 Taint를 견디는 "만능" Toleration (DaemonSet에서 자주 사용)
tolerations:
- operator: "Exists"          # key도 생략 → 모든 Taint 매칭

NoExecute와 tolerationSeconds: 유예 시간

NoExecute Taint가 추가되면 Toleration이 없는 기존 Pod는 즉시 축출된다. Toleration에 tolerationSeconds를 지정하면 해당 시간 동안은 노드에 머무를 수 있다.

tolerations:
- key: "node.kubernetes.io/unreachable"
  operator: "Exists"
  effect: "NoExecute"
  tolerationSeconds: 300      # 5분간 유예 후 축출

# 사용 시나리오:
# 노드 네트워크 장애 시 Pod가 즉시 다른 노드로 이동하면 불필요한 재시작이 발생
# tolerationSeconds로 일시적 장애를 견디고, 지속되면 축출

공식 문서에 따르면 tolerationSeconds를 지정하지 않으면 해당 Taint를 영구히 견딘다(축출 안 됨). 0으로 지정하면 즉시 축출된다.

Kubernetes가 자동으로 추가하는 Taint (Built-in Taints)

Kubernetes는 노드 상태에 따라 자동으로 Taint를 추가한다. 공식 문서에 명시된 주요 빌트인 Taint는 다음과 같다.

Taint Key Effect 발생 조건
node.kubernetes.io/not-ready NoExecute 노드가 Ready 상태가 아닐 때
node.kubernetes.io/unreachable NoExecute 노드가 컨트롤 플레인과 통신 불가
node.kubernetes.io/memory-pressure NoSchedule 노드 메모리 부족
node.kubernetes.io/disk-pressure NoSchedule 노드 디스크 부족
node.kubernetes.io/pid-pressure NoSchedule 노드 PID 부족
node.kubernetes.io/unschedulable NoSchedule kubectl cordon 실행 시

Kubernetes는 기본적으로 모든 Pod에 not-readyunreachable에 대한 Toleration을 tolerationSeconds: 300으로 자동 추가한다. 즉, 노드 장애 후 5분간 유예한다.

Taint + Toleration + Node Affinity 조합

중요: Toleration은 “이 노드에 스케줄해도 된다”는 허용일 뿐, “이 노드에 반드시 스케줄하라”는 강제가 아니다. GPU Toleration이 있는 Pod가 일반 노드에 스케줄될 수 있다. 전용 노드에 반드시 배치하려면 Taint + Toleration + Node Affinity를 함께 사용해야 한다.

# GPU 전용 노드 설정
# 1. 노드에 Taint + Label 추가
kubectl taint nodes gpu-node-1 dedicated=gpu:NoSchedule
kubectl label nodes gpu-node-1 node-type=gpu

# 2. Pod에 Toleration + Node Affinity
apiVersion: apps/v1
kind: Deployment
metadata:
  name: ml-training
spec:
  template:
    spec:
      tolerations:
      - key: "dedicated"
        operator: "Equal"
        value: "gpu"
        effect: "NoSchedule"
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: node-type
                operator: In
                values:
                - gpu
      containers:
      - name: trainer
        image: ml-trainer:latest
        resources:
          limits:
            nvidia.com/gpu: 1
메커니즘 역할 단독 사용 시 한계
Taint + Toleration 일반 Pod를 전용 노드에서 밀어냄 전용 Pod가 일반 노드에 갈 수 있음
Node Affinity Pod를 특정 노드로 끌어당김 일반 Pod가 전용 노드에 올라갈 수 있음
Taint + Affinity 조합 완전한 전용 노드 격리

DaemonSet과 Taint: 모든 노드에 배포해야 하는 경우

# 모니터링 에이전트 DaemonSet — 모든 Taint를 견딤
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: node-exporter
spec:
  template:
    spec:
      tolerations:
      - operator: "Exists"     # 모든 Taint 허용
      containers:
      - name: exporter
        image: prom/node-exporter:latest

DaemonSet은 모든 노드에 Pod를 배치해야 하므로, operator: "Exists"로 모든 Taint를 견디는 것이 일반적이다. Kubernetes 시스템 DaemonSet(kube-proxy, CNI 등)은 빌트인 Taint에 대한 Toleration을 자동으로 갖는다.

실전 체크리스트: Taints & Tolerations 설계 7단계

  1. 전용 노드 식별 — GPU, 고메모리, SSD 등 특수 노드에 Taint를 추가해 일반 워크로드를 차단
  2. Toleration + Node Affinity 조합 — Toleration만으로는 전용 노드 강제 배치가 안 됨, 반드시 Affinity와 함께
  3. NoSchedule vs NoExecute 선택 — 기존 Pod를 유지하려면 NoSchedule, 즉시 축출하려면 NoExecute
  4. tolerationSeconds 설정 — 노드 장애 시 Pod 축출 유예 시간을 워크로드 특성에 맞게 조정
  5. DaemonSet에 와일드카드 Toleration — 모니터링, 로깅 에이전트는 operator: Exists
  6. 빌트인 Taint 인지 — not-ready, unreachable의 기본 300초 유예를 이해하고 필요시 조정
  7. kubectl describe node로 확인 — Taint가 의도대로 적용되었는지 반드시 검증

흔한 실수 4가지와 방지법

실수 1: Toleration만 추가하고 Pod가 전용 노드에 배치되길 기대

증상: GPU Toleration이 있는 Pod가 일반 노드에 스케줄된다.

방지: Toleration은 “갈 수 있다”일 뿐 “가야 한다”가 아니다. 전용 노드 배치를 강제하려면 Node Affinity의 requiredDuringSchedulingIgnoredDuringExecution를 함께 사용한다.

실수 2: Taint의 key/value/effect를 Toleration과 정확히 맞추지 않음

증상: Toleration을 추가했는데 여전히 Pending 상태로 스케줄되지 않는다. kubectl describe podnode(s) had taint 메시지.

방지: operator: Equal이면 key, value, effect가 모두 정확히 일치해야 한다. 오타를 방지하려면 operator: Exists로 key만 매칭하는 것도 방법이다.

실수 3: NoExecute Taint 추가 시 기존 Pod 축출을 예상하지 못함

증상: 유지보수를 위해 Taint를 추가했더니 해당 노드의 모든 Pod가 즉시 종료되어 서비스 장애 발생.

방지: NoExecute는 기존 Pod를 축출한다. NoSchedule로 먼저 새 Pod 배치를 막고, kubectl drain으로 기존 Pod를 안전하게 이동시킨 후 유지보수한다.

실수 4: 빌트인 Taint의 기본 tolerationSeconds를 무시

증상: 노드 네트워크 순간 단절 후 5분 뒤에 Pod가 다른 노드로 이동하면서 불필요한 재시작.

방지: Stateful 워크로드(DB 등)는 not-ready/unreachable의 tolerationSeconds를 늘려(예: 600~1800초) 순간 장애를 견디게 한다. Stateless 워크로드는 기본값(300초) 또는 더 줄여 빠른 복구를 유도한다.

마무리

Taints & Tolerations는 Kubernetes 스케줄링의 “밀어내기” 메커니즘이다. NoSchedule로 새 Pod를 차단하고, NoExecute로 기존 Pod까지 축출하며, PreferNoSchedule로 소프트 분리를 구현한다. 전용 노드 격리는 Taint + Node Affinity 조합이 필수이고, DaemonSet은 와일드카드 Toleration으로 모든 노드에 배포한다. 이 글의 모든 내용은 Kubernetes 공식 문서(Taints and Tolerations)를 근거로 한다.

위로 스크롤
WordPress Appliance - Powered by TurnKey Linux