K8S線上集羣排查,實測排查Node節點NotReady異常狀態

一,文章簡述

你們好,本篇是我的的第 2 篇文章。是關於在以前項目中,k8s 線上集羣中 Node 節點狀態變成 NotReady 狀態,致使整個 Node 節點中容器中止服務後的問題排查。node

文章中所描述的是本人在項目中線上環境實際解決的,那除了如何解決該問題,更重要的是如何去排查這個問題的原由。git

關於 Node 節點不可用的 NotReady 狀態,當時也是花了挺久的時間去排查的。github

二,Pod 狀態

在分析 NotReady 狀態以前,咱們首先須要瞭解在 k8s 中 Pod 的狀態都有哪些。而且每一個狀態都表示什麼含義,不一樣狀態是很直觀的顯示出當前 Pod 所處的建立信息。docker

爲了不你們對 Node 和 Pod 的概念混淆,先簡單描述下二者之間的關係(引用一張 K8S 官方圖)。緩存

從圖中很直觀的顯示出最外面就是 Node 節點,而一個 Node 節點中是能夠運行多個 Pod 容器,再深刻一層就是每一個 Pod 容器能夠運行多個實例 App 容器。服務器

所以關於本篇文章所闡述的 Node 節點不可用,就會直接致使 Node 節點中全部的容器不可用。網絡

毫無疑問,Node 節點是否健康,直接影響該節點下全部的實例容器的健康狀態,直至影響整個 K8S 集羣。app

那麼如何解決並排查 Node 節點的健康狀態?不急,咱們先來聊聊關於關於 Pod 的生命週期狀態。oop

  • Pending:該階段表示已經被 Kubernetes 所接受,可是容器尚未被建立,正在被 kube 進行資源調度。
  • 1:圖中數字 1 是表示在被 kube 資源調度成功後,開始進行容器的建立,可是在這個階段是會出現容器建立失敗的現象
  • Waiting或ContainerCreating:這兩個緣由就在於容器建立過程當中鏡像拉取失敗,或者網絡錯誤容器的狀態就會發生轉變。
  • Running:該階段表示容器已經正常運行。
  • Failed:Pod 中的容器是以非 0 狀態(非正常)狀態退出的。
  • 2:階段 2 可能出現的狀態爲CrashLoopBackOff,表示容器正常啓動可是存在異常退出。
  • Succeeded:Pod 容器成功終止,而且不會再在重啓。

上面的狀態只是 Pod 生命週期中比較常見的狀態,還有一些狀態沒有列舉出來。post

這。。。狀態有點多。休息 3 秒鐘

不過話又說回來,Pod 的狀態和 Node 狀態是一回事嗎?嗯。。。其實並不徹底是一回事。

可是當容器服務不可用時,首先經過 Pod 的狀態去排查是很是重要的。那麼問題來了,若是 Node 節點服務不可用,Pod 還能訪問嗎?

答案是:不能

所以排查Pod的健康狀態的意義就在於,是什麼緣由會致使Node節點服務不可用,所以這是一項很是重要的排查指標。

三,業務回顧

因爲本人的工做是和物聯網相關的,暫且咱們假設 4 臺服務器(假設不考慮服務器自己性能問題,若是是這個緣由那最好是升級服務器),其中一臺作 K8S-Master 搭建,另外 3 臺機器作 Worker 工做節點。

每一個 worker 就是一個 Node 節點,如今須要在 Node 節點上去啓動鏡像,一切正常 Node 就是ready狀態。

可是過了一段時間後,就成這樣了

這就是咱們要說的 Node 節點變成 NotReady 狀態。

四,問題刨析

這跑着跑着就變成 NotReady 了,啥是 NotReady?

這都運行一段時間了,你告訴我還沒準備好?

好吧,那就看看爲何還沒準備好。

4.1 問題分析

再回到咱們前面說到問題,就是 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 的另外一個知識點,請耐心向下看。

五,Pod 健康檢測 PLEG

根據咱們最後面分析的情形,彷佛是 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 經常使用命令

最後分享一些經常使用的 K8S 命令

1,查詢所有 pod(命名空間)

kubectl get pods -n

2,查詢所有 node 節點

kubectl get nodes

3,查看 pod 詳細信息和日誌

kubectl describe pod -n

kubectl logs -f -n

4,查看 pod-yaml 文件

kubectl get pod -n -o yaml

5,經過標籤查詢 pod

kubectl get pod -l app= -n

6,查詢 pod 具體某一條信息

kubectl -n get pods|grep |awk '{print $3}'

7,刪除 pod(或經過標籤 -l app=)

kubectl delete pod -n

8,刪除 deployment

kubectl delete deployment -n

9,強制刪除 pod

kubectl delete pod -n --force --grace-period=0

10,進入 pod 容器

kubectl exec -it -n -- sh

11,給 node 打標籤

kubectl label node app=label

12,查看某一個 node 標籤

kubectl get node -l " "

13,查看所有 node 標籤

kubectl get node --show-labels=true

七,總結

關於 Node 節點的 NotReady 狀態當時也是排查了好久,對不少種狀況也是猜想,並不能具體肯定是什麼緣由。

網上關於這方面的內容也不是不少,只能是根據提示一步一步去排查問題的源頭,並加以驗證,最後也是在條件限制下解決了這個問題。

之後的工做也是作 AIOT 相關的,所謂 A 是指 Ai,IOT 指物聯網。也是和 K8S 強相關的內容,後續也還會繼續和你們分享關於 K8S 相關的知識。

若是您也是 K8S 的使用者,或者想接觸學習 K8S,歡迎關注我的公衆號!

最後,求關注


總結辛苦,原創不易!但願一些正能量的支持,求關注,點贊,轉發(一鍵三連)

相關文章
相關標籤/搜索