Pod 生命週期

此頁面描述了 Pod 的生命週期。Pod 遵循一個明確定義的生命週期,從 Pending 階段開始,如果其至少一個主容器啟動正常,則進入 Running 階段,然後根據 Pod 中是否有容器終止失敗,進入 SucceededFailed 階段。

與單個應用容器一樣,Pod 被認為是相對短暫(而非持久)的實體。Pod 被建立,分配一個唯一的 ID(UID),並排程到節點上執行,它們會一直留在節點上,直到終止(根據重啟策略)或刪除。如果一個 節點發生故障,在該節點上執行(或排程到該節點上執行)的 Pod 將被標記為刪除。控制面會在超時後標記 Pod 進行移除。

Pod 生命週期

當 Pod 執行時,kubelet 能夠重啟容器以處理某些型別的故障。在一個 Pod 中,Kubernetes 跟蹤不同的容器狀態,並確定採取什麼措施使 Pod 再次健康。

在 Kubernetes API 中,Pod 既有規範也有實際狀態。Pod 物件的 Status 包含一組 Pod 條件。如果這對你的應用有用,你還可以將自定義就緒資訊注入到 Pod 的條件資料中。

Pod 在其生命週期中只排程一次;將 Pod 分配到特定節點稱為 繫結,選擇使用哪個節點的過程稱為 排程。一旦 Pod 被排程並繫結到節點,Kubernetes 就會嘗試在該節點上執行該 Pod。Pod 將在該節點上執行,直到它停止或 Pod 終止;如果 Kubernetes 無法在選定的節點上啟動 Pod(例如,在 Pod 啟動之前節點崩潰),則該特定的 Pod 永遠不會啟動。

你可以使用 Pod 排程就緒來延遲 Pod 的排程,直到所有其 排程門都被移除。例如,你可能希望定義一組 Pod,但只在所有 Pod 都被建立後才觸發排程。

Pod 和故障恢復

如果 Pod 中的一個容器失敗,Kubernetes 可能會嘗試重啟該特定容器。閱讀Pod 如何處理容器問題以瞭解更多資訊。

然而,Pod 可能會以叢集無法恢復的方式失敗,在這種情況下,Kubernetes 不會嘗試進一步修復 Pod;相反,Kubernetes 會刪除 Pod,並依賴其他元件提供自動修復。

如果一個 Pod 被排程到一個 節點,然後該節點發生故障,Pod 將被視為不健康,Kubernetes 最終會刪除該 Pod。Pod 在因資源不足或節點維護而導致的驅逐後不會存活。

Kubernetes 使用一個更高級別的抽象,稱為控制器,它負責管理相對可丟棄的 Pod 例項。

一個給定的 Pod(由 UID 定義)永遠不會被“重新排程”到不同的節點;相反,該 Pod 可以被一個新的、幾乎相同的 Pod 替換。如果你建立一個替換 Pod,它甚至可以與舊 Pod 具有相同的名稱(如 .metadata.name),但替換 Pod 將具有與舊 Pod 不同的 .metadata.uid

Kubernetes 不保證現有 Pod 的替換品將排程到與被替換的舊 Pod 相同的節點上。

關聯的生命週期

當某個事物(例如)與 Pod 具有相同的生命週期時,這意味著該事物存在的時間與該特定 Pod(具有精確的 UID)存在的時間相同。如果該 Pod 因任何原因被刪除,即使建立了一個相同的替換品,相關事物(本例中的卷)也會被銷燬並重新建立。

A multi-container Pod that contains a file puller sidecar and a web server. The Pod uses an ephemeral emptyDir volume for shared storage between the containers.

圖 1。

一個包含檔案拉取器邊車容器和 Web 伺服器的多容器 Pod。Pod 使用臨時 emptyDir在容器之間共享儲存。

Pod 階段

Pod 的 status 欄位是一個 PodStatus 物件,它有一個 phase 欄位。

Pod 的階段是對 Pod 在其生命週期中所處位置的簡單、高層次總結。該階段並非旨在全面彙總容器或 Pod 狀態的觀察結果,也並非旨在成為全面的狀態機。

Pod 階段值的數量和含義受到嚴格保護。除了此處記錄的內容,不應假定具有給定 phase 值的 Pod 的任何其他資訊。

以下是 phase 可能的值

描述
PendingPod 已被 Kubernetes 叢集接受,但一個或多個容器尚未設定並準備執行。這包括 Pod 等待排程的時間以及透過網路下載容器映象所花費的時間。
RunningPod 已被繫結到節點,並且所有容器都已建立。至少一個容器仍在執行,或者正在啟動或重啟過程中。
SucceededPod 中的所有容器都已成功終止,並且不會被重啟。
FailedPod 中的所有容器都已終止,並且至少有一個容器終止失敗。也就是說,容器要麼以非零狀態退出,要麼被系統終止,並且未設定為自動重啟。
Unknown由於某種原因無法獲取 Pod 的狀態。此階段通常是由於與 Pod 應該執行的節點通訊時出錯而發生的。

自 Kubernetes 1.27 起,kubelet 會將已刪除的 Pod(靜態 Pod 和未帶 finalizer 的強制刪除的 Pod 除外)轉換到終止階段(根據 Pod 容器的退出狀態,可以是 FailedSucceeded),然後才從 API 伺服器中刪除。

如果節點死亡或與叢集的其餘部分斷開連線,Kubernetes 會應用策略,將丟失節點上所有 Pod 的 phase 設定為 Failed。

容器狀態

除了 Pod 的整體階段之外,Kubernetes 還跟蹤 Pod 中每個容器的狀態。你可以使用容器生命週期鉤子來觸發事件,使其在容器生命週期中的特定點執行。

一旦 排程器 將 Pod 分配給一個節點,kubelet 就會使用容器執行時為該 Pod 建立容器。容器有三種可能的狀態:WaitingRunningTerminated

要檢查 Pod 容器的狀態,可以使用 kubectl describe pod <pod-name>。輸出將顯示該 Pod 中每個容器的狀態。

每種狀態都有特定含義

Waiting

如果容器既不在 Running 狀態也不在 Terminated 狀態,則它處於 Waiting 狀態。處於 Waiting 狀態的容器仍在執行完成啟動所需的操作:例如,從容器映象倉庫拉取容器映象,或者應用Secret 資料。當你使用 kubectl 查詢一個帶有 Waiting 狀態容器的 Pod 時,你還會看到一個 Reason 欄位,總結容器處於該狀態的原因。

Running

Running 狀態表示容器正在執行而沒有問題。如果配置了 postStart 鉤子,它已經執行並完成。當你使用 kubectl 查詢一個帶有 Running 狀態容器的 Pod 時,你還會看到容器進入 Running 狀態的時間資訊。

Terminated

處於 Terminated 狀態的容器已經開始執行,然後要麼執行完成,要麼因某種原因失敗。當你使用 kubectl 查詢一個帶有 Terminated 狀態容器的 Pod 時,你會看到該容器執行期間的原因、退出程式碼以及開始和結束時間。

如果容器配置了 preStop 鉤子,則該鉤子在容器進入 Terminated 狀態之前執行。

Pod 如何處理容器問題

Kubernetes 使用 Pod spec 中定義的 restartPolicy 來管理 Pod 內的容器故障。此策略決定了 Kubernetes 如何響應因錯誤或其他原因退出的容器,它遵循以下序列:

  1. 初始崩潰:Kubernetes 根據 Pod 的 restartPolicy 嘗試立即重啟。
  2. 重複崩潰:在初始崩潰後,Kubernetes 會對後續重啟應用指數回退延遲,如restartPolicy中所述。這可以防止快速、重複的重啟嘗試導致系統過載。
  3. CrashLoopBackOff 狀態:這表示回退延遲機制當前正在對處於崩潰迴圈、反覆失敗和重啟的給定容器生效。
  4. 回退重置:如果容器成功運行了一定時間(例如 10 分鐘),Kubernetes 會重置回退延遲,將任何新的崩潰視為第一次崩潰。

在實踐中,當 Pod 中的容器未能正確啟動,然後在一個迴圈中反覆嘗試並失敗時,CrashLoopBackOff 是在描述或列出 Pod 時,從 kubectl 命令輸出中可能看到的一種條件或事件。

換句話說,當容器進入崩潰迴圈時,Kubernetes 會應用 容器重啟策略中提到的指數回退延遲。此機制可防止故障容器因連續的失敗啟動嘗試而使系統不堪重負。

CrashLoopBackOff 可能由以下問題引起:

  • 導致容器退出的應用程式錯誤。
  • 配置錯誤,例如不正確的環境變數或缺少配置檔案。
  • 資源限制,容器可能沒有足夠的記憶體或 CPU 來正確啟動。
  • 如果應用程式未在預期時間內開始提供服務,則健康檢查失敗。
  • 容器活性探針或啟動探針返回 Failure 結果,如探針部分所述。

要調查 CrashLoopBackOff 問題的根本原因,使用者可以:

  1. 檢查日誌:使用 kubectl logs <pod-name> 檢查容器的日誌。這通常是診斷導致崩潰問題的最直接方法。
  2. 檢查事件:使用 kubectl describe pod <pod-name> 檢視 Pod 的事件,這可以提供有關配置或資源問題的提示。
  3. 審查配置:確保 Pod 配置(包括環境變數和掛載卷)正確,並且所有必需的外部資源都可用。
  4. 檢查資源限制:確保為容器分配了足夠的 CPU 和記憶體。有時,增加 Pod 定義中的資源可以解決問題。
  5. 除錯應用程式:應用程式程式碼中可能存在錯誤或配置錯誤。在本地或開發環境中執行此容器映象有助於診斷應用程式特有的問題。

容器重啟

當 Pod 中的容器停止或發生故障時,Kubernetes 可以重啟它。重啟並非總是合適的;例如,初始化容器僅在 Pod 啟動期間執行一次。

你可以將重啟配置為適用於所有 Pod 的策略,或者使用容器級配置(例如:當你定義邊車容器時)。

容器重啟和彈性

Kubernetes 專案建議遵循雲原生原則,包括考慮意外或任意重啟的彈性設計。你可以透過使 Pod 失敗並依賴自動替換來實現這一點,或者你可以設計容器級別的彈性。這兩種方法都有助於確保你的整體工作負載在部分故障的情況下仍然可用。

Pod 級別的容器重啟策略

Pod 的 spec 具有 restartPolicy 欄位,可能的值為 Always、OnFailure 和 Never。預設值為 Always。

Pod 的 restartPolicy 適用於 Pod 中的應用容器和常規初始化容器邊車容器會忽略 Pod 級別的 restartPolicy 欄位:在 Kubernetes 中,邊車容器定義為 initContainers 中的一個條目,其容器級別的 restartPolicy 設定為 Always。對於退出並帶有錯誤的初始化容器,如果 Pod 級別的 restartPolicyOnFailureAlways,kubelet 會重啟該初始化容器。

  • Always:在任何終止後自動重啟容器。
  • OnFailure:僅當容器因錯誤(非零退出狀態)退出時才重啟容器。
  • Never:不自動重啟已終止的容器。

當 kubelet 根據配置的重啟策略處理容器重啟時,這僅適用於在同一 Pod 內部並在同一節點上執行的替換容器的重啟。在 Pod 中的容器退出後,kubelet 會以指數回退延遲(10 秒、20 秒、40 秒等)重新啟動它們,最長延遲為 300 秒(5 分鐘)。一旦容器連續執行 10 分鐘沒有任何問題,kubelet 會重置該容器的重啟回退計時器。邊車容器和 Pod 生命週期解釋了在初始化容器上指定 restartpolicy 欄位時的行為。

單個容器重啟策略和規則

功能狀態: Kubernetes v1.34 [alpha] (預設停用)

如果你的叢集啟用了功能門控 ContainerRestartRules,你可以在 單個容器 上指定 restartPolicyrestartPolicyRules 來覆蓋 Pod 重啟策略。容器重啟策略和規則適用於 Pod 中的應用容器和常規初始化容器

Kubernetes 原生的邊車容器的容器級 restartPolicy 設定為 Always,並且不支援 restartPolicyRules

容器重啟將遵循與上述 Pod 重啟策略相同的指數回退。支援的容器重啟策略:

  • Always:在任何終止後自動重啟容器。
  • OnFailure:僅當容器因錯誤(非零退出狀態)退出時才重啟容器。
  • Never:不自動重啟已終止的容器。

此外,_單個容器_ 可以指定 restartPolicyRules。如果指定了 restartPolicyRules 欄位,則容器 restartPolicy **也必須**指定。restartPolicyRules 定義了在容器退出時應用的一系列規則。每個規則將包含一個條件和一個動作。支援的條件是 exitCodes,它將容器的退出程式碼與給定值列表進行比較。支援的動作是 Restart,這意味著容器將被重啟。規則將按順序評估。在第一次匹配時,將應用該動作。如果沒有規則的條件匹配,Kubernetes 將回退到容器配置的 restartPolicy

例如,一個具有 OnFailure 重啟策略的 Pod,其中包含一個 try-once 容器。這允許 Pod 只重啟某些容器。

apiVersion: v1
kind: Pod
metadata:
  name: on-failure-pod
spec:
  restartPolicy: OnFailure
  containers:
  - name: try-once-container    # This container will run only once because the restartPolicy is Never.
    image: docker.io/library/busybox:1.28
    command: ['sh', '-c', 'echo "Only running once" && sleep 10 && exit 1']
    restartPolicy: Never     
  - name: on-failure-container  # This container will be restarted on failure.
    image: docker.io/library/busybox:1.28
    command: ['sh', '-c', 'echo "Keep restarting" && sleep 1800 && exit 1']

一個具有 Always 重啟策略的 Pod,其中包含一個只執行一次的初始化容器。如果初始化容器失敗,Pod 將失敗。這允許 Pod 在初始化失敗時失敗,但在初始化成功後繼續執行。

apiVersion: v1
kind: Pod
metadata:
  name: fail-pod-if-init-fails
spec:
  restartPolicy: Always
  initContainers:
  - name: init-once      # This init container will only try once. If it fails, the pod will fail.
    image: docker.io/library/busybox:1.28
    command: ['sh', '-c', 'echo "Failing initialization" && sleep 10 && exit 1']
    restartPolicy: Never
  containers:
  - name: main-container # This container will always be restarted once initialization succeeds.
    image: docker.io/library/busybox:1.28
    command: ['sh', '-c', 'sleep 1800 && exit 0']

一個具有 Never 重啟策略的 Pod,其中包含一個忽略特定退出程式碼並重新啟動的容器。這對於區分可重啟錯誤和不可重啟錯誤很有用。

apiVersion: v1
kind: Pod
metadata:
  name: restart-on-exit-codes
spec:
  restartPolicy: Never
  containers:
  - name: restart-on-exit-codes
    image: docker.io/library/busybox:1.28
    command: ['sh', '-c', 'sleep 60 && exit 0']
    restartPolicy: Never     # Container restart policy must be specified if rules are specified
    restartPolicyRules:      # Only restart the container if it exits with code 42
    - action: Restart
      exitCodes:
        operator: In
        values: [42]

重啟規則可用於更高階的生命週期管理場景。請注意,重啟規則會受到與常規重啟策略相同的缺陷的影響。Kubelet 重啟、容器執行時垃圾回收、與控制平面間歇性連線問題可能導致狀態丟失,並且即使你期望容器不重啟,容器也可能重新執行。

減少容器重啟延遲

特性狀態: `Kubernetes v1.33 [alpha]`(預設啟用:false)

啟用 alpha 功能門控 ReduceDefaultCrashLoopBackOffDecay 後,叢集中的容器啟動重試將從 1 秒(而不是 10 秒)開始,每次重啟以 2 倍指數增長,直到最大延遲為 60 秒(而不是 300 秒,即 5 分鐘)。

如果將此功能與 alpha 功能 KubeletCrashLoopBackOffMax(下文所述)一起使用,則單個節點可能具有不同的最大延遲。

可配置的容器重啟延遲

功能狀態: Kubernetes v1.32 [alpha] (預設停用)

啟用 alpha 功能門控 KubeletCrashLoopBackOffMax 後,你可以重新配置容器啟動重試之間的最大延遲,從預設的 300 秒(5 分鐘)更改。此配置透過 kubelet 配置在每個節點上設定。在你的 kubelet 配置中,在 crashLoopBackOff 下,將 maxContainerRestartPeriod 欄位設定為 "1s""300s" 之間的值。如上文 容器重啟策略 中所述,該節點上的延遲仍將從 10 秒開始,每次重啟以 2 倍指數增長,但現在將限制在你的配置最大值。如果配置的 maxContainerRestartPeriod 小於預設初始值 10 秒,則初始延遲將改為配置的最大值。

請參閱以下 kubelet 配置示例

# container restart delays will start at 10s, increasing
# 2x each time they are restarted, to a maximum of 100s
kind: KubeletConfiguration
crashLoopBackOff:
    maxContainerRestartPeriod: "100s"
# delays between container restarts will always be 2s
kind: KubeletConfiguration
crashLoopBackOff:
    maxContainerRestartPeriod: "2s"

如果將此功能與 alpha 功能 ReduceDefaultCrashLoopBackOffDecay(如上所述)一起使用,則叢集的初始回退和最大回退的預設值將不再是 10 秒和 300 秒,而是 1 秒和 60 秒。每個節點配置優先於 ReduceDefaultCrashLoopBackOffDecay 設定的預設值,即使這會導致節點具有比叢集中其他節點更長的最大回退。

Pod 條件

Pod 具有 PodStatus,其中包含一個 PodConditions 陣列,表示 Pod 已透過或未透過的條件。Kubelet 管理以下 PodConditions:

  • PodScheduled:Pod 已被排程到一個節點。
  • PodReadyToStartContainers:(beta 功能;預設啟用) Pod 沙箱已成功建立,網路已配置。
  • ContainersReady:Pod 中所有容器都已就緒。
  • Initialized:所有初始化容器已成功完成。
  • Ready:Pod 能夠處理請求,並且應該新增到所有匹配的服務負載均衡池中。
  • DisruptionTarget:Pod 即將因中斷(例如搶佔、驅逐或垃圾回收)而終止。
  • PodResizePending:已請求 Pod 大小調整但無法應用。請參閱Pod 大小調整狀態
  • PodResizeInProgress:Pod 正在調整大小。請參閱Pod 大小調整狀態
欄位名稱描述
type此 Pod 條件的名稱。
status表示該條件是否適用,可能的值為 “True”、“False” 或 “Unknown”。
lastProbeTime上次探測 Pod 條件的時間戳。
lastTransitionTimePod 上次從一種狀態轉換到另一種狀態的時間戳。
reason機器可讀的 UpperCamelCase 文字,表示條件上次轉換的原因。
message人類可讀的訊息,指示上次狀態轉換的詳細資訊。

Pod 就緒

功能狀態:`Kubernetes v1.14 [stable]`

你的應用程式可以將額外的反饋或訊號注入到 PodStatus 中:Pod 就緒。為此,請在 Pod 的 spec 中設定 readinessGates,以指定 kubelet 評估 Pod 就緒狀況的其他條件列表。

就緒門控由 Pod 的 status.condition 欄位的當前狀態決定。如果 Kubernetes 在 Pod 的 status.conditions 欄位中找不到這樣的條件,則該條件的狀態預設為 “False”。

這是一個例子:

kind: Pod
...
spec:
  readinessGates:
    - conditionType: "www.example.com/feature-1"
status:
  conditions:
    - type: Ready                              # a built in PodCondition
      status: "False"
      lastProbeTime: null
      lastTransitionTime: 2018-01-01T00:00:00Z
    - type: "www.example.com/feature-1"        # an extra PodCondition
      status: "False"
      lastProbeTime: null
      lastTransitionTime: 2018-01-01T00:00:00Z
  containerStatuses:
    - containerID: docker://abcd...
      ready: true
...

你新增的 Pod 條件名稱必須符合 Kubernetes 標籤鍵格式

Pod 就緒狀態

kubectl patch 命令不支援修補物件狀態。要為 Pod 設定這些 status.conditions,應用程式和操作員應該使用 PATCH 動作。你可以使用 Kubernetes 客戶端庫編寫程式碼,為 Pod 就緒設定自定義 Pod 條件。

對於使用自定義條件的 Pod,僅當以下兩個語句都適用時,該 Pod 才被評估為就緒:

  • Pod 中的所有容器都已就緒。
  • readinessGates 中指定的所有條件都為 True

當 Pod 的容器就緒,但至少有一個自定義條件缺失或為 False 時,kubelet 會將 Pod 的條件設定為 ContainersReady

Pod 網路就緒

功能狀態: Kubernetes v1.29 [beta]

Pod 被排程到節點後,需要被 kubelet 接納並掛載任何所需的儲存卷。一旦這些階段完成,kubelet 將與容器執行時(使用 容器執行時介面 (CRI))協作,為 Pod 設定執行時沙箱並配置網路。如果 PodReadyToStartContainersCondition 功能門控 已啟用(Kubernetes 1.34 預設啟用),則 PodReadyToStartContainers 條件將被新增到 Pod 的 status.conditions 欄位中。

當 Kubelet 檢測到 Pod 沒有配置網路的執行時沙箱時,它會將 PodReadyToStartContainers 條件設定為 False。這發生在以下情況:

  • 在 Pod 生命週期的早期,當 kubelet 尚未開始使用容器執行時為 Pod 設定沙箱時。
  • 在 Pod 生命週期的後期,當 Pod 沙箱因以下任一原因被銷燬時:
    • 節點重啟,而 Pod 未被驅逐
    • 對於使用虛擬機器進行隔離的容器執行時,Pod 沙箱虛擬機器重啟,這需要建立新的沙箱和新的容器網路配置。

在執行時外掛成功完成 Pod 的沙箱建立和網路配置後,kubelet 將 PodReadyToStartContainers 條件設定為 True。在 PodReadyToStartContainers 條件設定為 True 後,kubelet 可以開始拉取容器映象並建立容器。

對於帶有初始化容器的 Pod,kubelet 在初始化容器成功完成後(發生在執行時外掛成功建立沙箱和網路配置之後)將 Initialized 條件設定為 True。對於沒有初始化容器的 Pod,kubelet 在沙箱建立和網路配置開始之前將 Initialized 條件設定為 True

容器探針

探針kubelet 定期對容器執行的診斷。為了執行診斷,kubelet 要麼在容器內執行程式碼,要麼發出網路請求。

檢查機制

有四種不同的方法可以使用探針檢查容器。每個探針必須精確定義以下四種機制中的一種:

exec
在容器內執行指定命令。如果命令以狀態碼 0 退出,則診斷被認為是成功的。
grpc
使用 gRPC 執行遠端過程呼叫。目標應實現 gRPC 健康檢查。如果響應的 statusSERVING,則診斷被認為是成功的。
httpGet
對 Pod 的 IP 地址上的指定埠和路徑執行 HTTP GET 請求。如果響應狀態碼大於或等於 200 且小於 400,則診斷被認為是成功的。
tcpSocket
對 Pod 的 IP 地址上的指定埠執行 TCP 檢查。如果埠開啟,則診斷被認為是成功的。如果遠端系統(容器)在開啟連線後立即關閉連線,則這算作健康。

探測結果

每個探針有三種結果之一:

成功
容器透過診斷。
失敗
容器診斷失敗。
Unknown
診斷失敗(不應採取任何措施,kubelet 將進行進一步檢查)。

探針型別

kubelet 可以選擇對執行中的容器執行並響應三種類型的探針:

livenessProbe
指示容器是否正在執行。如果活性探針失敗,kubelet 會殺死容器,並且容器將受到其重啟策略的約束。如果容器未提供活性探針,預設狀態為 Success
readinessProbe
指示容器是否已準備好響應請求。如果就緒探針失敗,EndpointSlice 控制器將從所有匹配 Pod 的服務的 EndpointSlices 中移除 Pod 的 IP 地址。初始延遲之前的就緒預設狀態為 Failure。如果容器未提供就緒探針,預設狀態為 Success
startupProbe
指示容器內的應用程式是否已啟動。如果提供了啟動探針,則在它成功之前,所有其他探針都將被停用。如果啟動探針失敗,kubelet 會殺死容器,並且容器將受到其重啟策略的約束。如果容器未提供啟動探針,預設狀態為 Success

有關如何設定活性、就緒或啟動探針的更多資訊,請參閱配置活性、就緒和啟動探針

何時使用活性探針?

如果你的容器中的程序在遇到問題或變得不健康時能夠自行崩潰,那麼你並不一定需要活性探針;kubelet 會根據 Pod 的 restartPolicy 自動執行正確的操作。

如果你希望容器在探針失敗時被殺死並重啟,那麼請指定活性探針,並將 restartPolicy 指定為 Always 或 OnFailure。

何時使用就緒探針?

如果你希望只有當探測成功時才開始向 Pod 傳送流量,請指定就緒探針。在這種情況下,就緒探針可能與活性探針相同,但在規範中存在就緒探針意味著 Pod 將在不接收任何流量的情況下啟動,並且只有在探測開始成功後才開始接收流量。

如果你希望容器能夠自行停機進行維護,你可以指定一個就緒探針,該探針檢查一個特定於就緒的端點,該端點與活性探針不同。

如果你的應用程式對後端服務有嚴格的依賴,你可以實現活性探針和就緒探針。當應用程式本身健康時,活性探針會透過,但就緒探針還會額外檢查每個必需的後端服務是否可用。這有助於你避免將流量導向只能響應錯誤訊息的 Pod。

如果你的容器需要在啟動期間載入大量資料、配置檔案或進行遷移,你可以使用啟動探針。但是,如果你想區分應用程式已失敗和應用程式仍在處理其啟動資料的情況,你可能更喜歡就緒探針。

何時使用啟動探針?

啟動探針對於那些需要很長時間才能啟動的容器的 Pod 很有用。你可以配置一個獨立的配置來探測容器啟動,而不是設定一個很長的活性間隔,允許的時間比活性間隔允許的時間更長。

如果你的容器通常在 \( initialDelaySeconds + failureThreshold \times periodSeconds \) 之外啟動,你應該指定一個啟動探針,該探針檢查與活性探針相同的端點。periodSeconds 的預設值為 10 秒。然後,你應該將其 failureThreshold 設定得足夠高,以允許容器啟動,而無需更改活性探針的預設值。這有助於防止死鎖。

Pod 的終止

由於 Pod 代表在叢集節點上執行的程序,因此在不再需要這些程序時允許它們優雅地終止(而不是被 KILL 訊號突然停止而沒有機會進行清理)非常重要。

設計目標是讓你能夠請求刪除並知道程序何時終止,同時也能確保刪除最終完成。當你請求刪除 Pod 時,叢集會記錄並跟蹤允許 Pod 被強制終止之前的預期寬限期。有了這種強制關閉跟蹤,kubelet 會嘗試優雅關閉。

通常,在 Pod 優雅終止時,kubelet 會向容器執行時發出請求,嘗試透過首先向每個容器中的主程序傳送 TERM(也稱為 SIGTERM)訊號(帶有寬限期超時)來停止 Pod 中的容器。停止容器的請求由容器執行時非同步處理。無法保證這些請求的處理順序。許多容器執行時會遵守容器映象中定義的 STOPSIGNAL 值,如果不同,則傳送容器映象配置的 STOPSIGNAL 而不是 TERM。一旦寬限期過期,KILL 訊號將傳送給任何剩餘的程序,然後 Pod 將從 API 伺服器中刪除。如果在等待程序終止時 kubelet 或容器執行時的管理服務重新啟動,則叢集會從頭開始重試,包括完整的原始寬限期。

停止訊號

用於殺死容器的停止訊號可以在容器映象中使用 STOPSIGNAL 指令定義。如果映象中沒有定義停止訊號,則將使用容器執行時的預設訊號(containerd 和 CRI-O 均為 SIGTERM)來殺死容器。

定義自定義停止訊號

特性狀態: `Kubernetes v1.33 [alpha]`(預設啟用:false)

如果啟用了 ContainerStopSignals 功能門控,你可以從容器生命週期中為容器配置自定義停止訊號。我們要求 Pod 的 spec.os.name 欄位作為在容器生命週期中定義停止訊號的要求。有效訊號列表取決於 Pod 排程到的作業系統。對於排程到 Windows 節點的 Pod,我們僅支援 SIGTERM 和 SIGKILL 作為有效訊號。

以下是一個定義自定義停止訊號的 Pod 規範示例:

spec:
  os:
    name: linux
  containers:
    - name: my-container
      image: container-image:latest
      lifecycle:
        stopSignal: SIGUSR1

如果在生命週期中定義了停止訊號,它將覆蓋容器映象中定義的訊號。如果容器規範中沒有定義停止訊號,容器將回退到預設行為。

Pod 終止流程

Pod 終止流程,以一個示例說明:

  1. 你使用 kubectl 工具手動刪除一個特定的 Pod,使用預設寬限期(30 秒)。

  2. API 伺服器中的 Pod 會更新為 Pod 被視為“已死”的時間以及寬限期。如果你使用 kubectl describe 檢查你正在刪除的 Pod,該 Pod 將顯示為“Terminating”。在 Pod 執行的節點上:一旦 kubelet 發現 Pod 被標記為終止(已設定優雅關機持續時間),kubelet 就會開始本地 Pod 關機過程。

    1. 如果 Pod 的某個容器定義了 preStop 鉤子,並且 Pod 規範中的 terminationGracePeriodSeconds 未設定為 0,kubelet 將在容器內部執行該鉤子。預設的 terminationGracePeriodSeconds 設定為 30 秒。

      如果 preStop 鉤子在寬限期過期後仍在執行,kubelet 會請求一個小的、一次性的 2 秒寬限期延長。

    2. kubelet 觸發容器執行時向每個容器內的程序 1 傳送 TERM 訊號。

      如果 Pod 定義了任何邊車容器,則存在特殊的順序。否則,Pod 中的容器會在不同的時間以任意順序接收 TERM 訊號。如果關閉順序很重要,請考慮使用 preStop 鉤子進行同步(或切換為使用邊車容器)。

  3. 在 kubelet 開始 Pod 優雅關閉的同時,控制平面評估是否從 EndpointSlice 物件中移除該正在關閉的 Pod,這些物件代表具有已配置選擇器服務ReplicaSets 和其他工作負載資源不再將正在關閉的 Pod 視為有效、在服務中的副本。

    緩慢關閉的 Pod 不應繼續處理常規流量,而應開始終止並完成處理開啟的連線。有些應用程式需要超越完成開啟的連線,需要更優雅的終止,例如會話排空和完成。

    表示終止 Pod 的任何端點不會立即從 EndpointSlices 中移除,並且 EndpointSlice API 會公開指示終止狀態的狀態。終止中的端點始終將其 ready 狀態設定為 false(為了向後相容 1.26 之前的版本),因此負載均衡器將不會將其用於常規流量。

    如果需要對終止中的 Pod 進行流量排空,則實際就緒狀態可以作為條件 serving 進行檢查。有關如何實現連線排空的更多詳細資訊,請參閱教程Pod 和端點終止流程

  4. kubelet 確保 Pod 已關閉並終止:

    1. 當寬限期過期時,如果 Pod 中仍有任何容器正在執行,kubelet 將觸發強制關閉。容器執行時將 SIGKILL 傳送給 Pod 中任何容器中仍在執行的程序。如果容器執行時使用了隱藏的 pause 容器,kubelet 也會清理該容器。
    2. kubelet 將 Pod 轉換為終止階段(根據其容器的最終狀態,可以是 FailedSucceeded)。
    3. kubelet 透過將寬限期設定為 0(立即刪除)來強制從 API 伺服器中刪除 Pod 物件。
    4. API 伺服器刪除 Pod 的 API 物件,此後任何客戶端都無法再看到該物件。

強制 Pod 終止

預設情況下,所有刪除操作均在 30 秒內優雅完成。kubectl delete 命令支援 --grace-period=<seconds> 選項,允許你覆蓋預設值並指定自己的值。

將寬限期設定為 0 會強制並立即從 API 伺服器中刪除 Pod。如果 Pod 仍在節點上執行,則強制刪除會觸發 kubelet 開始立即清理。

使用 kubectl,你必須同時指定 --force 標誌和 --grace-period=0 才能執行強制刪除。

當執行強制刪除時,API 伺服器不會等待 kubelet 確認 Pod 已在其執行的節點上終止。它會立即在 API 中刪除 Pod,以便可以使用相同的名稱建立新的 Pod。在節點上,設定為立即終止的 Pod 仍將在被強制殺死之前獲得一個短暫的寬限期。

如果你需要強制刪除 StatefulSet 中的 Pod,請參閱從 StatefulSet 中刪除 Pod 的任務文件。

Pod 關機和 Sidecar 容器

如果你的 Pod 包含一個或多個Sidecar 容器(restart 策略為 Always 的 init 容器),kubelet 將延遲向這些 Sidecar 容器傳送 TERM 訊號,直到最後一個主容器完全終止。Sidecar 容器將按照它們在 Pod 規範中定義的相反順序終止。這確保了 Sidecar 容器在不再需要之前繼續為 Pod 中的其他容器提供服務。

這意味著主容器的緩慢終止也會延遲 Sidecar 容器的終止。如果寬限期在終止過程完成之前到期,Pod 可能會進入強制終止。在這種情況下,Pod 中所有剩餘的容器將以短暫的寬限期同時終止。

同樣,如果 Pod 有一個超出終止寬限期的 preStop 鉤子,可能會發生緊急終止。通常,如果你在沒有 Sidecar 容器的情況下使用 preStop 鉤子來控制終止順序,你現在可以刪除它們,讓 kubelet 自動管理 Sidecar 終止。

Pod 的垃圾回收

對於失敗的 Pod,API 物件會保留在叢集的 API 中,直到人工或控制器程序明確將其移除。

Pod 垃圾回收器(PodGC)是控制平面中的一個控制器,當 Pod 數量超過配置的閾值(由 kube-controller-manager 中的 terminated-pod-gc-threshold 決定)時,它會清理已終止的 Pod(SucceededFailed 狀態)。這可以避免隨著 Pod 的建立和終止而導致的資源洩漏。

此外,PodGC 會清理滿足以下任一條件的 Pod:

  1. 孤兒 Pod - 繫結到不再存在的節點,
  2. 未排程且正在終止的 Pod,
  3. 正在終止的 Pod,繫結到一個不就緒且被 node.kubernetes.io/out-of-service 汙點標記的節點。

除了清理 Pod 之外,如果 Pod 處於非終止階段,PodGC 還會將其標記為失敗。此外,PodGC 在清理孤兒 Pod 時會新增一個 Pod 中斷條件。有關更多詳細資訊,請參閱Pod 中斷條件

下一步

上次修改時間為 2025 年 7 月 1 日太平洋標準時間晚上 10:39:新增容器重啟規則文件 (5a0ebb3aa7)