K8S調度之Taints and Tolerations


Taints和Tolerations(污點和容忍)

《K8S之節點親和性》中,我們說到的的NodeAffinity節點親和性,是在pod上定義的一種屬性,使得Pod能夠被調度到某些node上運行。Taint剛好相反,它讓Node拒絕Pod的運行。
Taint需要與Toleration配合使用,讓pod避開那些不合適的node。在node上設置一個或多個Taint后,除非pod明確聲明能夠容忍這些“污點”,否則無法在這些node上運行。Toleration是pod的屬性,讓pod能夠(注意,只是能夠,而非必須)運行在標注了Taint的node上。

基本用法

  1. 設置污點:
    kubectl taint node [node] key=value[effect]   
          其中[effect] 可取值: [ NoSchedule | PreferNoSchedule | NoExecute ]
           NoSchedule :一定不能被調度。
           PreferNoSchedule:盡量不要調度。
           NoExecute:不僅不會調度,還會驅逐Node上已有的Pod。
           
           
    #示例:
      kubectl taint node 10.3.1.16 test=16:NoSchedule    
  1. 去除污點:
    #比如設置污點:
     kubectl taint node 10.3.1.16 test=16:NoSchedule
     kubectl taint node 10.3.1.16 test=16:NoExecute
     
    #去除指定key及其effect:
     kubectl taint nodes node_name key:[effect]-    #(這里的key不用指定value)
                
    #去除指定key所有的effect: 
     kubectl taint nodes node_name key-
    
    #示例:
     kubectl taint node 10.3.1.16 test:NoSchedule-
     kubectl taint node 10.3.1.16 test:NoExecute-
     kubectl taint node 10.3.1.16 test-

下面是一個簡單的示例:

在node1上加一個Taint,該Taint的鍵為key,值為value,Taint的效果是NoSchedule。這意味着除非pod明確聲明可以容忍這個Taint,否則就不會被調度到node1上:

kubectl taint nodes node1  key=value:NoSchedule

然后需要在pod上聲明Toleration。下面的Toleration設置為可以容忍具有該Taint的Node,使得pod能夠被調度到node1上:

apiVersion: v1
kind: Pod
metadata:
  name: pod-taints
spec:
  tolerations:
  - key: "key"
    operator: "Equal"
    value: "value"
    effect: "NoSchedule"
  containers:
    - name: pod-taints
      image: busybox:latest

也可以寫成如下:

tolerations:
- key: "key"
  operator: "Exists"
  effect: "NoSchedule"

pod的Toleration聲明中的key和effect需要與Taint的設置保持一致,並且滿足以下條件之一:

  • operator的值為Exists,這時無需指定value
  • operator的值為Equal並且value相等

如果不指定operator,則默認值為Equal。

另外還有如下兩個特例:

  • 空的key配合Exists操作符能夠匹配所有的鍵和值
  • 空的effect匹配所有的effect

effect說明

上面的例子中effect的取值為NoSchedule,下面對effect的值作下簡單說明:

  • NoSchedule: 如果一個pod沒有聲明容忍這個Taint,則系統不會把該Pod調度到有這個Taint的node上

  • PreferNoSchedule:NoSchedule的軟限制版本,如果一個Pod沒有聲明容忍這個Taint,則系統會盡量避免把這個pod調度到這一節點上去,但不是強制的。

  • NoExecute:定義pod的驅逐行為,以應對節點故障。NoExecute這個Taint效果對節點上正在運行的pod有以下影響:

    • 沒有設置Toleration的Pod會被立刻驅逐

    • 配置了對應Toleration的pod,如果沒有為tolerationSeconds賦值,則會一直留在這一節點中

    • 配置了對應Toleration的pod且指定了tolerationSeconds值,則會在指定時間后驅逐

    • 從kubernetes 1.6版本開始引入了一個alpha版本的功能,即把節點故障標記為Taint(目前只針對node unreachable及node not ready,相應的NodeCondition "Ready"的值為Unknown和False)。激活TaintBasedEvictions功能后(在--feature-gates參數中加入TaintBasedEvictions=true),NodeController會自動為Node設置Taint,而狀態為"Ready"的Node上之前設置過的普通驅逐邏輯將會被禁用。注意,在節點故障情況下,為了保持現存的pod驅逐的限速設置,系統將會以限速的模式逐步給node設置Taint,這就能防止在一些特定情況下(比如master暫時失聯)造成的大量pod被驅逐的后果。這一功能兼容於tolerationSeconds,允許pod定義節點故障時持續多久才被逐出。

多污點與多容忍配置

系統允許在同一個node上設置多個taint,也可以在pod上設置多個Toleration。Kubernetes調度器處理多個Taint和Toleration能夠匹配的部分,剩下的沒有忽略掉的Taint就是對Pod的效果了。下面是幾種特殊情況:

  • 如果剩余的Taint中存在effect=NoSchedule,則調度器不會把該pod調度到這一節點上。

  • 如果剩余的Taint中沒有NoSchedule的效果,但是有PreferNoSchedule效果,則調度器會嘗試不會pod指派給這個節點

  • 如果剩余Taint的效果有NoExecute的,並且這個pod已經在該節點運行,則會被驅逐;如果沒有在該節點運行,也不會再被調度到該節點上。

下面是一個示例:

kubectl taint nodes node1 key1=value1:NoSchedule
kubectl taint nodes node1 key1=value1:NoExecute
kubectl taint nodes node1 key2=value2:NoSchedule

在pod上設置兩個toleration:

tolerations:
- key: "key1"
  operator: "Equal"
  value: "value1"
  effect: "NoSchedule"
- key: "key1"
  operator: "Equal"
  value: "value1"
  effect: "NoExecute"  

這樣的結果是該pod無法被調度到node1上,因為第三個taint沒有匹配的toleration。但是如果這個Pod已經在node1上運行了,那么在運行時設置上第三個Taint,它還能繼續運行,因為pod可以容忍前兩個taint。

一般來 說,如果給node加上effect=NoExecute的Taint,那么該 node上正在運行的所有無對應toleration的pod都會被立刻驅逐,而具有相應toleration的pod則永遠不會被逐出。不過系統允許給具有NoExecute效果的Toleration加入一個可選 的tolerationSeconds字段,這個設置表明pod可以在Taint添加到node之后還能在這個node上運行多久(單們為s):

tolerations:
- key: "key1"
  operator: "Equal"
  value: "value1"
  effect: "NoSchedule"
  tolerationSeconds: 3600

上面的例子的意思是,如果pod正在運行,所在節點被加入一個匹配的Taint,則這個Pod會持續在這個節點上存活3600s后被驅逐。如果在這個寬限期內taint被移除,則不會觸發驅逐事件。

常見應用場景

節點獨占

如果想要拿出一部分節點,專門給特定的應用使用,則可以為節點添加這樣的Taint:

kubectl taint nodes nodename dedicated=groupName:NoSchedule

然后給這些應用的pod加入相應的toleration,則帶有合適toleration的pod就會被允許同使用其他節點一樣使用有taint的節點。然后再將這些node打上指定的標簽,再通過nodeSelector或者親和性調度的方式,要求這些pod必須運行在指定標簽的節點上。

具有特殊硬件設備的節點

在集群里,可能有一小部分節點安裝了特殊的硬件設備,比如GPU芯片。用戶自然會希望把不需要占用這類硬件的pod排除在外。以確保對這類硬件有需求的pod能夠順利調度到這些節點上。可以使用下面的命令為節點設置taint:

kubectl taint nodes nodename special=true:NoSchedule
kubectl taint nodes nodename special=true:PreferNoSchedule

然后在pod中利用對應的toleration來保障特定的pod能夠使用特定的硬件。然后同樣的,我們也可以使用標簽或者其他的一些特征來判斷這些pod,將其調度到這些特定硬件的服務器上。

應對節點故障

之前說到,在節點故障時,可以通過TaintBasedEvictions功能自動將節點設置Taint,然后將pod驅逐。但是在一些場景下,比如說網絡故障造成的master與node失聯,而這個node上運行了很多本地狀態的應用即使網絡故障,也仍然希望能夠持續在該節點上運行,期望網絡能夠快速恢復,從而避免從這個node上被驅逐。Pod的Toleration可以這樣定義:

tolerations:
- key: "node.alpha.kubernetes.io/unreachable"
  operator: "Exists"
  effect: "NoExecute"
  tolerationSeconds: 6000

對於Node未就緒狀態,可以把key設置為node.alpha.kubernetes.io/notReady

如果沒有為pod指定node.alpha.kubernetes.io/noReadyToleration,那么Kubernetes會自動為pod加入tolerationSeconds=300的node.alpha.kubernetes.io/notReady類型的toleration

同樣,如果沒有為pod指定node.alpha.kubernetes.io/unreachableToleration,那么Kubernetes會自動為pod加入tolerationSeconds=300的node.alpha.kubernetes.io/unreachable類型的toleration

這些系統自動設置的toleration用於在node發現問題時,能夠為pod確保驅逐前再運行5min。這兩個默認的toleration由Admission Controller "DefaultTolerationSeconds"自動加入。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM