DAY17 介紹了 Kubernetes 如何替 Pod 選擇合適的 Node。除了透過 nodeSelector 指定 Pod 可以前往哪些 Node,也可以反過來限制 Node 不要接收某些 Pod。
Kubernetes 使用 Taint(污點) 和 Toleration(容忍) 控制這件事:
例如,管理者可以在有 GPU 的 Node 上設定 Taint,避免一般 Pod 排到這些 Node;需要 GPU 的 Pod 除了設定對應的 Toleration,還要在資源設定中請求 GPU。
Taint 由 key、value 和 effect 組成,常見格式如下:
key=value:effect
例如:
kubectl taint nodes minikube-m02 dedicated=app:NoSchedule
這會在 minikube-m02 上設定 dedicated=app:NoSchedule。沒有相符 Toleration 的新 Pod,就不會被排程到這個 Node。
Kubernetes 有三種常見的 effect:
| effect | 作用 |
|---|---|
NoSchedule |
不讓沒有相符 Toleration 的新 Pod 排到這個 Node;已在執行的 Pod 不會因此被移除。 |
PreferNoSchedule |
盡量避免將沒有相符 Toleration 的 Pod 排到這個 Node,但不保證一定避開。 |
NoExecute |
沒有相符 Toleration 的 Pod 不會排到這個 Node;已在執行的 Pod 也會被移除。 |
NoExecute 的 Toleration 可以設定 tolerationSeconds,指定 Pod 在被移除前可以繼續留在 Node 上多久。
Toleration 設定在 Pod 的 spec 中。下面的設定會容忍 dedicated=app:NoSchedule:
tolerations:
- key: "dedicated"
operator: "Equal"
value: "app"
effect: "NoSchedule"
operator: "Equal" 表示 key 和 value 都要相符;operator: "Exists" 則表示只要指定的 key 存在即可,不檢查 value。
要注意的是,Toleration 只代表 Pod 可以 排到有相符 Taint 的 Node,並不代表它一定會被排到那裡。排程器還會考慮其他條件。因此,如果希望 Pod 只使用特定 Node,通常還要搭配 nodeSelector 或 Node Affinity。
可以把兩者的差異簡單理解為:
nodeSelector:指定 Pod 可以選擇哪些 Node。以下範例會讓沒有相符 Toleration 的 Pod 無法排到 minikube-m02
先在 Node 上加上 Label 和 Taint:
kubectl label nodes minikube-m02 dedicated=app
kubectl taint nodes minikube-m02 dedicated=app:NoSchedule
建立一個沒有 Toleration 的 Pod:
apiVersion: v1
kind: Pod
metadata:
name: taint-demo-denied
spec:
nodeSelector:
dedicated: app
containers:
- name: taint-demo
image: busybox
command: ["sh", "-c", "sleep 3600"]
套用設定並查看 Pod:
kubectl apply -f taint-demo-denied.yaml
kubectl describe pod taint-demo-denied
因為 nodeSelector 指定 Pod 只能排到 minikube-m02,但這個 Node 有 NoSchedule Taint,而 Pod 沒有相符的 Toleration,所以 Pod 會停留在 Pending。
接著建立有 Toleration 的 Pod:
apiVersion: v1
kind: Pod
metadata:
name: taint-demo-allowed
spec:
nodeSelector:
dedicated: app
tolerations:
- key: "dedicated"
operator: "Equal"
value: "app"
effect: "NoSchedule"
containers:
- name: taint-demo
image: busybox
command: ["sh", "-c", "sleep 3600"]
套用後檢查 Pod 被排到哪個 Node:
kubectl apply -f taint-demo-allowed.yaml
kubectl get pods -o wide
這個 Pod 同時符合 nodeSelector 和 Toleration 條件,因此可以排到 minikube-m02。
註:
如果你的 Minikube Node 名稱不是 minikube-m02,請先使用 kubectl get nodes 查詢,再替換範例中的名稱。
Taints / Tolerations 提供一種由 Node 排斥 Pod、由 Pod 表明可以容忍的排程控制方式。Taint 建立在 Node 上,Toleration 則設定在 Pod 上。若要限制 Pod 實際前往哪個 Node,可以再搭配 nodeSelector 或 Node Affinity。
參考資料:Kubernetes 官方文件:Taints and Tolerations