Kubernetes高階排程- Taint和Toleration、Node Affinity分析
此文分享了汙點和Node Affinity實際使用過程中的細節、坑和思維誤區。同時整理且回答了諸多細節問題,尤其那些在官方文件中不曾提及的細節。
閱讀提示:文中的節點指Node
(避免Pod和Node同時出現在一小段文字中,所以Node以節點漢字表述)
Taint和Toleration
汙點的理論支撐
1.1 汙點設定有哪些影響效果
使用效果(Effect):
-
PreferNoSchedule:排程器儘量避免把Pod排程到具有該汙點效果的節點上,如果不能避免(如其他節點資源不足),Pod也能排程到這個汙點節點上。
-
NoSchedule:不容忍該汙點效果的Pod永不會被排程到該節點上,透過kubelet管理的Pod(static Pod)不受限制;之前沒有設定汙點的Pod如果已執行在此節點(有汙點的節點)上,可以繼續執行。
-
NoExecute: 排程器不會把Pod排程到具有該汙點效果的節點上,同時會將節點上已存在的Pod驅逐出去。
汙點設定的第一前提是: 節點上的汙點key和Pod上的汙點容忍key相匹配。
1.2 設定汙點的效果實測
當Pod未設定汙點容忍而節點設定了汙點時
-
當節點的汙點影響效果被設定為:PreferNoSchedule時,已存在於此節點上的Pod不會被驅逐;新增但未設定汙點容忍的Pod仍然可以被排程到此節點上。
-
當節點的汙點影響效果被設定為:NoSchedule時,已存在於此節點上的Pod不會被驅逐;同時,新增的Pod不會被排程此節點上。
-
當節點的汙點影響效果被設定為:NoExecute時,已存在於此節點上的Pod會發生驅逐(驅逐時間由tolerationSeconds欄位確定,小於等於0會立即驅逐);新增的Pod不會排程到此節點上。
當Node設定了汙點且Pod設定了對應的汙點容忍時,實測效果如下表:
汙點容忍設定, Exists和Equal這兩個運算子之間的區別是什麼?
在配置上:
-
Exists必須把值設定為空字串,而只關心key與節點的汙點key是否匹配。
-
Equal需要同時設定key和value來匹配汙點節點的Key和value。
兩者之間的理解加深:
-
若一個節點存在多個汙點, Pod使用Exists只容忍了其中一個汙點, 仍然不能排程此節點, 原因在於Pod不容忍此節點的其他汙點。
-
若一個節點存在多個汙點, Pod使用Equal只容忍了其中一個汙點, 仍然不能排程此節點, 原因在於Pod還是不容忍此節點的其他汙點。
-
若想要一個Pod能夠排程到含有多個汙點的節點上, 那麼此Pod需要容忍此節點的所有汙點。
1.3 汙點容忍裡的一些小竅門:
-
在汙點容忍設定時,若key,value是空字元且運算子是Exists 那麼能Pod容忍節點的所有汙點。(注意:仍然遵從於容忍效果的等級設定)。例如:一個Pod在設定汙點容忍時,key,value為空且運算子是Exists,容忍效果為:NoExecute,那麼該Pod不會排程到汙點效果為:NoSchedule的節點上。
-
在設定汙點容忍時, 若Pod的容忍效果(effect)被設定為空字元,那麼Pod能匹配所有的容忍效果。
-
在設定汙點容忍時, 若key,value為空、運算子是Exists且容忍效果(effect)也為空時,則等於沒有設定。
預設情況下,運算子是Equal。
如果節點的影響效果是NoExecute,且不想Pod被立即驅逐,那麼可以設定TolerationSeconds(延遲驅逐時間),若值是0或者負數會立即驅逐,若值大於0,則在此時間後開始驅逐。
從測試結果來看,只要節點設定了汙點且效果是:NoExecute,不管Pod是否容忍了該汙點都不能在對應節點上正常執行(一直處於刪除,重建的過程),原因是能被排程到節點上是排程器選擇的結果,Pod被殺掉是本地kubelet決策的結果,這是兩個元件分管不同工作產生的效果,下面這種配置除外。
tolerations: - operator: Exists
#此Pod的汙點配置能夠容忍所有的汙點,所有的影響效果,所有能排程到所有的節點上(包括影響效果被設定為:NoExecute的Node).
1.4 認知誤區
1.4.1 當一個節點設定了汙點,那麼只要設定Pod對此汙點容忍就能排程上去且能正常執行。(錯)
當節點的一個汙點的影響效果被設定為:NoExecute,此時Pod對此汙點的容忍效果也是NoExecute時, Pod能排程上去,但是也會被Terminating,不斷的處於Terminating,ContainerCreating的過程。
對Node設定汙點:
kubectl taint nodes 1xx status=unavailable:NoExecute
Pod設定的汙點容忍:
tolerations: - effect: NoExecute key: status operator: Equal tolerationSeconds: 0 value: unavailable
效果:
tolerations: - operator: Exists
#此Pod的汙點配置能夠容忍所有的汙點,所有的影響效果,所有能排程到所有的節點上(包括影響效果被設定為: NoExecute的Node).
1.4.2 當一個節點設定了多個汙點,只要使用Exists運算子匹配到其中一個汙點,此Pod就能排程到對應的節點上。(錯)
原因在於Pod只能匹配到其中一個汙點,但是還是不能匹配到其他汙點。所以,不能排程上去。
1.4.3 在設定Pod容忍時,只要匹配到key和value就行了,不用關心容忍效果的設定。(錯)
容忍效果的設定和key/value的設定一樣重要,甚至更加重要。如果容忍效果不匹配。也會導致Pod排程不能到對應節點上。
1.4.4 如果Pod沒有設定任何的汙點容忍,Pod就不能排程到有汙點的節點上。(錯)
如果節點的汙點效果是: PreferNoSchedule, 沒有設定任何汙點容忍的Pod也能排程到此節點上。原因在於:PreferNoSchedule的意思是優先不排程,但是當沒有節點可用時,Pod仍然能排程到此節點。
二
Node Affinity
Node Affinity可以讓指定應用排程到指定的節點,這有利於應用的穩定性,減少重要業務和不重要業務之間相互搶佔資源的可能,同時也可以降低不重要業務對重要業務的影響,另一方面,也能夠進行多租戶之間的隔離。根據租戶需求為租戶提供特定的執行環境。
2.1 NodeAffinity配置要點
NodeAffinity配置分類兩大部分:
requiredDuringSchedulingIgnoredDuringExecution (強親和性)
preferredDuringSchedulingIgnoredDuringExecution (首選親和性)
但是,在真實的配置環節時,又會犯迷糊:
-
強親和性到底多強算強?
-
首選親和性中的首選體現在那些方面?
-
強親和性配置時,有兩種配置方式,兩種的區別是什麼?
-
首選親和性中的權重值到底是什麼規則? 值越大權重值越高麼?還是值越小越高(1最大)?
-
首選親和性配置中, 如果Pod能匹配A節點的多個Label,也能匹配B節點的一個Label(A的Label權重之和等於B單個Label的權重),這時Pod會優先排程到A節點麼?
-
縮容時,是先從低權重的節點上開始殺麼? 這些問題, 我們都不能全靠註釋和理解去揣測答案,必須經過實測得到真實答案,否則一旦上了生產再想修改就需要付出更大的成本。
-
如果Pod是以強親和性的方式繫結在節點上且Pod已經正常執行在此節點上,此時刪除節點的標籤是否會導致Pod重啟發生漂移。
強親和性:
requiredDuringSchedulingIgnoredDuringExecution
例子Node Labels設定:
level: important(重要),general(一般),unimportant(不重要)
Pod與運算的配置:
注意: 強親和性的配置分為: 與運算、或運算兩部分
requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: level operator: In values: - important - key: app operator: In values: - 1
在與運算的配置中,我們發現,在同一個matchExpressions中既需要匹配level=important的標籤也需要匹配app=1的標籤。也就是說:Pod只會選擇同時匹配這兩個Label的節點。
根據上面Pod的Node親和性設定,兩個Label求一個交集,只有同時滿足兩個Label的節點才會納入這個Pod的排程池,顯而易見,只有10.x.x.80這個節點。所以,此Pod只能排程到這個節點,如果這個節點資源不足,那麼此Pod排程失敗。
Pod或運算配置:
requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: level operator: In values: - important - matchExpressions: - key: level operator: In values: - unimportant
在或運算的配置中,我們發現有一個matchExpressions陣列,裡面的Label列表求並集。也就是說:Pod可以選擇只要匹配其中一個Label的節點就行,不用全匹配。
舉個例子:
節點的Label設定沿用上一個例子的。 節點的標籤只要能滿足Pod的其中一個標籤, 節點就能納入這個Pod的排程池,顯而易見,這個Pod可選的節點有:10.x.x.78, 10.x.x.79,10.x.x.80, 10.x.x.86, 10.x.x.87, 10.x.x.88。
首選親和性:
preferredDuringSchedulingIgnoredDuringExecution
它的使用風格應該是:如果Pod能排程到指定Label的節點最好,如果不能,也不強求,Pod選擇其他的節點也行,即使這個節點根本沒有Label或者節點的Label和我完全不匹配。
Pod首選親和性設定:
preferredDuringSchedulingIgnoredDuringExecution: - preference: matchExpressions: - key: level operator: In values: - important weight: 5 - preference: matchExpressions: - key: app operator: In values: - "1" weight: 4 - preference: matchExpressions: - key: master operator: In values: - "1" weight: 10
示例: Node的Label設定沿用上一個例子的, 根據上面的配置,我們會看到:
如表所示, 最終Pod優先排程到10.x.x.85, 原因在於app=1的權重是4, level=important的權重是5, 所以:節點 10.x.x.80的權重是:9,但是仍然小於節點:10.x.x.85的權重。
2.2 問題總結
-
其實強親和性和首選親和性區別體現在:Pod對節點的選擇上。就強親和性而言,如果節點不能匹配Pod對Label的要求, Pod永遠不會排程到這類節點上,即使是Pod排程失敗(沒錯,就是頭鐵),就首選親和性來說,能排程到最優節點是一件非常值得開心的事情,如果不能排程到最優節點可以退而求其次,總有適合自己的。 (回答問題1)
-
首選親和性體現在PodLabel的權重值上,而與節點Label的匹配個數無關。(回答問題2)
-
在首選親和性配置中會多一個權重值的欄位(weight),這個值越大,權重越大,Pod排程到對應此Label的節點的機率越高。(回答問題4)
-
一個節點有多個Label且節點能滿足Pod所要求的所有Label,如果多個Label的權重值相加仍然小於某單個Label的節點,那麼Pod首選是權重值高的節點;如果Pod能匹配到A 節點的所有Label,同時也能匹配到B 節點某一個Label.但是,A節點 Label的權重之和剛好等於B 節點的單個Label的權重,這時,Pod優先選擇的A還是B這是隨機的(只針對親和性來說是隨機的,實際情況還要考慮其他情況)。而不會管Label的匹配個數。(回答問題5)
-
建立或擴容Pod時,優先選擇Label匹配權重值大的節點,若此節點的其他條件不滿足(比如記憶體不足),選擇次權重的,最後選擇Label不匹配或者根本沒有Label的節點。
-
(回答問題6)縮容時,隨機選擇Pod殺掉,而不是我們預想的從低權重的節點開始殺,這點值得注意。
-
(回答問題7)答案是不會,正在執行的Pod不會被排程到新的節點去, 當Pod因為某種原因重啟(指Pod名字改變,觸發重排程,名字不改變,意味著不觸發排程器排程,只是原地重啟)後,會自動排程到符合親和性選擇的節點上。
三
汙點和Node Affinity的使用總結
-
就汙點而言,它的使用通常是負向的, 也就說, 汙點常用在某Node不讓大多數Pod排程只讓少部分Pod排程時,又或者節點根本不參加工作負載時。比如:我們常見的master節點上不排程負載pod,保證master元件的穩定性;節點有特殊資源,大部分應用不需要而少部分應用需要,如GPU。
-
就Node Affinity來說,他的使用可以正向的,也就是說,我們想讓某個應用的Pod部署在指定的一堆節點上。當然,也可以是負向的,比如說我們常說的Node 反親和性,只需要把運算子設定為NotIn就能達成預期目標。
-
就汙點而言,如果節點設定的汙點效果是NoSchedule或者NoExecute,意味著沒有設定汙點容忍的Pod絕不可能排程到這些節點上。
-
就Node Affinity而言,如果節點設定了Label,但是Pod沒有任何的Node Affinity設定,那麼Pod是可以排程到這些節點上的。
相關服務請訪問:https://support.huaweicloud.com/cce/index.html?utm_content=cce_helpcenter_2019
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69908804/viewspace-2640966/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- kubernetes排程之汙點(taint)和容忍(toleration)AI
- Kubernetes Pod排程:從基礎到高階實戰技巧
- K8S 高階排程方式K8S
- APS高階計劃排程系統和生產排產系統
- Abaqus熱分析高階課程
- Quartz排程系統入門和排程高可用實現方案quartz
- Linux核心排程分析(程式排程)Linux
- kubernetes負載感知排程負載
- Kubernetes 排程器實現初探
- Kubernetes排程流程與安全(七)
- 改造 Kubernetes 自定義排程器
- Spark中資源排程和任務排程Spark
- kubernetes排程概念與工作流程
- Kubernetes-15:一文詳解Pod、Node排程規則(親和性、汙點、容忍、固定節點)
- kubernetes實踐之三十八:Pod排程
- [典藏版] Golang 排程器 GMP 原理與排程全分析Golang
- libgo原始碼分析之多執行緒協程管理和排程Go原始碼執行緒
- Kubernetes高階部署元件 Argo Rollout元件Go
- 【Spark篇】---Spark資源排程和任務排程Spark
- 程式排程案例分析與常見疑惑1:為何不能排程?
- 作業排程中介軟體 Elastic-Job-Cloud 原始碼分析 —— 高可用ASTCloud原始碼
- 【APS】90張專業PPT學習高階計劃與排程(APS)
- Kubernetes叢集排程器原理剖析及思考
- kubernetes叢集內排程與負載均衡負載
- Kubernetes 資源拓撲感知排程優化優化
- Flink排程之排程器、排程策略、排程模式模式
- kubernetes高階之pod安全策略
- kubernetes高階之動態准入控制
- java高階用法之:繫結CPU的執行緒Thread-AffinityJava執行緒thread
- 中科信ANSYS高階疲勞分析技術培訓課程
- SOLIDWORKS模擬分析高階免費課程 碩迪科技Solid
- ModStart排程和佇列佇列
- mysql 儲存過程和事件排程MySql儲存過程事件
- Redux 高階 -- 原始碼分析Redux原始碼
- 理解索引(中):MySQL查詢過程和高階查詢索引MySql
- 使用Node.js的Node-cron進行任務排程 - DilinaNode.js
- OpenMP For Construct dynamic 排程方式實現原理和原始碼分析Struct原始碼
- kubernetes高階之叢集中使用sysctlsTLS