前言
Kubernetes 的調度機制中,污點(Taint)和容忍度(Toleration)是控制 Pod 落在哪些節點上的重要手段。一句話總結:如果 Pod 能容忍某個節點上的污點,它就可以被調度到該節點;不能容忍,就不會被調度過去。
打個比方,就像談戀愛——如果你知道對方的缺點但還是願意接受,那就可以在一起;無法接受的話,就沒辦法了。
核心觀念
污點與容忍度的定義
| 名詞 | 定義在 | 作用 |
|---|---|---|
| 污點(Taint) | 節點上 | 拒絕不具備對應容忍度的 Pod 調度到此節點 |
| 容忍度(Toleration) | Pod 上 | 讓 Pod 可以被調度到帶有特定污點的節點 |
三種排斥等級(Effect)
| 等級 | 對新 Pod 的影響 | 對已存在 Pod 的影響 |
|---|---|---|
NoSchedule |
不能調度到此節點 | 不受影響 |
PreferNoSchedule |
盡量不調度,但找不到其他節點時還是會 | 不受影響 |
NoExecute |
不能調度到此節點 | 已存在的 Pod 會被驅逐 |
兩種操作符
| 操作符 | 比對方式 |
|---|---|
Equal |
key、value、effect 三者完全匹配 |
Exists |
只比對 key 和 effect,value 留空 |
污點的語法格式:key=value:effect
常見使用場景
場景 1:節點獨佔
叢集中有些機器配備特殊硬體(如 GPU、大記憶體),不希望一般的 Pod 佔用這些節點。做法:
- 給特殊節點加上污點
- 只有需要這些資源的 Pod 才設定對應的容忍度
場景 2:自動驅逐
K8s 會自動在問題節點上打污點,例如:
| 內建污點 | 觸發條件 |
|---|---|
node.kubernetes.io/not-ready |
節點未就緒 |
node.kubernetes.io/unreachable |
節點不可達 |
node.kubernetes.io/memory-pressure |
記憶體不足 |
node.kubernetes.io/disk-pressure |
磁碟空間不足 |
node.kubernetes.io/network-unavailable |
網路不可用 |
這些污點會使用 NoExecute 等級,導致沒有對應容忍度的 Pod 被驅逐。DaemonSet 控制器會自動忽略這類污點,確保重要的系統 Pod 持續運行。
實戰操作
管理節點污點
# 加入污點
kubectl taint nodes node01 key=value:NoSchedule
# 刪除污點(key 後面加減號)
kubectl taint nodes node01 key:NoSchedule-
# 刪除某 key 的所有污點(不指定 effect)
kubectl taint nodes node01 key-
查看節點資訊
# 查看節點 label
kubectl get nodes --show-labels
# 查看節點詳細資訊(包含 Taints)
kubectl describe node <node-name>
# 加入節點 label
kubectl label node <node-name> special-app=specialwebapp
完整實戰流程
步驟 1:給節點加上污點
kubectl taint nodes k8s-worker-2 question-node=broken-disk:NoSchedule
步驟 2:部署 Pod(不含容忍度)→ Pod 會卡在 Pending
查看原因:kubectl describe pod <pod-name> 會看到 "node(s) had taints that the pod didn't tolerate"
步驟 3:加上容忍度後重新部署 → 調度成功
完整的 Pod YAML:
apiVersion: v1
kind: Pod
metadata:
name: webapp
namespace: demo
labels:
app: webapp
spec:
nodeSelector:
special-app: specialwebapp
tolerations:
- key: "question-node"
operator: "Equal"
value: "broken-disk"
effect: "NoSchedule"
containers:
- name: webapp
image: nginx
ports:
- containerPort: 80
延遲驅逐:tolerationSeconds
當污點等級是 NoExecute 時,已存在的 Pod 會被立刻驅逐。但你可以用 tolerationSeconds 設定一個寬限時間:
tolerations:
- key: "question-node"
operator: "Equal"
value: "broken-disk"
effect: "NoExecute"
tolerationSeconds: 3600 # Pod 還能繼續運行 3600 秒
這在節點短暫出問題但可能很快恢復的場景下非常實用。
小結
污點和容忍度是 K8s 調度機制中非常重要的一環。核心規則就一條:Pod 必須容忍節點的污點才能被調度上去。善用 NoSchedule、PreferNoSchedule、NoExecute 三種等級,搭配節點 label 和 nodeSelector,你就能精確控制 Pod 的調度行為。

發佈留言