1、在k8s 的微服務的項目當中,有的時候會遇到pod 會進行重啓, 那pod 為啥進行重啓,根因是什麼呢?
Pod 重啓的根本原因是其內部的容器停止了運行,而 Pod 的 restartPolicy 被設置為 Always 或 OnFailure,因此 Kubernetes 會嘗試重新啓動容器以維持預期的狀態。
下面我們來詳細拆解導致 Pod 重啓的幾大核心原因
1. 容器進程退出(應用本身故障)
這是最常見的原因。容器內的主進程(PID 1)因為某種原因退出,返回了非零的退出碼。
應用崩潰: 代碼中存在 Bug,導致應用拋出未捕獲的異常、段錯誤等而崩潰。
正常退出但配置不當: 應用執行完畢並正常退出(退出碼為 0),但 Pod 的 restartPolicy 是 Always,Kubernetes 會立即重啓它。這通常見於一次性任務(Job)錯誤地配置成了 Deployment。
資源清理: 應用完成了它的工作,自行退出。
排查方式
查看pod 日誌
kubectl logs <pod-name> [-c <container-name>] # 查看當前容器日誌
kubectl logs <pod-name> --previous # 查看上次崩潰的容器日誌,非常重要!
2. 存活探針失敗
Kubernetes 提供了存活探針來檢測應用是否健康。如果探針連續失敗次數超過 failureThreshold,Kubernetes 會殺掉容器並重啓它。
HTTP GET 探針失敗: 健康檢查的 HTTP 端點返回了非 200-399 的狀態碼,或者超時、無法連接。
TCP Socket 探針失敗: 指定的端口無法建立 TCP 連接。
Exec 探針失敗: 在容器內執行的命令返回了非零的退出碼。
排查的方法
檢查探針配置: kubectl describe pod <pod-name>,查看 Liveness 部分的配置(初始延遲、超時時間、檢查間隔等)是否合理。
檢查應用健康端點: 手動訪問或執行探針定義的檢查,確認應用本身是否真的不健康。
查看容器日誌: 應用可能因為高負載、死鎖等原因無法響應探針,日誌中可能會有線索。
檢查資源: 如果 CPU/內存不足,應用可能無法及時響應探針。
3. 資源限制與 OOMKilled
這是另一個非常常見的原因。
內存不足: 容器使用的內存超過了其配置的 limits,Linux 內核會觸發 OOM Killer 來終止容器進程。這會導致容器退出,並隨之重啓。
退出碼: 137 (128 + 9 SIGKILL) 通常代表被 OOMKilled。
CPU 節流: 雖然 CPU 耗盡不會直接殺死容器,但會導致應用運行極其緩慢,可能進而引發存活探針超時失敗,間接導致重啓。
排查方法
查看 Pod 狀態: kubectl describe pod <pod-name>。在 Events 部分或容器狀態中,很可能會看到 OOMKilled 的字樣。
檢查資源指標: 使用 kubectl top pod <pod-name> 或監控系統(如 Prometheus)查看 Pod 的歷史資源使用情況。
調整資源限制: 合理調整 resources.requests 和 resources.limits。
4、節點壓力與驅逐
當 Kubernetes 節點資源不足時,kubelet 會為了保護節點而驅逐 Pod。這會導致 Pod 被刪除,如果它由 Deployment、StatefulSet 等控制器管理,控制器會在其他節點上重建一個新的 Pod(看起來像是“重啓”)。
觸發驅逐的原因包括
nodefs 可用空間不足(磁盤空間)
nodefs inodes 不足
imagefs 可用空間不足(容器鏡像存儲空間)
內存不足(System OOM)
排查方法
檢查 Pod 所在節點: kubectl get pod <pod-name> -o wide
查看節點狀態和事件: kubectl describe node <node-name>。在 Events 部分會看到 DiskPressure, MemoryPressure 以及相關的驅逐事件。
檢查被驅逐的 Pod: kubectl get pod -o wide | grep Evicted
- 配置錯誤或變更
ConfigMap/Secret 更新: 如果 Pod 使用了 volume 方式掛載 ConfigMap 或 Secret,並且配置了 defaultMode,當這些資源更新時,可能會導致 Pod 被原地重啓以加載新配置(取決於配置方式)。
鏡像拉取策略: imagePullPolicy: Always 且每次使用的鏡像標籤相同(如 latest),當節點上存在舊鏡像時,kubelet 可能會嘗試拉取新鏡像,如果失敗可能導致重啓問題。
- 底層基礎設施問題
節點故障: 節點本身宕機、斷網或卡死。
Docker 守護進程故障: 或 Containerd 運行時故障。
內核恐慌。
排查問題的工作流總結
當發現 Pod 不斷重啓時,建議按照以下步驟進行排查:
查看 Pod 狀態:
kubectl get pod <pod-name> # 觀察 RESTARTS 計數和 STATUS
kubectl describe pod <pod-name> # 這是最關鍵的命令!重點關注 `Events` 部分和容器狀態。
查看日誌:
kubectl logs <pod-name> --previous # 上次崩潰的日誌
kubectl logs <pod-name> # 當前容器的日誌
檢查資源使用:
kubectl top pod <pod-name> # 如果已安裝 metrics-server
檢查探針:
回顧 kubectl describe pod 輸出中的探針配置,思考其合理性。
檢查節點狀態:
kubectl describe node <node-name>
通過以上步驟,你基本上可以定位到 90% 以上的 Pod 重啓原因。
記住,kubectl describe 和 kubectl logs --previous 是你最好的方法