Kubernetes v1.34: Job 的 Pod 替換策略進入 GA 階段

在 Kubernetes v1.34 中,**Pod 替換策略(Pod replacement policy)** 特性已達到正式釋出(GA)階段。這篇博文將介紹 Pod 替換策略特性以及如何在你的 Job 中使用它。

關於 Pod 替換策略

預設情況下,Job 控制器會在 Pod 失敗或開始終止(當它們具有刪除時間戳時)時立即重新建立 Pod。

因此,在某些 Pod 正在終止時,一個 Job 的正在執行的 Pod 總數可能會暫時超過指定的並行度。對於 Indexed Job,這甚至可能意味著多個 Pod 同時為同一個索引執行。

這種行為對許多工作負載來說沒有問題,但在某些情況下可能會導致問題。

例如,像 TensorFlow 和 JAX 這樣流行的機器學習框架,期望每個工作程式索引(worker index)只有一個 Pod。如果兩個 Pod 同時執行,你可能會遇到類似下面的錯誤:

/job:worker/task:4: Duplicate task registration with task_name=/job:worker/replica:0/task:4

此外,在舊 Pod 完全終止之前啟動替換 Pod 可能會導致:

  • 由於節點仍被佔用,kube-scheduler 會出現排程延遲。
  • 為了容納替換的 Pod,叢集會進行不必要的擴容。
  • Kueue 這樣的工作負載編排器會暫時繞過配額檢查。

有了 Pod 替換策略,Kubernetes 讓你能夠控制控制平面何時替換正在終止的 Pod,從而幫助你避免這些問題。

Pod 替換策略的工作原理

這項增強意味著 Kubernetes 中的 Job 有一個可選欄位 .spec.podReplacementPolicy
你可以選擇以下兩種策略之一:

  • TerminatingOrFailed(預設):一旦 Pod 開始終止就替換它們。
  • Failed:僅在 Pod 完全終止並轉換到 Failed 階段後才替換它們。

將策略設定為 Failed 可以確保只有在前一個 Pod 完全終止後才會建立新的 Pod。

對於具有 Pod 失效策略(Pod Failure Policy)的 Job,預設的 podReplacementPolicyFailed,並且不允許其他值。要了解更多關於 Job 的 Pod 失效策略的資訊,請參閱Pod 失效策略

你可以透過檢查 Job 的 .status.terminating 欄位來檢視當前有多少 Pod 正在終止:

kubectl get job myjob -o=jsonpath='{.status.terminating}'

示例

下面是一個 Job 示例,它並行執行一個任務兩次(spec.completions: 2),並行度為 2(spec.parallelism: 2),並且僅在 Pod 完全終止後才替換它們(spec.podReplacementPolicy: Failed):

apiVersion: batch/v1
kind: Job
metadata:
  name: example-job
spec:
  completions: 2
  parallelism: 2
  podReplacementPolicy: Failed
  template:
    spec:
      restartPolicy: Never
      containers:
      - name: worker
        image: your-image

如果 Pod 收到 SIGTERM 訊號(刪除、驅逐、搶佔...),它將開始終止。當容器優雅地處理終止時,清理工作可能需要一些時間。

當 Job 啟動時,我們會看到兩個 Pod 正在執行:

kubectl get pods

NAME                READY   STATUS    RESTARTS   AGE
example-job-qr8kf   1/1     Running   0          2s
example-job-stvb4   1/1     Running   0          2s

讓我們刪除其中一個 Pod(example-job-qr8kf)。

使用 TerminatingOrFailed 策略時,一旦一個 Pod(example-job-qr8kf)開始終止,Job 控制器會立即建立一個新的 Pod(example-job-b59zk)來替換它。

kubectl get pods

NAME                READY   STATUS        RESTARTS   AGE
example-job-b59zk   1/1     Running       0          1s
example-job-qr8kf   1/1     Terminating   0          17s
example-job-stvb4   1/1     Running       0          17s

使用 Failed 策略時,當舊 Pod(example-job-qr8kf)正在終止時,不會建立新的 Pod(example-job-b59zk)。

kubectl get pods

NAME                READY   STATUS        RESTARTS   AGE
example-job-qr8kf   1/1     Terminating   0          17s
example-job-stvb4   1/1     Running       0          17s

當正在終止的 Pod 完全轉換到 Failed 階段時,才會建立一個新的 Pod:

kubectl get pods

NAME                READY   STATUS        RESTARTS   AGE
example-job-b59zk   1/1     Running       0          1s
example-job-stvb4   1/1     Running       0          25s

如何瞭解更多?

致謝

與任何 Kubernetes 特性一樣,許多人都為完成這項工作做出了貢獻,從測試、提交錯誤到程式碼審查。

在這個特性經過 2 年的發展進入穩定階段之際,我們想感謝以下人員:

參與其中

這項工作由 Kubernetes 批處理工作組(batch working group)贊助,並與 SIG Apps 社群密切合作。

如果你有興趣在該領域開發新功能,我們建議你訂閱我們的 Slack 頻道並參加定期的社群會議。