DevOps CICD K8s DockerTaint the worker node g8node1 to be Unschedulable. Once done, create a pod called dev-redis, image redis:alpine to ensure workloads are not scheduled to this worker node. Finally, create a new pod called prod-redis and image redis:alpine with toleration to be scheduled on g8node1.
這題也是個Pod Scheduling的問題,但是它和我們第一題學的label的方式明顯不同,題目要求我們將g8node1標註為Unschedulable,且第一個Pod不可以被分派到g8node1上,但是第二個創建的Pod卻必須assing到g8node1上,這樣特殊的Scheduling方式要如何辦到呢?就需要依靠K8s中的Taint&Toleration啦~ 按照慣例,我們先來介紹一下這是個甚麼東西吧~
所謂的
Taints即是允許Node抵制 (repel) 某些Pod,使Pod無法在該節點上運行
而Tolerations則是搭配Taints一同使用,擁有Tolerations的Pod可以被分派到擁有Taints的節點上,但前提是兩者能夠匹配
Taints和Tolerations共同使用,以避免將Pod調度到不適合的節點上。一個或多個Taints應用於Node,表示該節點不應接受任何不能容忍Taints的Pod。
Taints用於Node;Tolerations則用於Pod
要使用Taints可以透過kubectl taint指命:
## 新增 taint
$ kubectl taint nodes <node-name> <key>=<value>:<effect>
## 例如
$ kubectl taint nodes g8node1 size=large:NoSchedule
## 刪除 taint
$ kubectl taint nodes <node-name> <key>=<value>:<effect>-
## 例如
$ kubectl taint nodes g8node1 size=large:NoSchedule-
effect欄位是指:當Pod因為此Taint而無法調度到該節點上的時候,該怎麼處理,一共有三種處理方式:
後面會介紹這三種的差別
若要讓Pod可以被分派到有taint的Node上,則需要宣告Tolerations。下面兩個Tolerations的設定都可以容忍上述例子的taint,因此可被調度到g8node1節點上:
tolerations:
- key: "size"
operator: "Equal"
value: "large"
effect: "NoSchedule"
或
tolerations:
- key: "size"
operator: "Exists"
effect: "NoSchedule"
所有的
value都要以雙引號""標註
Pod的Toleration宣告中的key和effect需要與Taint的設定保持一致,並滿足以下條件之一:
operator的值是Exists(無須指定value)operator的值是Equal且value值相等若無指定
operator,則effect預設為Equal
上面的例子使用了NoSchedule的effect,意思是:除非Pod明確宣告可以容忍這個Taint,否則不會被調度到g8node1上。除了NoSchedule外,還可以使用PreferNoSchedule的effect,意思是優先,一個Pod若沒有宣告容忍這個Taint,則K8s會盡量避免把該Pod調度到這個節點上,但不是強制的。
K8s允許在同個Node上設定多個Taints;當然也可以在Pod上設定多個Tolerations。K8s調度器處理多個Taints和Tolerations的邏輯順序是這樣:首先列出節點中所有的Taints,忽略Pod的Toleration能符合的部分,剩下沒有忽略的Taints就是對Pod的效果了。下面有幾種特殊情況:
Taints中存在effect=NoSchedule,則調度器不會把該Pod調度到此節點上Taints中沒有effect=NoSchedule,但有PreferNoSchedule,則會試著不把該Pod調度到此節點Taints中有effect=NoExcute,並且該Pod已經在此節點上運行,則會被驅逐;若沒有在此節點上運行,也不會再被調度到此節點上Taint和Toleration是一種處理節點驅逐Pod或讓Pod避開不適合節點的彈性調度方式,常見的使用Taint和Toleration的應用場景有:
Node做trobleshooting)有沒有發現我們創建的Pod都不會運行在
Control Plane節點上,聰明的你肯定發現原因了!沒錯,就是因為Control Plane節點default都有Taint在上面,因此無法在上面運行Pod哦~
可以用kubectl describe node指令,觀察Control Plane上的Taint欄位資訊~
回到題目,這題就是Taint和Toleration的應用題型,但值得注意的是,這題只在單一節點上設定Taint是不行的,因為Taint只能確保沒有Toleration的Pod不會被調度到該Node上,但是不能保證有Toleration的Pod一定可以被調度到有Taint的Node上
可能有點繞口,但這兩者是有差別的,你可以想像A,B兩節點,只有A有Taint,B沒有,有一個Pod要啟動,它有A的Toleration,所以它可以在A上運行,但其實它也可以在B上運行,兩者是沒有衝突的
因此,我們需要在每一節點上設置不同的Taint,Pod才能依照Toleration的設定調度到目標節點上。
其實想要讓某一pod一定運行在某一節點上,在K8s中有更聰明的方法,就是
Node Affinity。但是這題限定我們使用Taint&Toleration,而且我們還沒學過Node Affinity,就先這樣吧~
想法如下:
g8node1和g8node2
g8node2但無法容忍g8node1
g8node1但無法容忍g8node2
首先將g8node1和g8node2加上Taint
$ kubectl taint nodes g8node1 env_type=production:NoSchedule
$ kubectl taint nodes g8node2 other_type=development:NoSchedule
創建第一個Pod,讓它無法被調度到g8node1上,那就讓它能容忍g8node2的Taint
$ kubectl run dev-redis --image=redis:alpine --restart=Never --dry-run=client -o yaml > q10-1.yaml
$ vim q10-1.yaml
## 加上toleration,如下圖

創建第二個Pod,讓它可以被調度到g8node1上,讓它能容忍g8node1的Taint
$ kubectl run prod-redis --image=redis:alpine --restart=Never --dry-run=client -o yaml > q10-2.yaml
$ vim q10-2.yaml
## 加上toleration,如下圖

接著創建這兩個Pod,以kubectl get po -o wide命令即可看見調度的成果
因為我們的集群環境只有兩個節點,所以其實不用這麼麻煩,
g8node2根本不用Taint。但是考試時的環境可能不會只有兩個Node,所以建議練習時還是要作完整的考量哦~
今天介紹了K8s中更進階的Scheduling方式--Taint和Toleration,要特別注意它們的使用時機和各自作用的物件喔~ 好啦,今天就到這囉~ 謝謝大家~
You can find me on