您好,登錄后才能下訂單哦!
今天就跟大家聊聊有關K8S線上集群怎樣排查Node節點NotReady異常狀態,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結了以下內容,希望大家根據這篇文章可以有所收獲。
k8s 線上集群中 Node 節點狀態變成 NotReady 狀態,導致整個 Node 節點中容器停止服務后的問題排查。
文章中所描述的是本人在項目中線上環境實際解決的,那除了如何解決該問題,更重要的是如何去排查這個問題的起因。
關于 Node 節點不可用的 NotReady 狀態,當時也是花了挺久的時間去排查的。
在分析 NotReady 狀態之前,我們首先需要了解在 k8s 中 Pod 的狀態都有哪些。并且每個狀態都表示什么含義,不同狀態是很直觀的顯示出當前 Pod 所處的創建信息。
為了避免大家對 Node 和 Pod 的概念混淆,先簡單描述下兩者之間的關系(引用一張 K8S 官方圖)。
從圖中很直觀的顯示出最外面就是 Node 節點,而一個 Node 節點中是可以運行多個 Pod 容器,再深入一層就是每個 Pod 容器可以運行多個實例 App 容器。
因此關于本篇文章所闡述的 Node 節點不可用,就會直接導致 Node 節點中所有的容器不可用。
毫無疑問,Node 節點是否健康,直接影響該節點下所有的實例容器的健康狀態,直至影響整個 K8S 集群。
那么如何解決并排查 Node 節點的健康狀態?不急,我們先來聊聊關于關于 Pod 的生命周期狀態。
Pending
:該階段表示已經被 Kubernetes 所接受,但是容器還沒有被創建,正在被 kube 進行資源調度。
1
:圖中數字 1 是表示在被 kube 資源調度成功后,開始進行容器的創建,但是在這個階段是會出現容器創建失敗的現象
Waiting或ContainerCreating
:這兩個原因就在于容器創建過程中鏡像拉取失敗,或者網絡錯誤容器的狀態就會發生轉變。
Running
:該階段表示容器已經正常運行。
Failed
:Pod 中的容器是以非 0 狀態(非正常)狀態退出的。
2
:階段 2 可能出現的狀態為CrashLoopBackOff
,表示容器正常啟動但是存在異常退出。
Succeeded
:Pod 容器成功終止,并且不會再在重啟。
上面的狀態只是 Pod 生命周期中比較常見的狀態,還有一些狀態沒有列舉出來。
這。。。狀態有點多。休息 3 秒鐘
不過話又說回來,Pod 的狀態和 Node 狀態是一回事嗎?嗯。。。其實并不完全是一回事。
但是當容器服務不可用時,首先通過 Pod 的狀態去排查是非常重要的。那么問題來了,如果 Node 節點服務不可用,Pod 還能訪問嗎?
答案是:不能。
因此排查Pod的健康狀態的意義就在于,是什么原因會導致Node節點服務不可用,因此這是一項非常重要的排查指標。
由于本人的工作是和物聯網相關的,暫且我們假設 4 臺服務器(假設不考慮服務器本身性能問題,如果是這個原因那最好是升級服務器),其中一臺做 K8S-Master 搭建,另外 3 臺機器做 Worker 工作節點。
每個 worker 就是一個 Node 節點,現在需要在 Node 節點上去啟動鏡像,一切正常 Node 就是 ready 狀態。
但是過了一段時間后,就成這樣了
這就是我們要說的 Node 節點變成 NotReady 狀態。
這跑著跑著就變成 NotReady 了,啥是 NotReady?
這都運行一段時間了,你告訴我還沒準備好?
好吧,那就看看為什么還沒準備好。
再回到我們前面說到問題,就是 Node 節點變成 NotReady 狀態后,Pod 容器是否還成正常運行。
圖中用紅框標示的就是在節點edgenode
上,此時 Pod 狀態已經顯示為Terminating,表示 Pod 已經終止服務。
接下來我們就分析下 Node 節點為什么不可用。
(1)首先從服務器物理環境排查,使用命令df -m
查看磁盤的使用情況
或者直接使用命令free
查看
磁盤并沒有溢出,也就是說物理空間足夠。
(2)接著我們再查看下 CPU 的使用率,命令為:top -c (大寫P可倒序)
CPU 的使用率也是在范圍內,不管是在物理磁盤空間還是 CPU 性能,都沒有什么異常。那 Node 節點怎么就不可用了呢?而且服務器也是正常運行中。
這似乎就有點為難了,這可咋整?
(3)不慌,還有一項可以作為排查的依據,那就是使用 kube 命令 describe 命令查看 Node 節點的詳細日志。完整命令為:
kubectl describe node <節點名稱>
,那么圖中 Node 節點如圖:
哎呀,好像在這個日志里面看到了一些信息描述,首先我們先看第一句:Kubelet stoped posting node status
,大致的意思是 Kubelet 停止發送 node 狀態了,再接著Kubelet never posted node status
意思為再也收不到 node 狀態了。
查看下 Kubelet 是否在正常運行,是使用命令:
systemctl status kubelet
,如果狀態為 Failed,那么是需要重啟下的。但如果是正常運行,請繼續向下看。
分析一下好像有點眉目了,Kubelet 為什么要發送 node 節點的狀態呢?這就拋出了關于 Pod 的另一個知識點,請耐心向下看。
根據我們最后面分析的情形,似乎是 node 狀態再也沒有收到上報,導致 node 節點不可用,這就引申出關于 Pod 的生命健康周期。
PLEG
全稱為:Pod Lifecycle Event Generator
:Pod 生命周期事件生成器。
簡單理解就是根據 Pod 事件級別來調整容器運行時的狀態,并將其寫入 Pod 緩存中,來保持 Pod 的最新狀態。
在上述圖中,看出是 Kubelet 在檢測 Pod 的健康狀態。Kubelet 是每個節點上的一個守護進程,Kubelet 會定期去檢測 Pod 的健康信息,先看一張官方圖。
PLEG
去檢測運行容器的狀態,而 kubelet 是通過輪詢機制去檢測的。
分析到這里,似乎有點方向了,導致 Node 節點變成 NotReady 狀態是和 Pod 的健康狀態檢測有關系,正是因為超過默認時間了,K8S 集群將 Node 節點停止服務了。
那為什么會沒有收到健康狀態上報呢?我們先查看下在 K8S 中默認檢測的時間是多少。
在集群服務器是上,進入目錄:/etc/kubernetes/manifests/kube-controller-manager.yaml
,查看參數:
–node-monitor-grace-period=40s(node驅逐時間) –node-monitor-period=5s(輪詢間隔時間)
上面兩項參數表示每隔 5 秒 kubelet 去檢測 Pod 的健康狀態,如果在 40 秒后依然沒有檢測到 Pod 的健康狀態便將其置為 NotReady 狀態,5 分鐘后就將節點下所有的 Pod 進行驅逐。
官方文檔中對 Pod 驅逐策略進行了簡單的描述,https://kubernetes.io/zh/docs/concepts/scheduling-eviction/eviction-policy/
kubelet 輪詢檢測 Pod 的狀態其實是一種很消耗性能的操作,尤其隨著 Pod 容器的數量增加,對性能是一種嚴重的消耗。
在 GitHub 上的一位小哥對此也表示有自己的看法,原文鏈接為:
https://github.com/fabric8io/kansible/blob/master/vendor/k8s.io/kubernetes/docs/proposals/pod-lifecycle-event-generator.md
到這里我們分析的也差不多了,得到的結論為:
Pod 數量的增加導致 Kubelet 輪詢對服務器的壓力增大,CPU 資源緊張
Kubelet 輪詢去檢測 Pod 的狀態,就勢必受網絡的影響
Node 節點物理硬件資源限制,無法承載較多的容器
而由于本人當時硬件的限制,及網絡環境較差的前提下,所以只改了上面了兩項參數配置,延長 Kubelet 去輪詢檢測 Pod 的健康狀態。實際效果也確實得到了改善。
// 需要重啟docker sudo systemctl restart docker // 需要重啟kubelet sudo systemctl restart kubelet
但是如果條件允許的情況下,個人建議最好是從硬件方面優化。
提高 Node 節點的物理資源
優化 K8S 網絡環境
最后分享一些常用的 K8S 命令
kubectl get pods -n <namespaces>
kubectl get nodes
kubectl describe pod <podname> -n <namespaces>
kubectl logs -f <podname> -n <namespaces>
kubectl get pod <podname> -n <namespaces> -o yaml
kubectl get pod -l app=<labelname> -n <namespaces>
kubectl -n <namespaces> get pods|grep <podname>|awk '{print $3}'
kubectl delete pod <podname> -n <namespaces>
kubectl delete deployment <deploymentname> -n <namespaces>
kubectl delete pod <podname> -n <namespaces> --force --grace-period=0
kubectl exec -it <podname> -n <namespaces> -- sh
kubectl label node <nodename> app=label
kubectl get node -l "<labelname>"
kubectl get node --show-labels=true
看完上述內容,你們對K8S線上集群怎樣排查Node節點NotReady異常狀態有進一步的了解嗎?如果還想了解更多知識或者相關內容,請關注億速云行業資訊頻道,感謝大家的支持。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。