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