背景
繼上一篇《Kubernetes的污點和容忍(上篇)》,這是https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ 譯文的下半部分。
經常看外文文檔或書籍多了,會產生一個問題:“不方便溝通。”不太會用大家習慣的表述方式來闡述一個問題。所以需要定期看一些中文書籍來學習「行話」。
譯文
使用場景
污點和容忍是一種讓Pod不被調度到指定node或者是把不該在某個node上運行的Pod踢掉的靈活方法。下面列舉一些使用場景。
-
指定node:如果想為特殊的用戶指定一組node,可以添加一個污點到這組node上(運行命令: kubectl taint nodes nodename dedicated=groupName:NoSchedule)。然后添加對應的容忍到這個Pod上(這個最容易實現的方法是寫一個客戶端准入控制器)。帶有相應容忍的Pod就可以像被調度到集群中其他node一樣被調度到帶有相應污點的node上。
-
特殊硬件的node:在一個有一小組特殊硬件(例如GPU)的集群中,更希望將沒有特殊硬件需求的Pod不調度到這些node上,留出空間給后來的需要這些特殊硬件的Pod。這個通過給特殊硬件打上污點(例如:kubectl taint nodes nodename special=true:NoSchedule or kubectl taint nodes nodename special=true:PreferNoSchedule),然后添加相應的容忍到Pod上來實現。在這些使用場景,最容易實現的方法是使用客戶端准入控制器來實現。例如,推薦使用Extended Resources 來代表特殊硬件,將帶有擴展資源名的硬件打上污點。然后運行ExtendedResourceToleration准入控制器. 現在,由於這些node已經被打上污點了,沒有容忍的Pod不會被調度到上面。但是當你提交了一個需要擴展資源的Pod,ExtendedResourceToleration准入控制器會自動的添加正確的容忍到Pod上,Pod就可以被調度到這個特殊硬件的node上了。這會確保這些特殊硬件的node是需要相應的硬件的,並且不需要手動給Pod添加容忍。
-
基於污點的驅逐(beta版本特性):下面我們會介紹當node發生故障時基於單個Pod配置的驅逐行為。
基於驅逐的污點
早期我們提到了NoExecute污點的effect會影響已經在node上運行的Pod。
-
不能容忍污點的Pod會被立即驅逐。
-
Pod上的容忍沒有指定tolerationSeconds會好好的呆在node上。
-
Pod上的容忍帶有tolerationSeconds的會在node上停留指定的時間。
另外,Kubernets 1.6 引入了代表node問題的污點(在1.6版本是alpha版試用)。換句話說,node控制器當某種條件成立的時候會自動的給node打上污點。下面是其中內置的污點:
-
node.kubernetes.io/not-ready:node不是ready狀態。對應於node的condition ready=false.
-
node.kubernetes.io/unreachable:node controller與node失聯了。對應於node的condition ready=unknown
-
node.kubernetes.io/out-of-disk:node磁盤空間不足了。
-
node.kubernetes.io/network-unavailable:node的網斷了
-
node.kubernets.io/unschedulable:node不是可調度狀態
-
node.cloudprovider.kubernetes.io/uninitalized:kubelet是由外部雲提供商提供的時候,剛開始的時候會打上這個污點來標記還未被使用。當cloud-controller-manager控制器初始化完這個node,kubelet會自動移除這個污點。
在1.13版本中,「基於污點的驅逐」特性被提升至beta版,並且被默認開啟。因為這些污點會被自動添加到node控制器(或kubelet)中。而之前的常使用的邏輯:基於condition中ready狀態來驅逐pod也被禁用了。
注意:
為了維持在node故障時對存在的Pod驅逐做限流,系統實際上是用限速的方法來添加污點的。這種措施防止了master與node腦裂而產生的大規模驅逐Pod的場景。
這個beta版本特性再結合tolerationSeconds,可以使得pod指定當node節點出現問題的時候一個pod能在node上呆多久。
舉個栗子:
一個有很多本地狀態的應用可能想在產生網絡腦裂的時候還能在node上呆很久。這樣是希望腦裂會恢復,從而避免pod被驅逐。為了達到這個目的,可以這樣用:

Kubernetes會自動給pod添加容忍:node.kubernetes.io/not-ready 實效是tolerationSeconds=300。但是如果用戶自己給這個pod添加了node.kubernets.io/not-ready的容忍,用戶的配置不會被覆蓋。
類似的,它也會自動給pod添加容忍:node.kubernetes.io/unreachable 實效是tolerationSeconds=300。但是如果用戶自己給這個pod添加了node.kubernetes.io/unreahable,用戶的配置不會被覆蓋。
這種自動添加容忍機制確保了默認pod如果宿主機發生故障在5分鍾之內不會被自動驅逐。這兩個默認的容忍都是https://github.com/kubernetes/kubernetes/tree/master/plugin/pkg/admission/defaulttolerationseconds (DefaultTolerationSeconds admission controller)這個控件來添加的。
DaemonSet的pod會默認添加一個NoExecute不帶有tolerationSeconds的容忍:
-
node.kubernetes.io/unreachable
-
node.kubernetes.io/not-ready
這種方式確保了DaemonSet的Pod在發生故障的時候永遠不會被驅逐。
condition驅動的污點
在版本1.12中,「condition驅動的污點」特性被提升到beta版,node的生命周期控制器自動的創建condition相應的污點。類似的,調度器並不檢查node的condition,而是檢查污點。這種方式是用來保證node的condition不會影響已經調度到這台node的Pod。用戶可以用添加合適的容忍來忽視node的一些問題(condition是其中的代表)。在這個版本中「condition驅動的污點」只是打上了effect=NoSchedule的污點。而在1.13版本中才將effect=NoExcute作為beta版默認開啟。
從Kubernetes1.8版本開始,DaemonSet控制器自動的添加了NoSchedule容忍到所有的daemon線程來避免DaemonSets中斷。
-
node.kubernetes.io/memory-pressure
-
node.kubernetes.io/disk-pressure
-
node.kubernetes.io/out-of-disk(只對重要的pod生效)
-
node.kubernetes.io/unschedulable(1.10版本后生效)
-
node.kubernetes.io/network-unavailable(只針對主機網絡)
添加這些容忍確保了向后兼容,用戶可以隨意對DaemonSets添加容忍。
相關閱讀
作者是一個有美國硅谷、日本東京工作經驗,十二年堅持一線寫代碼的程序媛。堅持原創文章。歡迎技術交流!