7 張圖解 CrashLoopBackOff,如何發現問題並解決它?

7 張圖解 CrashLoopBackOff,如何發現問題並解決它?

CrashLoopBackOff 是一種 Kubernetes 狀態,表示 Pod 中發生的重啓循環:Pod 中的容器已啓動,但崩潰然後又重新啓動,一遍又一遍。

Kubernetes 將在重新啓動之間等待越來越長的回退時間,以便您有機會修復錯誤。因此,CrashLoopBackOff 本身並不是一個錯誤,而是表明發生了一個錯誤,導致 Pod 無法正常啓動。

Pod 在 Running、Failed 和 Waiting 之間循環

請注意,它重新啓動的原因是因爲它restartPolicy設置爲Always(默認情況下)或OnFailure,然後 kubelet 讀取此配置並重新啓動 Pod 中的容器並導致循環。這種行爲實際上很有用,因爲這爲丟失的資源完成加載提供了一些時間,也爲我們檢測問題和調試提供了一些時間,稍後會詳細介紹。

這解釋了CrashLoop部分,但是BackOff時間呢?基本上,這是重啓之間的指數延遲(10 秒、20 秒、40 秒……),上限爲 5 分鐘。當 Pod 狀態顯示 CrashLoopBackOff 時,表示它當前正在等待指示的時間,然後再重新啓動 Pod。除非它被修復,否則它可能會再次失敗。

Pod 處於循環中。嘗試運行,但失敗了,所以進入失敗狀態。 如果稍等片刻以幫助您調試,則會嘗試再次運行。如果問題沒有解決,就陷入了循環,將再次失敗

在本文中,您將看到:

  1. 什麼是 CrashLoopBackOff?
  2. 如何檢測 CrashLoopBackOff 問題
  3. CrashLoopBackOff 的常見原因
  4. 用於調試 CrashLoopBackOff 的 Kubernetes 工具
  5. 如何使用 Prometheus 檢測 CrashLoopBackOff

如何檢測集羣中的 CrashLoopBackOff?

最有可能的是,您通過kubectl get pods列出以下 pod 發現了處於此狀態的一個或多個 pod :

$ kubectl get pods
NAME                     READY     STATUS             RESTARTS   AGE
flask-7996469c47-d7zl2   1/1       Running            1          77d
flask-7996469c47-tdr2n   1/1       Running            0          77d
nginx-5796d5bc7c-2jdr5   0/1       CrashLoopBackOff   2          1m
nginx-5796d5bc7c-xsl6p   0/1       CrashLoopBackOff   2          1m

從輸出中,您可以看到最後兩個 pod:

  • 不處於READY( 0/1) 狀態。
  • 他們的狀態顯示CrashLoopBackOff
  • RESTARTS顯示重新啓動次數。

這三個信號指向我們解釋的內容:Pod 出現故障,它們正在重新啓動。在重新啓動之間,有一個寬限期,表示爲CrashLoopBackOff.

您可能在 Pod 處於RunningFailed狀態的短暫時間內找到它。

CrashloopBackoff 的時間線。 每次失敗時,BackoffTime 和 Restart Count 都會增加

CrashLoopBackOff 的常見原因

重要的是要注意 CrashLoopBackOff 不是導致 pod 崩潰的實際錯誤。請記住,它只是顯示STATUS列中發生的循環。您需要找到影響容器的潛在錯誤。

與實際應用程序相關的一些錯誤是:

  • 錯誤配置:就像配置文件中的錯字。
  • 資源不可用:例如未掛載的 PersistentVolume。
  • 錯誤的命令行參數:要麼丟失,要麼不正確。
  • bug 和異常: 這可以是任何異常,對你的應用來說都是非常具體的。

最後,來自網絡和權限的錯誤是:

  • 您試圖綁定被佔用的端口。
  • 內存限制太低,容器被 Out Of Memory 殺死。
  • liveness 探針返回錯誤 未報告 Pod 已 Ready。
  • 只讀文件系統,或缺乏權限。

以上這些只是可能原因的列表,可能還有很多其他原因。

現在讓我們看看如何深入挖掘並找到真正的原因。

調試、排障和修復 CrashLoopBackOff

上文,您瞭解到 pod 最終處於 CrashLoopBackOff 狀態的原因有很多。現在,你怎麼知道是哪一個在影響你?讓我們回顧一下您可以用來調試它的一些工具,以及使用它的順序。

這可能是我們最好的做法:

  1. 檢查pod 描述
  2. 檢查pod 日誌
  3. 檢查events
  4. 檢查deployment

1.查看 pod 描述:kubectl describe pod

kubectl describe pod命令提供特定 Pod 及其容器的詳細信息:

$ kubectl describe pod the-pod-name
Name:         the-pod-name
Namespace:    default
Priority:     0
…
State:          Waiting
Reason:       CrashLoopBackOff
Last State:     Terminated
Reason:       Error
…
Warning  BackOff                1m (x5 over 1m)   kubelet, ip-10-0-9-132.us-east-2.compute.internal  Back-off restarting failed container
…

從描述輸出中,您可以提取以下信息:

  • 當前 podStateWaiting.
  • 等待狀態的原因是“ CrashLoopBackOff ”。
  • 上一個 狀態是“Terminated”。
  • 上次終止的原因是“錯誤”。

這與我們一直在解釋的循環行爲一致。

通過使用kubectl describe pod,您可以檢查以下配置錯誤:

  • Pod 定義
  • 容器
  • 爲容器拉取的 鏡像
  • 爲容器分配的 資源
  • 錯誤或缺少的 參數
…
Warning  BackOff                1m (x5 over 1m)   kubelet, ip-10-0-9-132.us-east-2.compute.internal  Back-off restarting failed container
…

在最後幾行中,您會看到與此 pod 關聯的最後一個事件的列表,其中之一是"Back-off restarting failed container",這是重啓循環的事件。即使發生了多次重新啓動,也應該只有一行。

2.查看日誌:kubectl logs

您可以查看 pod 的所有容器的日誌:

kubectl logs mypod --all-containers

甚至是該 pod 中的容器:

kubectl logs mypod -c mycontainer

如果發送錯誤的 pod 中有錯誤的值,日誌可能會顯示有用的信息。

3.查看事件:kubectl get events

它們可以列出:

kubectl get events

或者,您可以使用以下命令列出單個 Pod 的所有事件:

kubectl get events --field-selector involvedObject.name=mypod

請注意,此信息也出現在describe pod輸出的底部。

4.檢查部署:kubectl describe deployment

您可以通過以下方式獲取此信息:

kubectl describe deployment mydeployment

如果部署定義了所需的 Pod 狀態,它可能包含導致 CrashLoopBackOff 的錯誤配置。

結合起來看

在下面的示例中,您可以看到如何挖掘日誌,在其中發現命令參數中的錯誤。

調試 Crashloopbackoff。 它顯示了三個終端以及幾個調試命令之間的關係。

在 Prometheus 中檢測 CrashLoopBackOff

如果您使用 Prometheus 進行監控,這裏有一些提示可以幫助您在發生 CrashLoopBackOff 時發出警報。

使用以下表達式,可以快速掃描集羣中處於CrashLoopBackOff狀態的容器(您需要提前部署 Kube State Metrics):

kube_pod_container_status_waiting_reason{reason="CrashLoopBackOff"} == 1

檢測 pod 狀態爲 CrashLoopBackOff 的 PromQL 示例

或者,你可以用以下方法跟蹤 pod 發生的重啓次數:

rate(kube_pod_container_status_restarts_total[5m]) > 0

基於重啓率檢測 CrashLoopBackOff 的 PromQL 示例

警告:並非集羣中發生的所有重啓都與 CrashLoopBackOff 狀態有關。

重新啓動和 crashloopbackoff 之間的相關性。 並非所有重啓都是由 crashloopbackoff 引起的

在每個 CrashLoopBackOff 週期之後應該有一個重新啓動 (1),但可能有與 CrashLoopBackOff (2) 無關的重新啓動。

可以創建如下所示的 Prometheus 警報規則,當任何 pod 處於此狀態時接收通知:

- alert: RestartsAlert
  expr: rate(kube_pod_container_status_restarts_total[5m]) > 0
  for: 10m
  labels:
    severity: warning
  annotations:
    summary: Pod is being restarted
  description: Pod {{ $labels.pod }} in {{ $labels.namespace }} has a container {{ $labels.container }} which is being restarted

結論

在這篇文章中,我們看到了 CrashLoopBackOff 本身並不是一個錯誤,而只是一個在 pod 中發生的重試循環的通知。

我們看到了它所經過的狀態的描述,以及如何使用kubectl命令跟蹤它。

此外,我們還看到了可能導致此狀態的常見錯誤配置,以及您可以使用哪些工具來調試它。

最後,我們回顧了 Prometheus 如何幫助跟蹤和提醒 Pod 中的 CrashLoopBackOff 事件。

雖然不是一個直觀的消息,但 CrashLoopBackOff 是一個有用的概念,它是有意義的,沒有什麼可害怕的。

譯自:https://sysdig.com/blog/debug-kubernetes-crashloopbackoff/
譯者:#公衆號:進擊雲原生

本文由mdnice多平臺發佈

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章