有排斥的設定那有沒有偏好設定?有! \(^o^)/
在部署 Pod 的時候,除了使用 Taints 和 Tolerations 設定避免 Pod 被部署到不適合的 Node 上,也可以透過偏好設定讓 Pod 優先在特定的 Node 上運行。
有幾種方式:
由 Pod 去指定要部署的 Node。
設定方式:
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx
nodeName: <要部署的 node name>
前篇也有提到,使用這個方式會有些風險。
nodeName 的設定會使部署繞過所有策略,直接將 Pod 部署在設定的 Node 上。
就算該 Node 包含 Taints 也一樣。
nodeName
設定?欸... 也不是這樣。
Taints 不是只有使用者在使用,Kubernetes 也會因為調度需求而在 Node 上自動設定/移除 Taints 。若使用nodeName
指定部署 Node,又遇上 Node 屬於不可用或資源不足狀態時,就會造成 Pod 部署失敗。
那 nodeName 用在哪裡?
通常會用在偵錯或測試階段,需要在指定 Node 上執行的時候;或是 Cluster 只有一個 Node 時,也不會產生負面影響。
那有沒有更彈性的方法?
有的!可以使用 nodeSelector
由 Pod 去選擇要部署的 Node。
蛤?聽起來跟前面一樣啊?
同款不同師傅啦 (。・ω・。)
Node 名稱是不可重複的,nodeName 設定是直接指定要部署的 那一個
Node,但 nodeSelector 的判斷標準是標籤 (Label),而標籤,可以重複使用,還可以設定多組。
打個比方,今天使用 Node 的資源配置去設定標籤。
設定指令:
kubectl label nodes <node-name> <key>=<value>
#範例
kubectl label nodes demo-01 size=large
標籤好的 Node 像這樣:
當 Scheduler 接到新的 Pod 需要部署:
apiVersion: v1
kind: Pod
metadata:
name: myapp
spec:
containers:
- name: nginx-container
iamge: nginx
nodeSelector:
size: large
擁有對應的標籤才會被選擇。
若有多組設定,條件之間則為 AND 邏輯,Node 需要 全部
都符合才會被選擇。
當有多個 Node 符合 selector 條件會怎麼樣?
Scheduler 會綜合考量其他因素,最終選定要部署的 Node。
可參考前篇:Scheduling
萬一沒有任何一個 Node 符合 selector 又會怎麼樣?
Pod 將會無法部署,一直保持在 pending 狀態直到有符合條件的 Node 出現。
有啊有啊,本篇的主角:nodeAffinity
nodeSelector
設置簡單,但只能處理=
邏輯,且一旦沒有對應到的 Node 就會部署失敗。
如果需要更有彈性的設定,可以使用 nodeAffinity。
相較於nodeSelector
Affinity 包含兩種類型:Affinity & anti-affinity
在 Node 的操作會使用的是nodeAffinity
,anti-affinity 的邏輯則是透過 Taints & Tolerations 實現
(官方文件的 anti-affinity 是全小寫,就依循使用了。)
概念上類似於 nodeSelector,但是支援更複雜的邏輯判斷。
Affinity 主要使用類型:
requiredDuringSchedulingIgnoredDuringExecution
:required
,當 Scheduler 有找到符合條件的 Node,才執行 Pod 的調度。。preferredDuringSchedulingIgnoredDuringExecution
:preferred
,當有符合條件的 Node,會優先調度。但是當無 Node 符合 Pod 設定,Scheduler 仍會找尋其他 Node 來部署。IgnoredDuringExecution:
只要 Pod 已經部署到 Node 上,即便 Node 的標籤產生異動,也不影響 Pod 繼續運行。整段一起看的話:DuringSchedulingIgnoredDuringExecution
其實就是這個設定條件在調度期間才有效,運行中則忽略。
另外還有一種比較特別的設定:
requiredDuringSchedulingRequiredDuringExecution
:必須
要運行在對應標籤的 Node 上,若是運行中 Pod 或是 Node 標籤發生異動,則 Pod 會被驅除,可能會刪除或是重新部署(取決於 Pod 上層是否有管理元件)。設定方式:
apiVersion: v1
kind: Pod
metadata:
name: myapp
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: size
operator: In
values:
- large
- medium
containers:
- name: nginx-container
iamge: nginx
超級長一串,其實就是這樣:
當 Node 包含 size=large 或 size=medium 標籤時,才可選為可用 Node。
想到就再提一下
注意!Kubernetes 大多數的配置都是大小寫敏感的,包含標籤。
所以在上述範例中,如果 Node 的標籤是 size=Large 或 size=Medium,是 不符合 比對條件的喔!
在 Kubernetes 中雖不存在 nodeAntiAffinity
,但是可以用 nodeAffinity 的 NotIn
屬性來達到類似的效果:
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: disktype
operator: NotIn
values:
- ssd
containers:
- name: my-container
image: nginx
這個設定就可以將 disktype=ssd 的 Node 排除囉!
最後補充Affinity可用的設定邏輯:
nodeAffinity 是 Kubernetes 中富有彈性的調度機制,用來控制 Pod 被分配到特定的節點上。藉由nodeAffinity,使用者可以根據 Node 的規劃和特性去定義標籤,以確保 Pod 被調度到它該去的地方。