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 處於循環中。嘗試運行,但失敗了,所以進入失敗狀態。 如果稍等片刻以幫助您調試,則會嘗試再次運行。如果問題沒有解決,就陷入了循環,將再次失敗
在本文中,您將看到:
- 什麼是 CrashLoopBackOff?
- 如何檢測 CrashLoopBackOff 問題
- CrashLoopBackOff 的常見原因
- 用於調試 CrashLoopBackOff 的 Kubernetes 工具
- 如何使用 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 處於Running
或Failed
狀態的短暫時間內找到它。
CrashloopBackoff 的時間線。 每次失敗時,BackoffTime 和 Restart Count 都會增加
CrashLoopBackOff 的常見原因
重要的是要注意 CrashLoopBackOff
不是導致 pod 崩潰的實際錯誤。請記住,它只是顯示STATUS
列中發生的循環。您需要找到影響容器的潛在錯誤。
與實際應用程序相關的一些錯誤是:
- 錯誤配置:就像配置文件中的錯字。
- 資源不可用:例如未掛載的 PersistentVolume。
- 錯誤的命令行參數:要麼丟失,要麼不正確。
- bug 和異常: 這可以是任何異常,對你的應用來說都是非常具體的。
最後,來自網絡和權限的錯誤是:
- 您試圖綁定被佔用的端口。
- 內存限制太低,容器被
Out Of Memory
殺死。 - liveness 探針返回錯誤 未報告 Pod 已 Ready。
- 只讀文件系統,或缺乏權限。
以上這些只是可能原因的列表,可能還有很多其他原因。
現在讓我們看看如何深入挖掘並找到真正的原因。
調試、排障和修復 CrashLoopBackOff
上文,您瞭解到 pod 最終處於 CrashLoopBackOff
狀態的原因有很多。現在,你怎麼知道是哪一個在影響你?讓我們回顧一下您可以用來調試它的一些工具,以及使用它的順序。
這可能是我們最好的做法:
- 檢查
pod 描述
。 - 檢查
pod 日誌
。 - 檢查events。
- 檢查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
…
從描述輸出中,您可以提取以下信息:
- 當前 pod
State
是Waiting
. - 等待狀態的原因是“ 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多平臺發佈