k8s 重啟維護節點,這樣操作才安全!
背景
一個專案用的 k8s 叢集發現了個 bug ,處理完成後需要重啟節點才能徹底修復。為了避免業務受到影響,在操作節點重啟前我們需要將當前節點上執行的所有業務 pod 都驅逐到其他節點上以繼續提供服務。這裡記錄下操作方法及注意事項,特別是結尾總結的注意事項,一定要認真檢查。
將 pod 驅逐到其他節點
一般情況下要將某節點上 pod 都驅逐出去我們可以直接使用 kubectl drain 命令來實現,如下所示:
1、獲取叢集中節點列表
[root@imzcy ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
192.168.2.41 Ready <none> 543d v1.22.5-tke.6
192.168.2.15 Ready <none> 436d v1.22.5-tke.12
192.168.2.8 Ready <none> 540d v1.22.5-tke.6
[root@imzcy ~]#
2、使用 kubectl drain 命令來驅逐指定節點上 pod
[root@imzcy ~]# kubectl drain --ignore-daemonsets 192.168.2.41
node/192.168.2.41 cordoned
WARNING: ignoring DaemonSet-managed Pods: kube-monitor/node-exporter-knxrq, kube-system/csi-nodeplugin-cfsplugin-xz66b
evicting pod uat/zcy-test-0418-6688fbff7b-kmrj4
pod/zcy-test-0418-6688fbff7b-kmrj4 evicted
node/192.168.2.41 evicted
[root@imzcy ~]#
drain 子命令的效果相當於:
-
給指定節點新增 node.kubernetes.io/unschedulable:NoSchedule 汙點。
-
將節點狀態標記為不可排程。
-
給指定節點上所有執行中的 Pod 傳送 SIGTERM 訊號以優雅終止 pod。
3、使節點重新變可用
重新維護好節點後,需要使用 kubectl uncordon,這將使節點重新變為可排程。
[
知道了 drain 命令的工作邏輯,我們也可以自己手動操作(使得過程更加可控):
- 給節點新增一個不能被現有 pod 容忍的汙點,並將 effect 欄位值設定為 NoSchedule(新的 Pod 不會被排程到此節點上,當前正在節點上執行的 Pod 不會被驅逐)。
- 手動將當前節點上執行的 pod delete 掉,由於設定了汙點所以 delete 掉的 pod 不會被重新排程到當前節點。
- 指定 pod 被 delete 掉後,可以觀察下是否在其他節點重新排程並正常執行,新 pod 排程到其他節點後資源負載情況是否在正常使用閾值內,如果一切正常,再繼續 delete 下一個 pod 一直到全部完成。
- 確認沒有業務 pod 在節點上執行了,再重啟節點進行維護。
- 重啟完成確認問題修復後,刪除節點上之前定義好的汙點。
特別注意
使用 drain 命令等清空節點時需要注意:
- 如果存在新的、能夠容忍 node.kubernetes.io/unschedulable 等汙點的 Pod, 那麼這些 Pod 可能會被排程到你已經清空的節點上。所以除了 DaemonSet 之外,請避免容忍此汙點(避免容忍所有汙點)。
-
如果你或另一個 API 使用者(繞過排程器)直接為 Pod 設定了 nodeName 欄位, 則即使你已將該節點清空並標記為不可排程,Pod 仍將被繫結到這個指定的節點並在該節點上執行。
-
如果節點上存在不受控制器管理的 pod(replication controller, replica set, daemon set, stateful set, 或 job),則必須新增使用 --force 選項,否則 drain 不會刪除任何Pod。
-
由於執行 drain 命令會將節點所有 pod 驅逐到其他節點上執行,所以如果節點本身承載大量的 pod ,需要注意評估該節點上所有 pod 被重新排程到其他節點上執行時是否會對叢集資源造成壓力。
-
確保沒有外部沒有直接呼叫此節點的 IP 進行業務請求的(NodePort),否則會導致重啟期間無法正常訪問。
謝謝閱讀