什么是容器退出碼
當(dāng)容器終止時,容器引擎使用退出碼來報告容器終止的原因。如果您是 Kubernetes 用戶,容器故障是 pod 異常最常見的原因之一,了解容器退出碼可以幫助您在排查時找到 pod 故障的根本原因。以下是容器使用的最常見的退出碼:
退出碼 | 名稱 | 含義 |
---|---|---|
0 | 正常退出 | 開發(fā)者用來表明容器是正常退出 |
1 | 應(yīng)用錯誤 | 容器因應(yīng)用程序錯誤或鏡像規(guī)范中的錯誤引用而停止 |
125 | 容器未能運(yùn)行 | docker run 命令沒有執(zhí)行成功 |
126 | 命令調(diào)用錯誤 | 無法調(diào)用鏡像中指定的命令 |
127 | 找不到文件或目錄 | 找不到鏡像中指定的文件或目錄 |
128 | 退出時使用的參數(shù)無效 | 退出是用無效的退出碼觸發(fā)的(有效代碼是 0-255 之間的整數(shù)) |
134 | 異常終止 (SIGABRT) | 容器使用 abort() 函數(shù)自行中止 |
137 | 立即終止 (SIGKILL) | 容器被操作系統(tǒng)通過 SIGKILL 信號終止 |
139 | 分段錯誤 (SIGSEGV) | 容器試圖訪問未分配給它的內(nèi)存并被終止 |
143 | 優(yōu)雅終止 (SIGTERM) | 容器收到即將終止的警告,然后終止 |
255 | 退出狀態(tài)超出范圍 | 容器退出,返回可接受范圍之外的退出代碼,表示錯誤原因未知 |
下面我們將解釋如何在宿主機(jī)和 Kubernetes 中對失敗的容器進(jìn)行故障排除,并提供有關(guān)上面列出的所有退出代碼的更多詳細(xì)信息。
容器生命周期
為了更好地理解容器故障的原因,讓我們先討論容器的生命周期。以 Docker 為例 —— 在任何給定時間,Docker 容器都會處于以下幾種狀態(tài)之一:
Created:Docker 容器已創(chuàng)建但尚未啟動(這是運(yùn)行?docker create?后但實際運(yùn)行容器之前的狀態(tài))
Up:Docker 容器當(dāng)前正在運(yùn)行。這意味著容器管理的操作系統(tǒng)進(jìn)程正在運(yùn)行。當(dāng)您使用命令?docker start?或?docker run?時會發(fā)生這種情況,使用?docker start?或?docker run?可能會發(fā)生這種情況。
Paused:容器進(jìn)程正在運(yùn)行,但 Docker 暫停了容器。通常,當(dāng)您運(yùn)行?docker pause?命令時會發(fā)生這種情況
Exited:Docker 容器已經(jīng)被終止,通常是因為容器的進(jìn)程被殺死了
當(dāng)一個容器達(dá)到 Exited 狀態(tài)時,Docker 會在日志中報告一個退出碼,告訴你容器發(fā)生了什么導(dǎo)致它退出。
了解容器退出碼
下面我們將更詳細(xì)地介紹每個退出碼。
退出碼 0:正常退出
退出代碼 0 由開發(fā)人員在任務(wù)完成后故意停止容器時觸發(fā)。從技術(shù)上講,退出代碼 0 意味著前臺進(jìn)程未附加到特定容器。
如果容器以退出碼 0 終止怎么辦?
檢查容器日志,確定哪個庫導(dǎo)致容器退出;
查看現(xiàn)有庫的代碼,并確定它觸發(fā)退出碼 0 的原因,以及它是否正常運(yùn)行。
退出碼 1:應(yīng)用錯誤
退出代碼 1 表示容器由于以下原因之一停止:
應(yīng)用程序錯誤:這可能是容器運(yùn)行的代碼中的簡單編程錯誤,例如“除以零”,也可能是與運(yùn)行時環(huán)境相關(guān)的高級錯誤,例如 Java、Python 等;
無效引用:這意味著鏡像規(guī)范引用了容器鏡像中不存在的文件。
如果容器以退出碼 1 終止怎么辦?
檢查容器日志以查看是否找不到映像規(guī)范中列出的文件之一。如果這是問題所在,請更正鏡像以指向正確的路徑和文件名。
如果您找不到不正確的文件引用,請檢查容器日志以查找應(yīng)用程序錯誤,并調(diào)試導(dǎo)致錯誤的庫。
退出碼 125:容器未能運(yùn)行
退出碼 125 表示該命令用于運(yùn)行容器。例如?docker run?在 shell 中被調(diào)用但沒有成功執(zhí)行。以下是可能發(fā)生這種情況的常見原因:
命令中使用了未定義的 flag,例如?docker run --abcd;
鏡像中用戶的定義命令在本機(jī)權(quán)限不足;
容器引擎與宿主機(jī)操作系統(tǒng)或硬件不兼容。
如果容器以退出碼 125 終止怎么辦?
檢查運(yùn)行容器的命令語法是否正確;
檢查運(yùn)行容器的用戶,或者鏡像中執(zhí)行命令的上下文,是否有足夠的權(quán)限在宿主機(jī)上創(chuàng)建容器;
如果您的容器引擎提供了運(yùn)行容器的 option,請嘗試它們。例如,在 Docker 中,嘗試?docker start?而不是?docker run;
測試您是否能夠使用相同的用戶名或上下文在主機(jī)上運(yùn)行其他容器。如果不能,重新安裝容器引擎,或者解決容器引擎和主機(jī)設(shè)置之間的底層兼容性問題。
退出碼 126:命令調(diào)用錯誤
退出碼 126 表示無法調(diào)用容器鏡像中使用的命令。這通常是用于運(yùn)行容器的持續(xù)集成腳本中缺少依賴項或錯誤的原因。
如果容器以退出碼 126 終止怎么辦?
檢查容器日志,查看無法調(diào)用哪個命令;
嘗試在沒有命令的情況下運(yùn)行容器以確保隔離問題;
對命令進(jìn)行故障排除以確保您使用正確的語法,并且所有依賴項都可用;
更正容器規(guī)范并重試運(yùn)行容器。
退出碼 127:找不到文件或目錄
退出碼 127 表示容器中指定的命令引用了不存在的文件或目錄。
如果容器以退出碼 127 終止怎么辦?
與退出碼 126 相同,識別失敗的命令,并確保容器鏡像中引用的文件名或文件路徑真實有效。
退出碼 128:退出時使用的參數(shù)無效
退出碼 128 表示容器內(nèi)的代碼觸發(fā)了退出命令,但沒有提供有效的退出碼。Linux exit?命令只允許 0-255 之間的整數(shù),因此如果進(jìn)程以退出碼 3.5 退出,則日志將報告退出代碼 128。
如果容器以退出碼 128 終止怎么辦?
檢查容器日志以確定哪個庫導(dǎo)致容器退出。
確定有問題的庫在哪里使用了?exit?命令,并更正它以提供有效的退出代碼。
退出碼 134:異常終止 (SIGABRT)
退出碼 134 表示容器自身異常終止,關(guān)閉進(jìn)程并刷新打開的流。此操作是不可逆的,類似?SIGKILL(請參閱下面的退出碼 137)。進(jìn)程可以通過執(zhí)行以下操作之一來觸發(fā)?SIGABRT:
調(diào)用?libc?庫中的?abort()?函數(shù);
調(diào)用?assert()?宏,用于調(diào)試。如果斷言為假,則該過程中止。
如果容器以退出碼 134 終止怎么辦?
檢查容器日志,查看哪個庫觸發(fā)了?SIGABRT?信號;
檢查中止進(jìn)程是否是預(yù)期內(nèi)的(例如,因為庫處于調(diào)試模式),如果不是,則對庫進(jìn)行故障排除,并修改以避免中止容器。
退出碼 137:立即終止 (SIGKILL)
退出碼 137 表示容器已收到來自主機(jī)操作系統(tǒng)的?SIGKILL?信號。該信號指示進(jìn)程立即終止,沒有寬限期。可能的原因是:
當(dāng)通過容器引擎殺死容器時觸發(fā),例如使用?docker kill?命令時;
由 Linux 用戶向進(jìn)程發(fā)送?kill -9?命令觸發(fā);
在嘗試終止容器并等待 30 秒的寬限期后由 Kubernetes 觸發(fā)(默認(rèn)情況下);
由主機(jī)自動觸發(fā),通常是由于內(nèi)存不足。在這種情況下,docker inspect?命令將指示?OOMKilled?錯誤。
如果容器以退出碼 137 終止怎么辦?
檢查主機(jī)上的日志,查看在容器終止之前發(fā)生了什么,以及在接收到?SIGKILL?之前是否之前收到過?SIGTERM?信號(優(yōu)雅終止);
如果之前有?SIGTERM?信號,請檢查您的容器進(jìn)程是否處理?SIGTERM?并能夠正常終止;
如果沒有?SIGTERM?并且容器報告了?OOMKilled?錯誤,則排查主機(jī)上的內(nèi)存問題。
退出碼 139:分段錯誤 (SIGSEGV)
退出碼 139 表示容器收到了來自操作系統(tǒng)的?SIGSEGV?信號。這表示分段錯誤 —— 內(nèi)存違規(guī),由容器試圖訪問它無權(quán)訪問的內(nèi)存位置引起。SIGSEGV?錯誤有三個常見原因:
編碼錯誤:容器進(jìn)程沒有正確初始化,或者它試圖通過指向先前釋放的內(nèi)存的指針來訪問內(nèi)存
二進(jìn)制文件和庫之間不兼容:容器進(jìn)程運(yùn)行的二進(jìn)制文件與共享庫不兼容,因此可能會嘗試訪問不適當(dāng)?shù)膬?nèi)存地址
硬件不兼容或配置錯誤:如果您在多個庫中看到多個分段錯誤,則主機(jī)上的內(nèi)存子系統(tǒng)可能存在問題或系統(tǒng)配置問題
如果容器以退出碼 139 終止怎么辦?
檢查容器進(jìn)程是否處理?SIGSEGV。在 Linux 和 Windows 上,您都可以處理容器對分段錯誤的響應(yīng)。例如,容器可以收集和報告堆棧跟蹤;
如果您需要對?SIGSEGV?進(jìn)行進(jìn)一步的故障排除,您可能需要將操作系統(tǒng)設(shè)置為即使在發(fā)生分段錯誤后也允許程序運(yùn)行,以便進(jìn)行調(diào)查和調(diào)試。然后,嘗試故意造成分段錯誤并調(diào)試導(dǎo)致問題的庫;
如果您無法復(fù)現(xiàn)問題,請檢查主機(jī)上的內(nèi)存子系統(tǒng)并排除內(nèi)存配置故障。
退出碼 143:優(yōu)雅終止 (SIGTERM)
退出碼 143 表示容器收到來自操作系統(tǒng)的?SIGTERM?信號,該信號要求容器正常終止,并且容器成功正常終止(否則您將看到退出碼 137)。該退出碼可能的原因是:
容器引擎停止容器時觸發(fā),例如使用?docker stop?或?docker-compose down?命令時;
由 Kubernetes 將 Pod 設(shè)置為 Terminating 狀態(tài)觸發(fā),并給容器 30 秒的時間以正常關(guān)閉。
如果容器以退出碼 143 終止怎么辦?
檢查主機(jī)日志,查看操作系統(tǒng)發(fā)送?SIGTERM?信號的上下文。如果您使用的是 Kubernetes,請檢查 kubelet 日志,查看 pod 是否以及何時關(guān)閉。
一般來說,退出碼 143 不需要故障排除。這意味著容器在主機(jī)指示后正確關(guān)閉。
退出碼 255:退出狀態(tài)超出范圍
當(dāng)您看到退出碼 255 時,意味著容器的 entrypoint 以該狀態(tài)停止。這意味著容器停止了,但不知道是什么原因。
如果容器以退出碼 255 終止怎么辦?
如果容器在虛擬機(jī)中運(yùn)行,首先嘗試刪除虛擬機(jī)上配置的 overlay 網(wǎng)絡(luò)并重新創(chuàng)建它們。
如果這不能解決問題,請嘗試刪除并重新創(chuàng)建虛擬機(jī),然后在其上重新運(yùn)行容器。
如果上述操作失敗,則 bash 進(jìn)入容器并檢查有關(guān) entrypoint 進(jìn)程及其失敗原因的日志或其他線索。
評論