天天看點

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

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

什麼是容器退出碼

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

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

退出碼 名稱 含義
正常退出 開發者用來表明容器是正常退出
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 start​

    ​​ 或​

    ​docker run​

    ​​ 時會發生這種情況,使用​

    ​docker start​

    ​​ 或​

    ​docker 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 stop​

    ​​ 或​

    ​docker-compose down​

    ​ 指令時;
  • 由 Kubernetes 将 Pod 設定為 Terminating 狀态觸發,并給容器 30 秒的時間以正常關閉。

如果容器以退出碼 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​

​提供的退出代碼解決問題:

  • 如果退出代碼為 0:容器正常退出,無需排查
  • 如果退出代碼在 1-128 之間:容器因内部錯誤而終止,例如鏡像規範中缺少或無效的指令
  • 如果退出代碼在 129-255 之間:容器因操作信号而停止,例如 SIGKILL 或 SIGINT
  • 如果退出代碼是​

    ​exit(-1)​

    ​​或 0-255 範圍之外的另一個值,​

    ​kubectl​

    ​将其轉換為 0-255 範圍内的值。

出處