Kubernetes高級調度- Taint和Toleration、Node Affinity分析

此文分享了污點和Node Affinity實際使用過程當中的細節、坑和思惟誤區。同時整理且回答了諸多細節問題,尤爲那些在官方文檔中未曾說起的細節。html

閱讀提示:文中的節點指Nodejava

(避免Pod和Node同時出如今一小段文字中,因此Node以節點漢字表述)node

Taint和Toleration數組

污點的理論支撐app

0410_1.jpg

1.1 污點設置有哪些影響效果測試

使用效果(Effect):ui

  • PreferNoSchedule:調度器儘可能避免把Pod調度到具備該污點效果的節點上,若是不能避免(如其餘節點資源不足),Pod也能調度到這個污點節點上。htm

  • NoSchedule:不容忍該污點效果的Pod永不會被調度到該節點上,經過kubelet管理的Pod(static Pod)不受限制;以前沒有設置污點的Pod若是已運行在此節點(有污點的節點)上,能夠繼續運行。blog

  • NoExecute: 調度器不會把Pod調度到具備該污點效果的節點上,同時會將節點上已存在的Pod驅逐出去。內存

污點設置的第一前提是: 節點上的污點key和Pod上的污點容忍key相匹配。

1.2 設置污點的效果實測

0410_2.jpg

 

當Pod未設置污點容忍而節點設置了污點時

  • 當節點的污點影響效果被設置爲:PreferNoSchedule時,已存在於此節點上的Pod不會被驅逐;新增但未設置污點容忍的Pod仍然能夠被調度到此節點上。

  • 當節點的污點影響效果被設置爲:NoSchedule時,已存在於此節點上的Pod不會被驅逐;同時,新增的Pod不會被調度此節點上。

  • 當節點的污點影響效果被設置爲:NoExecute時,已存在於此節點上的Pod會發生驅逐(驅逐時間由tolerationSeconds字段肯定,小於等於0會當即驅逐);新增的Pod不會調度到此節點上。

當Node設置了污點且Pod設置了對應的污點容忍時,實測效果以下表:

0410_3.jpg

 

污點容忍設置, 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(不重要)

0410_4.jpg

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設置沿用上一個例子的, 根據上面的配置,咱們會看到:

0410_5.jpg

如表所示, 最終Pod優先調度到10.x.x.85, 緣由在於app=1的權重是4, level=important的權重是5, 因此:節點 10.x.x.80的權重是:9,可是仍然小於節點:10.x.x.85的權重。

2.2 問題總結

  1. 其實強親和性和首選親和性區別體如今:Pod對節點的選擇上。就強親和性而言,若是節點不能匹配Pod對Label的要求, Pod永遠不會調度到這類節點上,即便是Pod調度失敗(沒錯,就是頭鐵),就首選親和性來講,能調度到最優節點是一件很是值得開心的事情,若是不能調度到最優節點能夠退而求其次,總有適合本身的。 (回答問題1)

  2. 首選親和性體如今PodLabel的權重值上,而與節點Label的匹配個數無關。(回答問題2)

  3. 在首選親和性配置中會多一個權重值的字段(weight),這個值越大,權重越大,Pod調度到對應此Label的節點的機率越高。(回答問題4)

  4. 一個節點有多個Label且節點能知足Pod所要求的全部Label,若是多個Label的權重值相加仍然小於某單個Label的節點,那麼Pod首選是權重值高的節點;若是Pod能匹配到A 節點的全部Label,同時也能匹配到B 節點某一個Label.可是,A節點 Label的權重之和恰好等於B 節點的單個Label的權重,這時,Pod優先選擇的A仍是B這是隨機的(只針對親和性來講是隨機的,實際狀況還要考慮其餘狀況)。而不會管Label的匹配個數。(回答問題5)

  5. 建立或擴容Pod時,優先選擇Label匹配權重值大的節點,若此節點的其餘條件不知足(好比內存不足),選擇次權重的,最後選擇Label不匹配或者根本沒有Label的節點。

  6. (回答問題6)縮容時,隨機選擇Pod殺掉,而不是咱們預想的從低權重的節點開始殺,這點值得注意。

  7. (回答問題7)答案是不會,正在運行的Pod不會被調度到新的節點去, 當Pod由於某種緣由重啓(指Pod名字改變,觸發重調度,名字不改變,意味着不觸發調度器調度,只是原地重啓)後,會自動調度到符合親和性選擇的節點上。

污點和Node Affinity的使用總結

0410_6.jpg

  1. 就污點而言,它的使用一般是負向的, 也就說, 污點經常使用在某Node不讓大多數Pod調度只讓少部分Pod調度時,又或者節點根本不參加工做負載時。好比:咱們常見的master節點上不調度負載pod,保證master組件的穩定性;節點有特殊資源,大部分應用不須要而少部分應用須要,如GPU。

  2. 就Node Affinity來講,他的使用能夠正向的,也就是說,咱們想讓某個應用的Pod部署在指定的一堆節點上。固然,也能夠是負向的,好比說咱們常說的Node 反親和性,只須要把操做符設置爲NotIn就能達成預期目標。

  3. 就污點而言,若是節點設置的污點效果是NoSchedule或者NoExecute,意味着沒有設置污點容忍的Pod毫不可能調度到這些節點上。

  4. 就Node Affinity而言,若是節點設置了Label,可是Pod沒有任何的Node Affinity設置,那麼Pod是能夠調度到這些節點上的。

 

相關服務請訪問:https://support.huaweicloud.com/cce/index.html?utm_content=cce_helpcenter_2019

相關文章
相關標籤/搜索