K8S 和 容器中的退出狀態碼 完全指南

什麼是容器退出碼

當容器終止時,容器引擎使用退出碼來報告容器終止的原因。如果您是 Kubernetes 用戶,容器故障是 pod 異常最常見的原因之一,瞭解容器退出碼可以幫助您在排查時找到 pod 故障的根本原因。

以下是容器使用的最常見的退出碼:

aW7h1s

下面我們將解釋如何在宿主機和 Kubernetes 中對失敗的容器進行故障排除,並提供有關上面列出的所有退出代碼的更多詳細信息。

容器生命週期

爲了更好地理解容器故障的原因,讓我們先討論容器的生命週期。以 Docker 爲例 —— 在任何給定時間,Docker 容器都會處於以下幾種狀態之一:

當一個容器達到 Exited 狀態時,Docker 會在日誌中報告一個退出碼,告訴你容器發生了什麼導致它退出。

瞭解容器退出碼

下面我們將更詳細地介紹每個退出碼。

退出碼 0:正常退出

退出代碼 0 由開發人員在任務完成後故意停止容器時觸發。從技術上講,退出代碼 0 意味着前臺進程未附加到特定容器。

如果容器以退出碼 0 終止怎麼辦?

  1. 檢查容器日誌,確定哪個庫導致容器退出;

  2. 查看現有庫的代碼,並確定它觸發退出碼 0 的原因,以及它是否正常運行。

退出碼 1:應用錯誤

退出代碼 1 表示容器由於以下原因之一停止:

  1. 應用程序錯誤:這可能是容器運行的代碼中的簡單編程錯誤,例如 “除以零”,也可能是與運行時環境相關的高級錯誤,例如 Java、Python 等;

  2. 無效引用:這意味着鏡像規範引用了容器鏡像中不存在的文件。

如果容器以退出碼 1 終止怎麼辦?

  1. 檢查容器日誌以查看是否找不到映像規範中列出的文件之一。如果這是問題所在,請更正鏡像以指向正確的路徑和文件名。

  2. 如果您找不到不正確的文件引用,請檢查容器日誌以查找應用程序錯誤,並調試導致錯誤的庫。

退出碼 125:容器未能運行

退出碼 125 表示該命令用於運行容器。例如 docker run 在 shell 中被調用但沒有成功執行。以下是可能發生這種情況的常見原因:

  1. 命令中使用了未定義的 flag,例如 docker run --abcd

  2. 鏡像中用戶的定義命令在本機權限不足;

  3. 容器引擎與宿主機操作系統或硬件不兼容。

如果容器以退出碼 125 終止怎麼辦?

  1. 檢查運行容器的命令語法是否正確;

  2. 檢查運行容器的用戶,或者鏡像中執行命令的上下文,是否有足夠的權限在宿主機上創建容器;

  3. 如果您的容器引擎提供了運行容器的 option,請嘗試它們。例如,在 Docker 中,嘗試 docker start 而不是 docker run

  4. 測試您是否能夠使用相同的用戶名或上下文在主機上運行其他容器。如果不能,重新安裝容器引擎,或者解決容器引擎和主機設置之間的底層兼容性問題。

退出碼 126:命令調用錯誤

退出碼 126 表示無法調用容器鏡像中使用的命令。這通常是用於運行容器的持續集成腳本中缺少依賴項或錯誤的原因。

如果容器以退出碼 126 終止怎麼辦?

  1. 檢查容器日誌,查看無法調用哪個命令;

  2. 嘗試在沒有命令的情況下運行容器以確保隔離問題;

  3. 對命令進行故障排除以確保您使用正確的語法,並且所有依賴項都可用;

  4. 更正容器規範並重試運行容器。

退出碼 127:找不到文件或目錄

退出碼 127 表示容器中指定的命令引用了不存在的文件或目錄。

如果容器以退出碼 127 終止怎麼辦?

與退出碼 126 相同,識別失敗的命令,並確保容器鏡像中引用的文件名或文件路徑真實有效。

退出碼 128:退出時使用的參數無效

退出碼 128 表示容器內的代碼觸發了退出命令,但沒有提供有效的退出碼。Linux exit 命令只允許 0-255 之間的整數,因此如果進程以退出碼 3.5 退出,則日誌將報告退出代碼 128。

如果容器以退出碼 128 終止怎麼辦?

  1. 檢查容器日誌以確定哪個庫導致容器退出。

  2. 確定有問題的庫在哪裏使用了 exit 命令,並更正它以提供有效的退出代碼。

退出碼 134:異常終止 (SIGABRT)

退出碼 134 表示容器自身異常終止,關閉進程並刷新打開的流。此操作是不可逆的,類似 SIGKILL(請參閱下面的退出碼 137)。進程可以通過執行以下操作之一來觸發 SIGABRT

如果容器以退出碼 134 終止怎麼辦?

  1. 檢查容器日誌,查看哪個庫觸發了 SIGABRT 信號;

  2. 檢查中止進程是否是預期內的(例如,因爲庫處於調試模式),如果不是,則對庫進行故障排除,並修改以避免中止容器。

退出碼 137:立即終止 (SIGKILL)

退出碼 137 表示容器已收到來自主機操作系統的 SIGKILL 信號。該信號指示進程立即終止,沒有寬限期。可能的原因是:

如果容器以退出碼 137 終止怎麼辦?

  1. 檢查主機上的日誌,查看在容器終止之前發生了什麼,以及在接收到 SIGKILL 之前是否之前收到過 SIGTERM 信號(優雅終止);

  2. 如果之前有 SIGTERM 信號,請檢查您的容器進程是否處理 SIGTERM 並能夠正常終止;

  3. 如果沒有 SIGTERM 並且容器報告了 OOMKilled 錯誤,則排查主機上的內存問題。

退出碼 139:分段錯誤 (SIGSEGV)

退出碼 139 表示容器收到了來自操作系統的 SIGSEGV 信號。這表示分段錯誤 —— 內存違規,由容器試圖訪問它無權訪問的內存位置引起。SIGSEGV 錯誤有三個常見原因:

如果容器以退出碼 139 終止怎麼辦?

  1. 檢查容器進程是否處理 SIGSEGV。在 Linux 和 Windows 上,您都可以處理容器對分段錯誤的響應。例如,容器可以收集和報告堆棧跟蹤;

  2. 如果您需要對 SIGSEGV 進行進一步的故障排除,您可能需要將操作系統設置爲即使在發生分段錯誤後也允許程序運行,以便進行調查和調試。然後,嘗試故意造成分段錯誤並調試導致問題的庫;

  3. 如果您無法復現問題,請檢查主機上的內存子系統並排除內存配置故障。

退出碼 143:優雅終止 (SIGTERM)

退出碼 143 表示容器收到來自操作系統的 SIGTERM 信號,該信號要求容器正常終止,並且容器成功正常終止(否則您將看到退出碼 137)。該退出碼可能的原因是:

如果容器以退出碼 143 終止怎麼辦?

檢查主機日誌,查看操作系統發送 SIGTERM 信號的上下文。如果您使用的是 Kubernetes,請檢查 kubelet 日誌,查看 pod 是否以及何時關閉。

一般來說,退出碼 143 不需要故障排除。這意味着容器在主機指示後正確關閉。

退出碼 255:退出狀態超出範圍

當您看到退出碼 255 時,意味着容器的 entrypoint 以該狀態停止。這意味着容器停止了,但不知道是什麼原因。

如果容器以退出碼 255 終止怎麼辦?

  1. 如果容器在虛擬機中運行,首先嚐試刪除虛擬機上配置的 overlay 網絡並重新創建它們。

  2. 如果這不能解決問題,請嘗試刪除並重新創建虛擬機,然後在其上重新運行容器。

  3. 如果上述操作失敗,則 bash 進入容器並檢查有關 entrypoint 進程及其失敗原因的日誌或其他線索。

哪些 Kubernetes 錯誤與容器退出代碼有關?

每當 pod 中容器發生故障,或者 Kubernetes 指示 pod 出於任何原因終止時,容器將關閉並記錄退出代碼。識別退出代碼可以幫助您瞭解 pod 異常的根本原因。

您可以使用以下命令查看 pod 錯誤:kubectl describe pod [name]

結果將如下所示:

Containers:
kubedns:
Container ID: ...
Image: ...
Image ID: ...
Ports: ...
Host Ports: ...
Args: ...
State: Running
   Started: Fri, 15 Oct 2021 12:06:01 +0800
Last State: Terminated
   Reason: Error
   Exit Code: 255
   Started: Fri, 15 Oct 2021 11:43:42 +0800
   Finished: Fri, 15 Oct 2021 12:05:17 +0800
Ready: True
Restart Count: 1

使用kubectl提供的退出代碼解決問題:

請參閱上面的相關部分,瞭解如何對每個退出代碼的容器進行故障排除。

作者:komodor

譯自:https://u.kubeinfo.cn/EybA7f

譯者:# 公衆號:進擊雲原生

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/EOyBESRscrwdA5oJHc7QCw