Kubernetes Taints 與 Tolerations

Kubernetes Taints and Tolerations Configuration

概述

在 Kubernetes 中,TaintsTolerations 是一組強大的機制,用於控制 Pod 可以被調度到哪些節點上。Taints 設定在節點上,用於排斥特定的 Pod;而 Tolerations 則設定在 Pod 上,允許 Pod 被調度到具有相應 Taint 的節點。

這種機制與 Node Affinity 不同:Node Affinity 是吸引 Pod 到特定節點,而 Taints 則是排斥 Pod 離開特定節點。兩者可以搭配使用,實現更精細的調度控制。

Taint 效果類型

Kubernetes 支援三種 Taint 效果(Effect):

效果類型說明
NoSchedule新的 Pod 不會被調度到該節點,但已存在的 Pod 不受影響
PreferNoSchedule軟性限制,調度器會盡量避免將 Pod 調度到該節點,但非強制
NoExecute新的 Pod 不會被調度,且已存在且不容忍該 Taint 的 Pod 會被驅逐

為節點新增 Taint

使用 kubectl taint 命令為節點新增 Taint:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# 新增 Taint
kubectl taint nodes node1 key=value:NoSchedule

# 範例:標記節點為專用 GPU 節點
kubectl taint nodes gpu-node-01 gpu=true:NoSchedule

# 範例:標記節點正在維護中
kubectl taint nodes node1 maintenance=true:NoExecute

# 移除 Taint(在結尾加上減號)
kubectl taint nodes node1 key=value:NoSchedule-

# 查看節點的 Taints
kubectl describe node node1 | grep -A 5 Taints

Pod Tolerations 設定

在 Pod 的 spec 中加入 tolerations 欄位,讓 Pod 能夠容忍特定的 Taint:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
spec:
  containers:
  - name: nginx
    image: nginx:1.24
  tolerations:
  - key: "gpu"
    operator: "Equal"
    value: "true"
    effect: "NoSchedule"

Deployment 中的 Tolerations 設定

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
apiVersion: apps/v1
kind: Deployment
metadata:
  name: gpu-workload
spec:
  replicas: 3
  selector:
    matchLabels:
      app: gpu-app
  template:
    metadata:
      labels:
        app: gpu-app
    spec:
      containers:
      - name: gpu-container
        image: nvidia/cuda:12.0-base
        resources:
          limits:
            nvidia.com/gpu: 1
      tolerations:
      - key: "gpu"
        operator: "Equal"
        value: "true"
        effect: "NoSchedule"
      - key: "dedicated"
        operator: "Equal"
        value: "gpu-workloads"
        effect: "NoSchedule"

運算子(Operator)

Tolerations 支援兩種運算子:

Equal 運算子

Equal 運算子要求 key、value 和 effect 必須完全匹配:

1
2
3
4
5
tolerations:
- key: "environment"
  operator: "Equal"
  value: "production"
  effect: "NoSchedule"

Exists 運算子

Exists 運算子只檢查 key 是否存在,不需要指定 value:

1
2
3
4
5
6
7
8
tolerations:
# 容忍所有具有 key "dedicated" 的 Taint
- key: "dedicated"
  operator: "Exists"
  effect: "NoSchedule"

# 容忍所有 Taint(萬用設定)
- operator: "Exists"

常見使用場景

1. 專用節點(Dedicated Nodes)

為特定工作負載保留專用節點:

1
2
3
# 標記專用節點
kubectl taint nodes dedicated-node dedicated=special-user:NoSchedule
kubectl label nodes dedicated-node dedicated=special-user
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
apiVersion: v1
kind: Pod
metadata:
  name: special-workload
spec:
  containers:
  - name: app
    image: myapp:latest
  tolerations:
  - key: "dedicated"
    operator: "Equal"
    value: "special-user"
    effect: "NoSchedule"
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: dedicated
            operator: In
            values:
            - special-user

2. 節點維護

進行節點維護時,先驅逐現有 Pod:

1
2
3
4
5
# 標記節點進入維護模式
kubectl taint nodes node1 maintenance=true:NoExecute

# 維護完成後移除 Taint
kubectl taint nodes node1 maintenance=true:NoExecute-

3. 容忍驅逐的寬限期

使用 tolerationSeconds 設定 Pod 被驅逐前的等待時間:

1
2
3
4
5
tolerations:
- key: "node.kubernetes.io/unreachable"
  operator: "Exists"
  effect: "NoExecute"
  tolerationSeconds: 300

與 Node Affinity 結合

結合 Taints/Tolerations 與 Node Affinity 可實現更精確的調度:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
apiVersion: apps/v1
kind: Deployment
metadata:
  name: high-priority-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: high-priority
  template:
    metadata:
      labels:
        app: high-priority
    spec:
      containers:
      - name: app
        image: myapp:latest
      tolerations:
      - key: "tier"
        operator: "Equal"
        value: "critical"
        effect: "NoSchedule"
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: tier
                operator: In
                values:
                - critical
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 100
            podAffinityTerm:
              labelSelector:
                matchLabels:
                  app: high-priority
              topologyKey: kubernetes.io/hostname

內建 Taints

Kubernetes 會自動為節點新增某些內建 Taints:

Taint Key說明
node.kubernetes.io/not-ready節點尚未就緒
node.kubernetes.io/unreachable節點無法連線
node.kubernetes.io/memory-pressure節點記憶體壓力過大
node.kubernetes.io/disk-pressure節點磁碟壓力過大
node.kubernetes.io/pid-pressure節點 PID 資源不足
node.kubernetes.io/network-unavailable節點網路不可用
node.kubernetes.io/unschedulable節點被標記為不可調度

DaemonSet Controller 預設會為 DaemonSet Pod 自動加入對這些內建 Taint 的容忍。

最佳實踐

  1. 明確命名規範:使用有意義的 key 和 value,例如 dedicated=gpu-workloads 而非 d=g

  2. 搭配標籤使用:Taints 通常應搭配對應的 Node Labels 和 Node Affinity 使用,確保 Pod 不只是「可以」調度到節點,而是「必須」調度到節點

  3. 謹慎使用 NoExecute:此效果會驅逐現有 Pod,在生產環境中需謹慎評估影響

  4. 設定 tolerationSeconds:對於 NoExecute 類型的 Taint,考慮設定合理的寬限期

  5. 文件化:將叢集中使用的 Taints 記錄在文件中,方便團隊成員查閱

  6. 定期檢視:定期檢查節點上的 Taints,移除不再需要的設定

1
2
# 列出所有節點的 Taints
kubectl get nodes -o custom-columns=NAME:.metadata.name,TAINTS:.spec.taints

參考資料

comments powered by Disqus
Built with Hugo
Theme Stack designed by Jimmy