容器生命週期鉤子
本頁面描述了 kubelet 管理的容器如何使用容器生命週期鉤子框架來執行由其管理生命週期事件觸發的程式碼。
概述
與許多具有元件生命週期鉤子的程式語言框架(例如 Angular)類似,Kubernetes 為容器提供了生命週期鉤子。這些鉤子使容器能夠感知其管理生命週期中的事件,並在執行相應的生命週期鉤子時執行處理程式中實現的程式碼。
容器鉤子
暴露給容器的鉤子有兩種
PostStart
此鉤子在容器建立後立即執行。但是,不能保證該鉤子會在容器 ENTRYPOINT 之前執行。沒有引數傳遞給處理程式。
PreStop
此鉤子在容器因 API 請求或管理事件(例如活性/啟動探針失敗、搶佔、資源爭用等)而終止之前立即呼叫。如果容器已經處於終止或完成狀態,則對 PreStop
鉤子的呼叫將失敗,並且該鉤子必須在傳送用於停止容器的 TERM 訊號之前完成。Pod 的終止寬限期倒計時在 PreStop
鉤子執行之前開始,因此無論處理程式的結果如何,容器最終都會在 Pod 的終止寬限期內終止。沒有引數傳遞給處理程式。
有關終止行為的更詳細描述,請參閱Pod 終止。
StopSignal
StopSignal 生命週期可用於定義一個停止訊號,該訊號將在容器停止時傳送給容器。如果設定此項,它將覆蓋容器映象中定義的任何 STOPSIGNAL
指令。
有關使用自定義停止訊號的終止行為的更詳細描述,請參閱停止訊號。
鉤子處理程式實現
容器可以透過實現並註冊該鉤子的處理程式來訪問鉤子。可以為容器實現三種類型的鉤子處理程式
- Exec - 在容器的 cgroups 和名稱空間內執行特定命令,例如
pre-stop.sh
。命令消耗的資源計入容器。 - HTTP - 對容器上的特定端點執行 HTTP 請求。
- Sleep - 暫停容器指定時長。
鉤子處理程式執行
當呼叫容器生命週期管理鉤子時,Kubernetes 管理系統會根據鉤子操作執行處理程式,httpGet
、tcpSocket
(已棄用) 和 sleep
由 kubelet 程序執行,而 exec
在容器中執行。
PostStart
鉤子處理程式呼叫在容器建立時啟動,這意味著容器 ENTRYPOINT 和 PostStart
鉤子同時觸發。但是,如果 PostStart
鉤子執行時間過長或掛起,它可能會阻止容器轉換為 running
狀態。
PreStop
鉤子與停止容器的訊號並非非同步執行;該鉤子必須在 TERM 訊號傳送之前完成其執行。如果 PreStop
鉤子在執行期間掛起,則 Pod 的階段將為 Terminating
並保持在那裡,直到 Pod 在其 terminationGracePeriodSeconds
到期後被終止。此寬限期適用於 PreStop
鉤子執行和容器正常停止的總時間。例如,如果 terminationGracePeriodSeconds
為 60 秒,並且鉤子需要 55 秒才能完成,並且容器在收到訊號後需要 10 秒才能正常停止,那麼容器將在正常停止之前被終止,因為 terminationGracePeriodSeconds
小於這兩個事件發生所需的總時間(55 + 10)。
如果 PostStart
或 PreStop
鉤子失敗,它將終止容器。
使用者應儘可能使他們的鉤子處理程式輕量級。然而,在某些情況下,長時間執行的命令是有意義的,例如在停止容器之前儲存狀態。
鉤子傳遞保證
鉤子傳遞旨在實現**至少一次**,這意味著對於任何給定事件,例如 PostStart
或 PreStop
,鉤子可能會被呼叫多次。正確處理此問題取決於鉤子實現。
通常,只會進行一次傳遞。例如,如果 HTTP 鉤子接收器出現故障且無法處理流量,則不會嘗試重新發送。但在某些罕見情況下,可能會發生雙重傳遞。例如,如果 kubelet 在傳送鉤子過程中重新啟動,則鉤子可能會在 kubelet 重新啟動後重新發送。
除錯鉤子處理程式
鉤子處理程式的日誌不會在 Pod 事件中公開。如果處理程式因某種原因失敗,它會廣播一個事件。對於 PostStart
,這是 FailedPostStartHook
事件,對於 PreStop
,這是 FailedPreStopHook
事件。要自己生成一個失敗的 FailedPostStartHook
事件,請修改 lifecycle-events.yaml 檔案,將 postStart 命令更改為“badcommand”並應用它。以下是執行 kubectl describe pod lifecycle-demo
後看到的事件的一些示例輸出
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 7s default-scheduler Successfully assigned default/lifecycle-demo to ip-XXX-XXX-XX-XX.us-east-2...
Normal Pulled 6s kubelet Successfully pulled image "nginx" in 229.604315ms
Normal Pulling 4s (x2 over 6s) kubelet Pulling image "nginx"
Normal Created 4s (x2 over 5s) kubelet Created container lifecycle-demo-container
Normal Started 4s (x2 over 5s) kubelet Started container lifecycle-demo-container
Warning FailedPostStartHook 4s (x2 over 5s) kubelet Exec lifecycle hook ([badcommand]) for Container "lifecycle-demo-container" in Pod "lifecycle-demo_default(30229739-9651-4e5a-9a32-a8f1688862db)" failed - error: command 'badcommand' exited with 126: , message: "OCI runtime exec failed: exec failed: container_linux.go:380: starting container process caused: exec: \"badcommand\": executable file not found in $PATH: unknown\r\n"
Normal Killing 4s (x2 over 5s) kubelet FailedPostStartHook
Normal Pulled 4s kubelet Successfully pulled image "nginx" in 215.66395ms
Warning BackOff 2s (x2 over 3s) kubelet Back-off restarting failed container
下一步
- 瞭解更多關於容器環境的資訊。
- 獲取將處理程式附加到容器生命週期事件的實踐經驗。