容器生命週期鉤點
本頁說明了 kubelet 管理的容器如何使用容器生命週期鉤點框架,以執行由其管理生命週期中的事件觸發的程式碼。
總覽
類似於許多具有元件生命週期鉤點的程式語言框架(例如 Angular),Kubernetes 為容器提供了生命週期鉤點。 這些鉤點使容器能夠感知其管理生命週期中的事件,並在執行對應的生命週期鉤點時,執行在處理常式中實作的程式碼。
容器鉤點
有兩個鉤點暴露給容器
PostStart
此鉤點在容器建立後立即執行。 但是,不保證鉤點會在容器 ENTRYPOINT 之前執行。 沒有參數傳遞給處理常式。
PreStop
此鉤點在容器因 API 請求或管理事件(例如存活度/啟動探測失敗、搶佔、資源爭用等)而終止之前立即呼叫。 如果容器已處於終止或完成狀態,則對 PreStop
鉤點的呼叫將會失敗,並且鉤點必須在可以傳送 TERM 訊號以停止容器之前完成。 Pod 的終止寬限期倒數在執行 PreStop
鉤點之前開始,因此無論處理常式的結果如何,容器最終都會在 Pod 的終止寬限期內終止。 沒有參數傳遞給處理常式。
有關終止行為的更詳細說明,請參閱 Pod 終止。
鉤點處理常式實作
容器可以透過實作和註冊該鉤點的處理常式來存取鉤點。 有三種類型的鉤點處理常式可以為容器實作
- Exec - 在容器的 cgroup 和命名空間內執行特定命令,例如
pre-stop.sh
。 命令消耗的資源會計入容器。 - HTTP - 對容器上的特定端點執行 HTTP 請求。
- Sleep - 將容器暫停指定的持續時間。 這是 beta 級別的功能,預設由
PodLifecycleSleepAction
功能閘門 啟用。
注意
如果您想為 Sleep 生命周期鉤點設定零秒的睡眠持續時間(實際上是無操作),請啟用PodLifecycleSleepActionAllowZero
功能閘門。鉤點處理常式執行
當呼叫容器生命週期管理鉤點時,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 恢復運作後,鉤點可能會重新傳送。
偵錯 Hook 處理程序
Hook 處理程序的日誌不會顯示在 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
下一步
- 進一步瞭解容器環境。
- 取得將處理程序附加到容器生命週期事件的實務經驗。