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 這個過程包含以下幾個步驟:
- 排程到某臺 node 上。kubernetes 根據一定的優先順序演算法選擇一臺 node 節點將其作為 Pod 執行的 node
- 拉取映象
- 掛載儲存配置等
- 執行起來。如果有健康檢查,會根據檢查的結果來設定其狀態。
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 所在主機通訊失敗。
四: 故障排除步驟
-
檢視Pod事件
- kubectl describe TYPE NAME_PREFIX
-
檢視Pod日誌(Failed狀態下)
- kubectl logs <POD_NAME> [-c Container_NAME]
-
進入Pod(狀態為running,但是服務沒有提供)
- kubectl exec –it <POD_NAME> bash
-
檢視叢集資訊
- kubectl get nodes
-
發現叢集狀態正常
- kubectl cluster-info
-
檢視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的影響