介紹
在默認情況下,一個 pod 在哪個 node 節點上運行,是由 Scheduler 組件采用相應的算法算出來的,這個過程是不受人工控制的。但是在實際使用中,這並不滿足需求,因為在很多情況下,我們想控制某些 pod 到達某些節點上,那么應該怎么做呢?這就涉及到 kubernetes 對 pod 的調度規則,kubernetes 提供了四大類調度方式
- 自動調度:運行在哪個節點上完全由 Scheduler 經過一系列的算法計算得出
- 定向調度:有兩種,根據節點名稱(NodeName)或者節點選擇器(NodeSelector)
- 親和性調度:NodeAffinity、PodAffinity、PodAntiAffinity
- 污點(容忍)調度:Taints、Toleration
默認就是自動調度,所以下面來看其他的幾種調度方式
定向調度
定向調度,指的是利用在 pod 上聲明 nodeName 或者 nodeSelector,以此將 pod 調度到期望的 node 節點上。注意,這里的調度是強制的,這就意味着即使要調度的目標 node 不存在,也會向上面進行調度,只不過 pod 運行失敗而已
NodeName
NodeName 用於強制將 pod 調度到指定的 name 的 node 節點上,這種方式,其實是直接跳過 Scheduler 的調度邏輯,直接將 pod 調度到指定名稱的節點
接下來,實驗一下:創建一個 pod-nodename.yaml 文件
apiVersion: v1 kind: Pod metadata: name: pod-nodename namespace: zouzou spec: containers: - name: nginx image: nginx:1.14 nodeName: dce-10-6-215-190 # 指定調度到 dce-10-6-215-190 節點上
如果你不知道 nodeName 的話,使用下面命令查看
kubectl get node
創建 pod,查看 pod
# 創建 pod kubectl apply -f pod-nodename.yaml
查看 pod 的信息,可以看到 pod 已經分配給了 dce-10-6-215-190 的節點上
# 可以看到 pod 分配到了 dce-10-6-215-190 的節點上,有人說,可能是隨機分配的,那你也可以寫一個不存在的 node 地址試下 [root@dce-10-6-215-215 tmp]# kubectl get pod pod-nodename -n zouzou -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES pod-nodename 1/1 Running 0 89s 172.29.190.141 dce-10-6-215-190 <none> <none>
NodeSelector
NodeSelector 用於將 pod 調度到添加了指定標簽的 node 節點上,它是通過 kubernetes 的 label-selector 機制實現的,也就是說,在 pod 創建之前,會由 scheduler 使用 MatchNodeSelector 調度策略進行 label 匹配,找出目標 node,然后將 pod 調度到目標節點,該匹配規則是強制約束。
接下來,實驗一下:首先查看下節點的 labels
[root@dce-10-6-215-215 tmp]# kubectl get node --show-labels NAME STATUS ROLES AGE VERSION LABELS dce-10-6-215-190 Ready <none> 7d3h v1.18.20 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=dce-10-6-215-190,kubernetes.io/os=linux dce-10-6-215-200 Ready <none> 7d1h v1.18.20 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=dce-10-6-215-200,kubernetes.io/os=linux dce-10-6-215-215 Ready master,registry 8d v1.18.20 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=dce-10-6-215-215,kubernetes.io/os=linux,node-role.kubernetes.io/master=,node-role.kubernetes.io/registry=
上面有很多的標簽,為了測試方便,在此基礎上給兩個 node 節點添加兩個簡單的標簽
kubectl label node dce-10-6-215-190 nodeenv=pro
kubectl label node dce-10-6-215-200 nodeenv=test
在來查看下對應的標簽
這樣我們就給兩個節點打上了標簽
創建一個 pod-nodeselector.yaml 文件,並使用它創建 Pod
apiVersion: v1 kind: Pod metadata: name: pod-nodeselector namespace: zouzou spec: containers: - name: nginx image: nginx:1.14 nodeSelector: nodeenv: pro # 指定調度到具有 nodeenv=pro 標簽的節點上
創建 pod 查看詳情,可以看到,pod 分配給了 nodeenv=pro 的標簽節點上
# 創建 pod [root@dce-10-6-215-215 tmp]# kubectl apply -f pod-nodeselector.yaml pod/pod-nodeselector created # 查看 pod 在 dce-10-6-215-190 上了,你也可以寫個不存在的標簽測試是不是隨機分配的 [root@dce-10-6-215-215 tmp]# kubectl get pod pod-nodeselector -n zouzou -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES pod-nodeselector 1/1 Running 0 48s 172.29.190.142 dce-10-6-215-190 <none> <none>
親和性調度
上面,介紹了兩種定向調度的方式,使用起來非常方便,但是也有一定的問題,那就是如果沒有滿足條件的 node,那么 pod 將不會被運行,即使在集群中還有可用 node 列表也不行,這就限制了它的使用場景
基於上面的問題,kubernetes 還提供了一種親和度(Affinity)調度。它在 NodeSelector 的基礎上進行了擴展,可以通過配置的形式,實現優先選擇滿足條件的 Node 進行調度,如果沒有,也可以調度到不滿足條件的節點上,使調度更加靈活
Affinity 主要分為三類
- nodeAffinity(node 親和性):以 node 為目標,解決 pod 可以調度到哪些 node 上的問題
- podAffinity(pod 親和性):以 pod 為目標,解決 pod 可以和哪些已存在的 pod 部署在同一個拓撲域中的問題
- podAntiAffinity(pod 反親和性):以 pod 為目標,解決 pod 不能和哪些已存在 pod 部署在同一個拓撲域中的問題
關於親和性和反親和性使用場景的說明:
親和性:如果兩個應用頻繁交互,那就有必要利用親和性讓兩個應用盡可能的靠近,這樣可以減少因網絡通信而帶來的性能損耗,比如 web 應用和 mysql,要頻繁的從數據庫里查詢和新增數據,所以應該讓他們盡可能的在一起
反親和性:當應用采用多副本部署時,有必要采用反親和性讓各個應用實例打散分布在各個 node 上,這樣可以提高服務的高可用性,當一個服務器掛掉之后,其他的 pod 還可以提供服務
NodeAffinity
首先來看一下 NodeAffinity
的可配置項:
pod.spec.affinity.nodeAffinity requiredDuringSchedulingIgnoredDuringExecution # Node節點必須滿足指定的所有規則才可以,相當於硬限制 nodeSelectorTerms # 節點選擇列表 matchFields # 按節點字段列出的節點選擇器要求列表 matchExpressions # 按節點標簽列出的節點選擇器要求列表(推薦) key # 鍵 values # 值 operat or # 關系符 支持Exists, DoesNotExist, In, NotIn, Gt, Lt preferredDuringSchedulingIgnoredDuringExecution # 優先調度到滿足指定的規則的 Node,相當於軟限制 (傾向) preference # 一個節點選擇器項,與相應的權重相關聯 matchFields # 按節點字段列出的節點選擇器要求列表 matchExpressions # 按節點標簽列出的節點選擇器要求列表(推薦) key # 鍵 values # 值 operator # 關系符 支持In, NotIn, Exists, DoesNotExist, Gt, Lt weight # 傾向權重,在范圍1-100。
關系符的說明
- matchExpressions: - key: nodeenv # 匹配存在標簽的 key 為 nodeenv 的節點 operator: Exists - key: nodeenv # 匹配標簽的 key 為 nodeenv,且 value 是 "xxx" 或 "yyy" 的節點 operator: In values: ["xxx","yyy"] - key: nodeenv # 匹配標簽的 key 為 nodeenv,且 value 大於 "xxx" 的節點 operator: Gt values: "xxx"
接下來首先演示一下 requiredDuringSchedulingIgnoredDuringExecution
創建 pod-nodeaffinity-required.yaml,內容如下
apiVersion: v1 kind: Pod metadata: name: pod-nodeaffinity-required namespace: zouzou spec: containers: - name: nginx image: nginx:1.14 affinity: # 親和性設置 nodeAffinity: # 設置 node 親和性 requiredDuringSchedulingIgnoredDuringExecution: # 硬限制,沒有滿足就會失敗 nodeSelectorTerms: # node 選擇器,可以有多個 - matchExpressions: # 匹配標簽 - key: nodeenv # 標簽的 key 要為 nodeenv operator: In # 操作符,在里面 values: ["xxx","yyy"] # 值在["xxx","yyy"]中的標簽
創建 pod
# 創建 pod kubectl create -f pod-nodeaffinity-required.yaml
查看 pod 和 pod 的 event
# 查看 pod ,發現 pod 沒有調度到節點上,因為 nodeenv 的值沒有 xxx 或者 yyy,而且是硬限制 [root@dce-10-6-215-215 tmp]# kubectl get pod pod-nodeaffinity-required -n zouzou -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES pod-nodeaffinity-required 0/1 Pending 0 81s <none> <none> <none> <none> # 從 event 可以看到,調度失敗,有三個 node 節點,但是沒有滿足標簽選擇器的 node [root@dce-10-6-215-215 tmp]# kubectl describe pod pod-nodeaffinity-required -n zouzou Name: pod-nodeaffinity-required Namespace: zouzou Priority: 0 Node: <none> Labels: <none> ...... Events: Type Reason Age From Message ---- ------ ---- ---- ------- Warning FailedScheduling 104s default-scheduler 0/3 nodes are available: 3 node(s) didn't match node selector. Warning FailedScheduling 30s default-scheduler 0/3 nodes are available: 3 node(s) didn't match node selector.
從上面我們可以看出,硬限制當沒有匹配的標簽時,會調度失敗。因為我們兩個 node 節點,只有 nodeenv=pro 和 nodeenv=test 的節點,沒有 nodeenv=xxx 或者 nodeenv=yyy 的節點
接下來,我們刪除 pod,把 yyy 改為 pro,因為 nodeenv=pro 是存在的
# 刪除 pod kubectl delete -f pod-nodeaffinity-required.yaml
修改后在創建 pod
# 創建 pod kubectl create -f pod-nodeaffinity-required.yaml
查看 pod
# 可以看到,pod 分配給了 dce-10-6-215-190 的節點上,並成功運行了
[root@dce-10-6-215-215 tmp]# kubectl get pod pod-nodeaffinity-required -n zouzou -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES pod-nodeaffinity-required 1/1 Running 0 17s 172.29.190.143 dce-10-6-215-190 <none> <none> # 從 event 里,也可以看出來,是成功調度的 [root@dce-10-6-215-215 tmp]# kubectl describe pod pod-nodeaffinity-required -n zouzou Name: pod-nodeaffinity-required Namespace: zouzou...... Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 24s default-scheduler Successfully assigned zouzou/pod-nodeaffinity-required to dce-10-6-215-190 Normal Pulled 21s kubelet Container image "nginx:1.14" already present on machine Normal Created 21s kubelet Created container nginx Normal Started 20s kubelet Started container nginx
接下來再演示一下 requiredDuringSchedulingIgnoredDuringExecution
創建 pod-nodeaffinity-preferred.yaml,內容如下
apiVersion: v1 kind: Pod metadata: name: pod-nodeaffinity-preferred namespace: zouzou spec: containers: - name: nginx image: nginx:1.14 affinity: # 親和性設置 nodeAffinity: # 設置 node 親和性 preferredDuringSchedulingIgnoredDuringExecution: # 軟限制,沒有匹配的標簽也會分配給某個 node - weight: 1 # 權重 preference: # 一個節點選擇器項,與相應的權重相關聯 matchExpressions: # 匹配標簽 - key: nodeenv # 標簽的 key 要為 nodeenv operator: In # 操作符,在里面 values: ["xxx","yyy"] # 匹配 env 的值在["xxx","yyy"]中的標簽(當前環境沒有)
創建 pod
kubectl create -f pod-nodeaffinity-preferred.yaml
查看 pod 和 pod event
# 可以看到,成功分配給了 dce-10-6-215-200 的節點上 [root@dce-10-6-215-215 tmp]# kubectl get pod pod-nodeaffinity-preferred -n zouzou -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES pod-nodeaffinity-preferred 1/1 Running 0 53s 172.29.34.238 dce-10-6-215-200 <none> <none> # 從 event 中也可以看出,pod 是調度成功的 [root@dce-10-6-215-215 tmp]# kubectl describe pod pod-nodeaffinity-preferred -n zouzou Name: pod-nodeaffinity-preferred Namespace: zouzou Priority: 0 Node: dce-10-6-215-200/10.6.215.200 Start Time: Sat, 16 Apr 2022 11:45:15 +0800 ...... Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 66s default-scheduler Successfully assigned zouzou/pod-nodeaffinity-preferred to dce-10-6-215-200 Normal Pulled 63s kubelet Container image "nginx:1.14" already present on machine Normal Created 63s kubelet Created container nginx Normal Started 62s kubelet Started container ngin
從上面的結果可以看出,軟限制,當沒有匹配到對應的標簽時,也不會調度失敗,會根據算法分配給合適的節點
NodeAffinity規則設置的注意事項:
- 如果同時定義了 nodeSelector 和 nodeAffinity,那么必須兩個條件都得到滿足,Pod 才能運行在指定的 Node 上
- 如果 nodeAffinity 指定了多個 nodeSelectorTerms,那么只需要其中一個能夠匹配成功即可
- 如果一個 nodeSelectorTerms 中有多個 matchExpressions ,則一個節點必須滿足所有的才能匹配成功
- 如果一個 pod 所在的 Node 在 Pod 運行期間其標簽發生了改變,不再符合該 Pod 的節點親和性需求,則系統將忽略此變化
PodAffinity
PodAffinity 主要實現以運行的 Pod 為參照,實現讓新創建的 Pod 跟參照 pod 在一個區域的功能。
首先來看一下 PodAffinity
的可配置項:
pod.spec.affinity.podAffinity requiredDuringSchedulingIgnoredDuringExecution # 硬限制 namespaces # 指定參照 pod 的 namespace topologyKey # 指定調度作用域 labelSelector # 標簽選擇器 matchExpressions # 按節點標簽列出的節點選擇器要求列表(推薦) key # 鍵 values # 值 operator # 關系符 支持 In, NotIn, Exists, DoesNotExist. matchLabels # 指多個 matchExpressions 映射的內容 preferredDuringSchedulingIgnoredDuringExecution # 軟限制 podAffinityTerm # 選項 namespaces topologyKey labelSelector matchExpressions key # 鍵 values # 值 operator matchLabels weight # 傾向權重,在范圍 1-100
topologyKey 用於指定調度時作用域
- 如果指定為 kubernetes.io/hostname,那就是以 Node 節點為區分范圍
- 如果指定為 beta.kubernetes.io/os,則以 Node 節點的操作系統類型來區分
接下來,演示下 requiredDuringSchedulingIgnoredDuringExecution(硬限制)
首先創建一個參照 Pod,pod-podaffinity-target.yaml,內容如下
apiVersion: v1 kind: Pod metadata: name: pod-podaffinity-target namespace: zouzou labels: podenv: pro # 給 pod 設置標簽 spec: containers: - name: nginx image: nginx:1.14 nodeName: dce-10-6-215-200 # 將目標 pod 明確指定到 dce-10-6-215-200 上
創建 pod
kubectl apply -f pod-podaffinity-target.yaml
接下來創建 創建 pod-podaffinity-required.yaml,內容如下:
apiVersion: v1 kind: Pod metadata: name: pod-podaffinity-required namespace: zouzou spec: containers: - name: nginx image: nginx:1.14 affinity: # 親和性設置 podAffinity: # 設置pod親和性 requiredDuringSchedulingIgnoredDuringExecution: # 硬限制 - labelSelector: matchExpressions: # 匹配env的值在["xxx","yyy"]中的標簽 - key: podenv # 對應的是 pod 的標簽,不是 node 的,上面創建參照 pod 的時候創建了一個 podenv=pro 的標簽 operator: In values: ["xxx","yyy"] # 不存在 podenv=xxx 或者 podenv=yyy topologyKey: kubernetes.io/hostname # 以 node 節點為區分范圍
上面配置表達的意思是:新 Pod 必須要與擁有標簽 podenv=xxx 或者 podenv=yyy 的 pod 在同一 Node 上,顯然現在沒有這樣 pod,接下來,運行測試一下
# 創建 pod kubectl create -f pod-podaffinity-required.yaml
查看 pod 和 pod event
# 查看 pod,發現 pod 未運行,也沒有分配到節點上 [root@dce-10-6-215-215 tmp]# kubectl get pods pod-podaffinity-required -n zouzou -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES pod-podaffinity-required 0/1 Pending 0 30s <none> <none> <none> <none> # 查看 event,底下提示有三個節點,一個節點有污點(master),兩個節點(node)不滿足標簽規則 [root@dce-10-6-215-215 tmp]# [root@dce-10-6-215-215 tmp]# kubectl describe pod pod-nodeaffinity-preferred -n zouzou Name: pod-nodeaffinity-preferred Namespace: zouzou Priority: 0 Node: dce-10-6-215-200/10.6.215.200 Start Time: Sat, 16 Apr 2022 11:45:15 +0800 ...... Events: Type Reason Age From Message ---- ------ ---- ---- ------- Warning FailedScheduling 51s default-scheduler 0/3 nodes are available: 1 node(s) had taint {node-role.kubernetes.io/master: }, that the pod didn't tolerate, 2 node(s) didn't match pod affinity rules, 2 node(s) didn't match pod affinity/anti-affinity.
接下來修改 values: ["xxx","yyy"]----->values:["pro","yyy"]
意思是:新 Pod 必須要與擁有標簽 podenv=xxx 或者 podenv=yyy 的 pod 在同一 Node 上
修改完之后重新創建 pod
# 創建 pod kubectl create -f pod-podaffinity-required.yaml
查看 pod,是正常運行的
# 查看 pod,pod 是正常運行的 [root@dce-10-6-215-215 tmp]# kubectl get pods pod-podaffinity-required -n zouzou -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES pod-podaffinity-required 1/1 Running 0 36s 172.29.34.240 dce-10-6-215-200 <none> <none> # 查看 event,正常 [root@dce-10-6-215-215 tmp]# kubectl describe pods pod-podaffinity-required -n zouzou Name: pod-podaffinity-required Namespace: zouzou Priority: 0 Node: dce-10-6-215-200/10.6.215.200 Start Time: Sat, 16 Apr 2022 12:19:04 +0800 ...... Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 41s default-scheduler Successfully assigned zouzou/pod-podaffinity-required to dce-10-6-215-200 Normal Pulled 39s kubelet Container image "nginx:1.14" already present on machine Normal Created 38s kubelet Created container nginx Normal Started 38s kubelet Started container nginx
可以看到,我們的參考 pod 在 dce-10-6-215-200節點上,配置了 pod 親和性之后,也在 dce-10-6-215-200 節點上
關於 PodAffinity
的 preferredDuringSchedulingIgnoredDuringExecution
,這里不再演示。
PodAntiAffinity
PodAntiAffinity 主要實現以運行的 Pod 為參照,讓新創建的 Pod 跟參照 pod 不在一個區域中的功能。
它的配置方式和選項跟 PodAffinty 是一樣的,這里不再做詳細解釋,直接做一個測試案例。
繼續使用上個案例中目標 pod,pod-podaffinity-target.yaml
創建 pod-podantiaffinity-required.yaml,內容如下:
apiVersion: v1 kind: Pod metadata: name: pod-podantiaffinity-required namespace: zouzou spec: containers: - name: nginx image: nginx:1.14 affinity: # 親和性設置 podAntiAffinity: #設置 pod 反親和性 requiredDuringSchedulingIgnoredDuringExecution: # 硬限制 - labelSelector: matchExpressions: # 匹配env的值在["xxx","yyy"]中的標簽 - key: podenv # 對應的是 pod 的標簽,不是 node 的,上面創建參照 pod 的時候創建了一個 podenv=pro 的標簽 operator: In values: ["pro"] # 反親和性,不在和 pod 的標簽 podenv=pro 的節點上 topologyKey: kubernetes.io/hostname #
創建 pod
kubectl create -f pod-podantiaffinity-required.yaml
可以看到,因為我們設置了反親和性,創建的 pod 就沒有和 podenv=pro 標簽的 pod 在一台 node 機器上
污點和容忍
污點(Taints)
前面的調度方式都是站在 pod 的角度上,通過在 pod 上添加屬性,來確定 pod 是否要調度到指定的 node 上,其實我們也可以站在 node 的角度上,通過在 node 上添加污點屬性,來決定是否允許 pod 調度過來
node 被設置上污點之后就和 pod 之間存在了一種互斥的關系,進而拒絕 pod 調度進來,甚至可以將已經存在的 pod 驅逐出去
污點的格式為:key=value:effect,key 和 value 是污點的標簽,effect 描述污點的作用,支持如下三個選項
- PreferNoSchedule:kubernetes 將盡量避免把 Pod 調度到具有該污點的 Node上,除非沒有其他節點可調度
- NoSchedule:kubernetes 將不會把 Pod 調度到具有該污點的 Node 上,但不會影響當前 Node 上已存在的 Pod
- NoExecute:kubernetes 將不會把 Pod 調度到具有該污點的 Node 上,同時也會將 Node 上已存在的 Pod 驅離
使用 kubectl 設置和去除污點的命令示例如下:
# 設置污點 kubectl taint nodes node1 key=value:effect # 去除污點 kubectl taint nodes node1 key:effect- # 去除所有污點 kubectl taint nodes node1 key-
接下來,演示下污點的效果
- 准備一個節點,為了演示效果更加明顯,只需要一個 master 和一個 worker 即可
- 為 node 節點設置一個污點:tag=hihi:PreferNoSchedule,然后創建 pod1
- 修改 node 節點的污點:tag=hihi:NoSchedule,然后創建 pod2
- 修改 node 節點的污點:tag=NoExecute,然后創建 pod3
# 為 node 設置污點(PreferNoSchedule) kubectl taint node dce-10-6-215-190 tag=hihi:PreferNoSchedule
查看節點 dce-10-6-215-190 的污點,使用下面命令
# 查看 dce-10-6-215-190 節點的污點 kubectl describe node dce-10-6-215-190
創建 pod
# 創建 pod,名稱叫 demo1 [root@dce-10-6-215-215 tmp]# kubectl run demo1 --image=nginx:1.14 -n zouzou [root@dce-10-6-215-215 tmp# kubectl get pods -n zouzou -o wide NAME READY STATUS RESTARTS AGE IP NODE demo1-7665f7fd85-574h4 1/1 Running 0 2m24s 10.244.1.59 dce-10-6-215-190
從結果可以看到,我們創建的 pod 運行在了 dce-10-6-215-190 的節點上,雖然 dce-10-6-215-190 我們添加了污點,但污點是 tag=hihi:PreferNoSchedule,也就是盡量避免不添加到有污點的節點上,但只有這一個 worker 節點,所以也就調度到了 dce-10-6-215-190 的節點上
刪除污點,創建一個新污點,不能修改
# 刪除污點 tag:PreferNoSchedule- kubectl taint node dce-10-6-215-190 tag:PreferNoSchedule-
刪除后,在去查看已經沒有了
# 查看污點 kubectl describe node dce-10-6-215-190
設置 NoSchedule 污點
# 給 dce-10-6-215-190 節點設置污點 tag=hihi:NoSchedule kubectl taint node dce-10-6-215-190 tag=hihi:NoSchedule
查看污點
在來創建一個新 pod 查看是否可以成功創建
# 創建 pod,名稱為 demo2 [root@dce-10-6-215-215 tmp]# kubectl run demo2 --image=nginx:1.14 -n zouzou [root@dce-10-6-215-215 tmp]# kubectl get pods -n zouzou -o wide NAME READY STATUS RESTARTS AGE IP NODE demo1-7665f7fd85-574h4 1/1 Running 0 2m24s 10.244.1.59 dce-10-6-215-190 demo2-544694789-6zmlf 0/1 Pending 0 21s <none> <none>
從上面可以看出,我們新創建的 pod demo2 沒有創建成功,但 demo1 還是正常運行的,因為我們創建的污點是 tag=hihi:NoSchedule(kubernetes 將不會把 Pod 調度到具有該污點的 Node 上,但不會影響當前 Node 上已存在的 Pod)
刪除污點,創建一個新污點,不能修改
# 刪除污點 kubectl taint node dce-10-6-215-190 tag:NoSchedule-
刪除后,在去查看已經沒有了
# 查看污點 kubectl describe node dce-10-6-215-190
設置 NoExecute 污點
# 給 dce-10-6-215-190 節點設置污點 tag=hihi:NoExecute kubectl taint node dce-10-6-215-190 tag=hihi:NoExecute
查看污點,污點已經設置成功了
在來創建一個新 pod 查看是否可以成功創建
# 創建 pod,名稱叫 demo3 [root@dce-10-6-215-215 tmp]# kubectl run demo3 --image=nginx:1.14 -n zouzou [root@dce-10-6-215-215 tmp]# kubectl get pods -n zouzou -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED demo1-7665f7fd85-htkmp 0/1 Pending 0 35s <none> <none> <none> demo2-544694789-bn7wb 0/1 Pending 0 35s <none> <none> <none> demo3-6d78dbd749-tktkq 0/1 Pending 0 6s <none> <none> <none>
從上面結果可以看出,pod demo3 沒有創建成功,而之前成功的 pod demo1 也被移除了,這是因為我們設置的污點是 tag=hihi:NoExecute(不會把 Pod 調度到具有該污點的 Node 上,同時也會將 Node 上已存在的 Pod 驅離)
使用 kubeadm 搭建的集群,默認就會給 master 節點添加一個污點標記,所以 pod 就不會調度到 master 節點上
容忍(Toleration)
上面介紹了污點的作用,我們可以在 node 上添加污點用於拒絕 pod 調度上來,但是如果就是想將一個 pod 調度到一個有污點的 node 上去,這時候應該怎么做呢?這就要使用到容忍
污點就是拒絕,容忍就是忽略,Node 通過污點拒絕 pod 調度上去,Pod 通過容忍忽略拒絕
下面先通過一個案例看下效果:
- 上面,已經在 dce-10-6-215-190 節點上打上了
NoExecute
的污點,此時 pod 是調度不上去的 - 可以通過給 pod 添加容忍,然后將其調度上去
創建 pod-toleration.yaml 內容如下,先創建個不添加容忍的,創建 pod 查看效果,在創建個添加了容忍的,創建 pod,查看效果
apiVersion: v1 kind: Pod metadata: name: pod-toleration namespace: dev spec: containers: - name: nginx image: nginx:1.17.1 tolerations: # 添加容忍,下面的意思就是:tag=hihi:NoExecute - key: "tag" # 要容忍的污點的key operator: "Equal" # 操作符,Equal 為等於 value: "hihi" # 容忍的污點的value effect: "NoExecute" # 添加容忍的規則,這里必須和標記的污點規則相同
# 添加容忍之前的pod [root@dce-10-6-215-215 tmp]# kubectl get pods -n zouzou -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED pod-toleration 0/1 Pending 0 3s <none> <none> <none> # 添加容忍之后的pod [root@dce-10-6-215-215 tmp]# kubectl get pods -n zouzou -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED pod-toleration 1/1 Running 0 3s 10.244.1.62 dce-10-6-215-190 <none>
可以看到,添加了容忍之后,節點有 node,也可以創建成功
下面看一下容忍的詳細配置
[root@dce-10-6-215-215 tmp]# kubectl explain pod.spec.tolerations ...... FIELDS: key # 對應着要容忍的污點的鍵,空意味着匹配所有的鍵 value # 對應着要容忍的污點的值 operator # key-value 的運算符,支持 Equal 和 Exists(默認),Exists 是存在的意思,只判斷 key,不需要寫 value,只要 key 存在就行 effect # 對應污點的effect,空意味着匹配所有影響 tolerationSeconds # 容忍時間, 當 effect 為 NoExecute 時生效,表示之前在你 node 節點上的 pod 的停留時間,超過了這個時間,node 就會將 pod 移除
刪除多個污點
上面我們 dce-10-6-215-190 已經有一個污點了,接下來在添加一個污點
上面節點上已經有兩個污點了,可以使用下面命令刪除相同 key 的污點
# 刪除相同 key 的污點,這里刪除 key=tag 的污點 kubectl taint nodes dce-10-6-215-190 tag-