上一章節中,我們介紹了如何主動指定 Pod 要部署在哪些節點上。然而在預設情況下,調度器會將 Pod 平均部署在所有可用的節點中。如果我們希望某些節點預設情況下不被調度,Taints
和 Tolerations
的搭配便是很好的解決方案。
Taints
和 Tolerations
是 Kubernetes 中的機制,用於控制 Pod 的調度靈活性,確保 Pod 調度到合適的節點。
Taints:
Tolerations:
搶占(Preemption) 是在資源緊張時,為高優先級的 Pod 騰出資源,可能會驅逐低優先級的 Pod。而 Taints 則用於預防不合適的 Pod 調度到特定節點。
驅逐(Eviction) 是指當節點資源不足或節點出現故障時,Kubernetes 會主動移除一些 Pod。Taints 則更側重於調度前的預防措施,而不是調度後的處理。
某些節點可能配置了特殊硬件(如 GPU)或用於特定用途。使用 Taints 可以避免其他無關的 Pod 被調度到這些節點上,確保這些節點僅運行特定工作負載。
當節點出現故障或處於維護模式時,可以通過應用 Taints 暫時阻止新的 Pod 被調度到這些節點上。
在多租戶 Kubernetes 集群中,可以使用 Taints 來確保不同租戶的工作負載被隔離到各自專用的節點上,避免資源衝突。
Taints 通過以下命令設置,可以在節點的 YAML 定義中指定:
kubectl taint nodes nodename key=value:taint-effect
Tolerations 通過 Pod 的 YAML 組態檔來設置:
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:
- name: mycontainer
image: nginx
tolerations:
- key: "key"
operator: "Equal"
value: "value"
effect: "NoSchedule"
tolerationSeconds: 3600
Equal
表示必須匹配指定的 key
和 value
。NoSchedule
)。NoExecute
Taint。該 Pod 會在指定時間內被允許運行,超過時間後將被驅逐。kubectl get nodes -o json | jq '.items[] | {name: .metadata.name, taints: .spec.taints}'
結果如下
{
"name": "wslkind-control-plane",
"taints": [
{
"effect": "NoSchedule",
"key": "node-role.kubernetes.io/control-plane"
}
]
}
{
"name": "wslkind-worker",
"taints": null
}
{
"name": "wslkind-worker2",
"taints": null
}
kubectl taint nodes wslkind-worker2 dedicated=nginx-app:NoSchedule
kubectl get nodes -o json | jq '.items[] | {name: .metadata.name, taints: .spec.taints}'
結果如下
{
"name": "wslkind-control-plane",
"taints": [
{
"effect": "NoSchedule",
"key": "node-role.kubernetes.io/control-plane"
}
]
}
{
"name": "wslkind-worker",
"taints": null
}
{
"name": "wslkind-worker2",
"taints": [
{
"effect": "NoSchedule",
"key": "dedicated",
"value": "nginx-app"
}
]
}
但凡節點存在污點,Pod 在調度時預設就會避開它們,我們來驗證一下。
組態檔案: deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: test-deploy
name: test-deploy
spec:
replicas: 6
selector:
matchLabels:
app: test-pod
template:
metadata:
creationTimestamp: null
labels:
app: test-pod
spec:
containers:
- image: nginx
name: nginx
該配置文件相當單純,配置 1 個具有 6 個副本的 nginx container 。
kubectl apply -f deploy.yaml
kubectl get pod -l app=test-pod -o wide
結果如下
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
test-deploy-7f7cd9b788-75gjl 1/1 Running 0 12s 10.244.1.10 wslkind-worker <none> <none>
test-deploy-7f7cd9b788-bkgn6 1/1 Running 0 9s 10.244.1.13 wslkind-worker <none> <none>
test-deploy-7f7cd9b788-bpqh7 1/1 Running 0 12s 10.244.1.11 wslkind-worker <none> <none>
test-deploy-7f7cd9b788-th8c6 1/1 Running 0 7s 10.244.1.15 wslkind-worker <none> <none>
test-deploy-7f7cd9b788-wqxm2 1/1 Running 0 12s 10.244.1.12 wslkind-worker <none> <none>
test-deploy-7f7cd9b788-zwhj7 1/1 Running 0 8s 10.244.1.14 wslkind-worker <none> <none>
可以看到,由於剛剛對 wslkind-worker2
節點添加了污點,在調度的時候會避免在有污點的節點部署 Pod。
Pod 在預設中不會被調度到 control-plane
節點也是這個原因。
在 Pod 添加 spec.tolerations
配置,可以使該 Pod 容忍指定的污點,允許 Pod 部署在那些節點上,下面我們來驗證一下。
修改上面的 deploy.yaml
配置文件,添加兩個容忍條件,我們預期包含控制平面節點在內,所有的節點應該都可以調度 pod。
組態檔案: deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: test-deploy
name: test-deploy
spec:
replicas: 6
selector:
matchLabels:
app: test-pod
template:
metadata:
creationTimestamp: null
labels:
app: test-pod
spec:
tolerations:
- key: "dedicated"
operator: "Equal"
value: "nginx-app"
effect: "NoSchedule"
- key: "node-role.kubernetes.io/control-plane"
operator: "Exists"
effect: "NoSchedule"
containers:
- image: nginx
name: nginx
deploy.yaml
建立 deploymentkubectl apply -f deploy.yaml
kubectl get pod -l app=test-pod -o wide
結果如下
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
test-deploy-86b969b6b-28s6b 1/1 Running 0 47s 10.244.0.22 wslkind-control-plane <none> <none>
test-deploy-86b969b6b-2sxj2 1/1 Running 0 52s 10.244.0.21 wslkind-control-plane <none> <none>
test-deploy-86b969b6b-575zn 1/1 Running 0 50s 10.244.2.7 wslkind-worker2 <none> <none>
test-deploy-86b969b6b-cldls 1/1 Running 0 52s 10.244.0.20 wslkind-control-plane <none> <none>
test-deploy-86b969b6b-dp8bq 1/1 Running 0 52s 10.244.0.19 wslkind-control-plane <none> <none>
test-deploy-86b969b6b-kdx8l 1/1 Running 0 49s 10.244.1.16 wslkind-worker <none> <none>
現在 3 個節點都部署了 Pod,包括控制平面節點。
kubectl taint nodes wslkind-worker2 dedicated=nginx-app:NoSchedule-
Taints and Tolerations
是 Kubernetes 中強大且靈活的調度控制機制,能夠有效地控制 Pod 調度到節點的行為。它們提供了防止不合適的 Pod 被調度到特定節點上的能力,並可以在特定應用場景中進行靈活運用,如專用節點的隔離、多租戶環境的資源隔離等。這使得 Kubernetes 能夠在調度過程中保證更高的可控性和精確性。