在《K8S之節點親和性》中,咱們說到的的NodeAffinity節點親和性,是在pod上定義的一種屬性,使得Pod可以被調度到某些node上運行。Taint恰好相反,它讓Node拒絕Pod的運行。
Taint須要與Toleration配合使用,讓pod避開那些不合適的node。在node上設置一個或多個Taint後,除非pod明確聲明可以容忍這些「污點」,不然沒法在這些node上運行。Toleration是pod的屬性,讓pod可以(注意,只是可以,而非必須)運行在標註了Taint的node上。html
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
#好比設置污點: 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-
下面是一個簡單的示例:node
在node1上加一個Taint,該Taint的鍵爲key,值爲value,Taint的效果是NoSchedule。這意味着除非pod明確聲明能夠容忍這個Taint,不然就不會被調度到node1上:api
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的設置保持一致,而且知足如下條件之一:code
若是不指定operator,則默認值爲Equal。htm
另外還有以下兩個特例:blog
上面的例子中effect的取值爲NoSchedule,下面對effect的值做下簡單說明:事件
NoSchedule: 若是一個pod沒有聲明容忍這個Taint,則系統不會把該Pod調度到有這個Taint的node上ci
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/noReady
的Toleration
,那麼Kubernetes會自動爲pod加入tolerationSeconds=300的node.alpha.kubernetes.io/notReady
類型的toleration
。
一樣,若是沒有爲pod指定node.alpha.kubernetes.io/unreachable
的Toleration
,那麼Kubernetes會自動爲pod加入tolerationSeconds=300的node.alpha.kubernetes.io/unreachable
類型的toleration
。
這些系統自動設置的toleration用於在node發現問題時,可以爲pod確保驅逐前再運行5min。這兩個默認的toleration由Admission Controller "DefaultTolerationSeconds"自動加入。