1. 程式人生 > 其它 >k8s資源控制(汙點和容忍)

k8s資源控制(汙點和容忍)

目錄

一: 汙點

1.1 汙點的作用

節點親和性,是Pod的一種屬性(偏好或硬性要求) ,它使Pod被吸引到一類特定的節點。Taint則相反,它使節點能夠排斥一類特定的PodTaint和Toleration相互配合,可以用來避免Pod被分配到不合適的節點上。每個節點上都可以應用一個或多個taint

,這表示對於那些不能容忍這些taint的Pod,是不會被該節點接受的。如果將toleration應用於Pod上,則表示這些Pod

可以(但不一定)被排程到具有匹配taint的節點上。

使用kubectl taint命令可以給某個Node節點設定汙點, Node被設定上汙點之後就和Pod之間存在了一種相斥的關係,可以讓Node拒絕Pod的排程執行,甚至將Node已經存在的Pod驅逐出去。

/



1.2 汙點的組成

汙點的組成格式如下:key-value:effect

每個汙點有一個key和value作為汙點的標籤,其中value可以為空, effect描述汙點的作用。

當前taint effect支援如下三個選項:

  • NoSchedule:表示k8s將不會將Pod排程到具有該汙點的Node上
  • PreferNoschedule:表示k8s將盡量避免將Pod排程到具有該汙點的Node上
  • NoExecute:表示k8s將不會將Pod排程到具有該汙點的Node上,同時會將Node上已經存在的Pod驅逐出去
[root@master ~]# kubectl  describe  nodes  master  | grep -i 'taints'
Taints:             node-role.kubernetes.io/master:NoSchedule



1.3 設定,檢視,去除汙點

#為node01節點設定汙點 key1=value1:NoSchedule.  NoSchedule便是pod不排程到這個節點
[root@master ~]# kubectl  taint  nodes node01 key1=value1:NoSchedule
node/node01 tainted

#通過describe 檢視節點詳細資訊檢視汙點,並不區分大小寫過濾 ‘key'
[root@master ~]# kubectl  describe node node01 | grep -i 'key1'
Taints:             key1=value1:NoSchedule
[root@master ~]# 
#刪除node01的汙點key1:NoSchedule
[root@master ~]# kubectl  taint  node node01 key1:NoSchedule-
node/node01 untainted
[root@master ~]# kubectl  describe node node01 | grep -i 'key1'



1.4 示例

[root@master demo]# kubectl  get pods -o wide
NAME      READY   STATUS    RESTARTS   AGE   IP             NODE     NOMINATED NODE   READINESS GATES
myapp01   1/1     Running   0          29s   10.244.1.143   node01   <none>           <none>
myapp02   1/1     Running   0          17s   10.244.2.110   node02   <none>           <none>
myapp03   1/1     Running   0          9s    10.244.1.144   node01   <none>           <none>
[root@master demo]# 

#設定node01節點,不允許將pod排程到上面,同時還會驅逐該節點上的pod
[root@master demo]# kubectl  taint  node node01 check=mycheck:NoExecute
node/node01 tainted

#node01節點上的pod被驅逐
[root@master demo]# kubectl  get pods -o wide
NAME      READY   STATUS    RESTARTS   AGE   IP             NODE     NOMINATED NODE   READINESS GATES
myapp02   1/1     Running   0          84s   10.244.2.110   node02   <none>           <none>

注意:如果是Deployment或者StateFulSet資源型別,為了未出副本數量,則會在其他的node上建立新的pod



二:容忍

2.1 容忍的作用

容忍(Tolerations)

設定了汙點的Node將根據taint的effect : Noschedule, PreferNoschedule, NoExecute和Pod之間產生互斥的關係, Pod將在一定程度上不會被排程到Node上。但我們可以在Pod上設定容忍(Tolerations) ,意思是設定了容忍的Pod

將可以容忍汙點的存在,可以被排程到存在汙點的Node上。



2.2 示例

2.2.1 將兩個節點都設定汙點

#將node02也打上汙點NoExecute。node01和node02都有此汙點
[root@master demo]# kubectl  taint  node node02 check=mycheck:NoExecute
node/node02 tainted

[root@master demo]# vim pod3.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: myapp01
  labels:
    app: myapp01
spec:
  containers:
  - name: with-node-affinity
    image: soscscs/myapp:v1

[root@master demo]# kubectl  apply  -f pod3.yaml 
pod/myapp01 created

#此時,兩個節點都設定了NoExecute,所以,pod無法排程
root@master demo]# kubectl  get pods -o wide
NAME      READY   STATUS    RESTARTS   AGE   IP       NODE     NOMINATED NODE   READINESS GATES
myapp01   0/1     Pending   0          23s   <none>   <none>   <none>           <none>


2.2.2 在pod上配置容忍

[root@master demo]# vim pod3.yaml
apiVersion: v1
kind: Pod
metadata:
  name: myapp01
  labels:
    app: myapp01
spec:
  containers:
  - name: with-node-affinity
    image: soscscs/myapp:v1
  tolerations:
  - key: "check"
    operator: "Equal"
    value: "mycheck"
    effect: "NoExecute"
    tolerationSeconds: 3600


#其中的 key、vaule、effect 都要與 Node 上設定的 taint 保持一致
#operator 的值為 Exists 將會忽略 value 值,即存在即可
#tolerationSeconds 用於描述當 Pod 需要被驅逐時可以在 Pod 上繼續保留執行的時間
#如果不設定tolerationSeconds,則pod將不限時
#在配置了pod的容忍後,pod的狀態變為了running
[root@master demo]# kubectl  get pods  -o wide
NAME      READY   STATUS    RESTARTS   AGE     IP             NODE     NOMINATED NODE   READINESS GATES
myapp01   1/1     Running   0          6m18s   10.244.2.111   node02   <none>           <none>



2.3 注意事項

#當不指定 key 值時,表示容忍所有的汙點 key
  tolerations:
  - operator: "Exists"
  
#當不指定 effect 值時,表示容忍所有的汙點作用
  tolerations:
  - key: "key"
    operator: "Exists"

#有多個 Master 存在時,防止資源浪費,可以如下設定
kubectl taint nodes Master-Name node-role.kubernetes.io/master=:PreferNoSchedule

2.4 node更新時對pod的操作

#如果某個 Node 更新升級系統元件,為了防止業務長時間中斷,可以先在該 Node 設定 NoExecute 汙點,把該 Node 上的 Pod 都驅逐出去
kubectl taint nodes node01 check=mycheck:NoExecute

#此時如果別的 Node 資源不夠用,可臨時給 Master 設定 PreferNoSchedule 汙點,讓 Pod 可在 Master 上臨時建立
kubectl taint nodes master node-role.kubernetes.io/master=:PreferNoSchedule

#待所有 Node 的更新操作都完成後,再去除汙點
kubectl taint nodes node01 check=mycheck:NoExecute-



三: Pod啟動階段

3.1 Pod過程的步驟

Pod 建立完之後,一直到持久執行起來,中間有很多步驟,也就有很多出錯的可能,因此會有很多不同的狀態。
一般來說,pod 這個過程包含以下幾個步驟:

  1. 排程到某臺 node 上。kubernetes 根據一定的優先順序演算法選擇一臺 node 節點將其作為 Pod 執行的 node
  2. 拉取映象
  3. 掛載儲存配置等
  4. 執行起來。如果有健康檢查,會根據檢查的結果來設定其狀態。



3.2 Pod啟動的5種狀態

phase 的可能狀態有:
●Pending:表示APIServer建立了Pod資源物件並已經存入了etcd中,但是它並未被排程完成(比如還沒有排程到某臺node上),或者仍然處於從倉庫下載映象的過程中。

●Running:Pod已經被排程到某節點之上,並且Pod中所有容器都已經被kubelet建立。至少有一個容器正在執行,或者正處於啟動或者重啟狀態(也就是說Running狀態下的Pod不一定能被正常訪問)。

●Succeeded:有些pod不是長久執行的,比如job、cronjob,一段時間後Pod中的所有容器都被成功終止,並且不會再重啟。需要反饋任務執行的結果。

●Failed:Pod中的所有容器都已終止了,並且至少有一個容器是因為失敗終止。也就是說,容器以非0狀態退出或者被系統終止,比如 command 寫的有問題。

●Unknown:因為某些原因無法取得 Pod 的狀態,通常是因為與 Pod 所在主機通訊失敗。



四: 故障排除步驟

  1. 檢視Pod事件

    • kubectl describe TYPE NAME_PREFIX
  2. 檢視Pod日誌(Failed狀態下)

    • kubectl logs <POD_NAME> [-c Container_NAME]
  3. 進入Pod(狀態為running,但是服務沒有提供)

    • kubectl exec –it <POD_NAME> bash
  4. 檢視叢集資訊

    • kubectl get nodes
  5. 發現叢集狀態正常

    • kubectl cluster-info
  6. 檢視kubelet日誌發現

    • journalctl -xefu kubelet



五:對節點執行維護操作

kubectl get nodes

//將 Node 標記為不可排程的狀態,這樣就不會讓新建立的 Pod 在此 Node 上執行
kubectl cordon <NODE_NAME> 		 #該node將會變為SchedulingDisabled狀態

//kubectl drain 可以讓 Node 節點開始釋放所有 pod,並且不接收新的 pod 程序。drain 本意排水,意思是將出問題的 Node 下的 Pod 轉移到其它 Node 下執行
kubectl drain <NODE_NAME> --ignore-daemonsets --delete-local-data --force

--ignore-daemonsets:無視 DaemonSet 管理下的 Pod。
--delete-local-data:如果有 mount local volume 的 pod,會強制殺掉該 pod。
--force:強制釋放不是控制器管理的 Pod,例如 kube-proxy。

注:執行 drain 命令,會自動做了兩件事情:
(1)設定此 node 為不可排程狀態(cordon)
(2)evict(驅逐)了 Pod

//kubectl uncordon 將 Node 標記為可排程的狀態
kubectl uncordon <NODE_NAME>

如果node的標記為 cordon ,則經過scheduler排程的pod,無法排程到那個節點。
而使用nodeName 進行指定,則跳過了scheduler 排程過程,因此不會受到cordon的影響