Kubernetes 和 容器的退出碼完整指南

容器和 Kubernetes 中的退出碼完整指南

什麼是容器退出碼

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

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

退出碼 名稱 含義
0 正常退出 開發者用來表明容器是正常退出
1 應用錯誤 容器因應用程序錯誤或鏡像規範中的錯誤引用而停止
125 容器未能運行 docker run 命令沒有執行成功
126 命令調用錯誤 無法調用鏡像中指定的命令
127 找不到文件或目錄 找不到鏡像中指定的文件或目錄
128 退出時使用的參數無效 退出是用無效的退出碼觸發的(有效代碼是 0-255 之間的整數)
134 異常終止 (SIGABRT) 容器使用 abort() 函數自行中止
137 立即終止 (SIGKILL) 容器被操作系統通過 SIGKILL 信號終止
139 分段錯誤 (SIGSEGV) 容器試圖訪問未分配給它的內存並被終止
143 優雅終止 (SIGTERM) 容器收到即將終止的警告,然後終止
255 退出狀態超出範圍 容器退出,返回可接受範圍之外的退出代碼,表示錯誤原因未知

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

容器生命週期

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

  • Created:Docker 容器已創建但尚未啓動(這是運行 docker create 後但實際運行容器之前的狀態)
  • Up:Docker 容器當前正在運行。這意味着容器管理的操作系統進程正在運行。當您使用命令 docker startdocker run 時會發生這種情況,使用 docker startdocker run 可能會發生這種情況。
  • Paused:容器進程正在運行,但 Docker 暫停了容器。通常,當您運行 docker pause 命令時會發生這種情況
  • Exited: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

  • 調用 libc 庫中的 abort() 函數;
  • 調用 assert() 宏,用於調試。如果斷言爲假,則該過程中止。

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

  1. 檢查容器日誌,查看哪個庫觸發了 SIGABRT 信號;
  2. 檢查中止進程是否是預期內的(例如,因爲庫處於調試模式),如果不是,則對庫進行故障排除,並修改以避免中止容器。

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

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

  • 當通過容器引擎殺死容器時觸發,例如使用 docker kill 命令時;
  • 由 Linux 用戶向進程發送 kill -9 命令觸發;
  • 在嘗試終止容器並等待 30 秒的寬限期後由 Kubernetes 觸發(默認情況下);
  • 由主機自動觸發,通常是由於內存不足。在這種情況下,docker inspect 命令將指示 OOMKilled 錯誤。

如果容器以退出碼 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)。該退出碼可能的原因是:

  • 容器引擎停止容器時觸發,例如使用 docker stopdocker-compose down 命令時;
  • 由 Kubernetes 將 Pod 設置爲 Terminating 狀態觸發,並給容器 30 秒的時間以正常關閉。

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

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

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

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

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

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

  1. 如果容器在虛擬機中運行,首先嚐試刪除虛擬機上配置的 overlay 網絡並重新創建它們。
  2. 如果這不能解決問題,請嘗試刪除並重新創建虛擬機,然後在其上重新運行容器。
  3. 如果上述操作失敗,則 bash 進入容器並檢查有關 entrypoint 進程及其失敗原因的日誌或其他線索。

出處

譯自:Exit Codes in Containers and Kubernetes – The Complete Guide

本文由mdnice多平臺發佈

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