工作

工作代表一次性的任務,它們會執行直到完成然後停止。

一個工作會建立一個或多個 Pod,並會持續重試執行這些 Pod,直到指定數量的 Pod 成功終止。當 Pod 成功完成時,工作會追蹤這些成功的完成。當達到指定數量的成功完成時,該任務(即工作)就完成了。刪除一個工作會清理它所建立的 Pod。暫停一個工作會刪除其活躍的 Pod,直到該工作再次恢復。

一個簡單的案例是建立一個工作物件,以便可靠地執行一個 Pod 直到完成。如果第一個 Pod 失敗或被刪除(例如由於節點硬體故障或節點重啟),該工作物件將啟動一個新的 Pod。

您也可以使用工作來平行執行多個 Pod。

如果您想按排程執行工作(單一任務或多個平行任務),請參閱 CronJob

執行範例工作

這是一個工作設定的範例。它計算圓周率 π 到 2000 位並列印出來。它大約需要 10 秒鐘才能完成。

apiVersion: batch/v1
kind: Job
metadata:
  name: pi
spec:
  template:
    spec:
      containers:
      - name: pi
        image: perl:5.34.0
        command: ["perl",  "-Mbignum=bpi", "-wle", "print bpi(2000)"]
      restartPolicy: Never
  backoffLimit: 4

您可以使用此命令執行範例

kubectl apply -f https://kubernetes.club.tw/examples/controllers/job.yaml

輸出類似於此

job.batch/pi created

使用 kubectl 檢查工作的狀態


Name:           pi
Namespace:      default
Selector:       batch.kubernetes.io/controller-uid=c9948307-e56d-4b5d-8302-ae2d7b7da67c
Labels:         batch.kubernetes.io/controller-uid=c9948307-e56d-4b5d-8302-ae2d7b7da67c
                batch.kubernetes.io/job-name=pi
                ...
Annotations:    batch.kubernetes.io/job-tracking: ""
Parallelism:    1
Completions:    1
Start Time:     Mon, 02 Dec 2019 15:20:11 +0200
Completed At:   Mon, 02 Dec 2019 15:21:16 +0200
Duration:       65s
Pods Statuses:  0 Running / 1 Succeeded / 0 Failed
Pod Template:
  Labels:  batch.kubernetes.io/controller-uid=c9948307-e56d-4b5d-8302-ae2d7b7da67c
           batch.kubernetes.io/job-name=pi
  Containers:
   pi:
    Image:      perl:5.34.0
    Port:       <none>
    Host Port:  <none>
    Command:
      perl
      -Mbignum=bpi
      -wle
      print bpi(2000)
    Environment:  <none>
    Mounts:       <none>
  Volumes:        <none>
Events:
  Type    Reason            Age   From            Message
  ----    ------            ----  ----            -------
  Normal  SuccessfulCreate  21s   job-controller  Created pod: pi-xf9p4
  Normal  Completed         18s   job-controller  Job completed


apiVersion: batch/v1
kind: Job
metadata:
  annotations: batch.kubernetes.io/job-tracking: ""
             ...  
  creationTimestamp: "2022-11-10T17:53:53Z"
  generation: 1
  labels:
    batch.kubernetes.io/controller-uid: 863452e6-270d-420e-9b94-53a54146c223
    batch.kubernetes.io/job-name: pi
  name: pi
  namespace: default
  resourceVersion: "4751"
  uid: 204fb678-040b-497f-9266-35ffa8716d14
spec:
  backoffLimit: 4
  completionMode: NonIndexed
  completions: 1
  parallelism: 1
  selector:
    matchLabels:
      batch.kubernetes.io/controller-uid: 863452e6-270d-420e-9b94-53a54146c223
  suspend: false
  template:
    metadata:
      creationTimestamp: null
      labels:
        batch.kubernetes.io/controller-uid: 863452e6-270d-420e-9b94-53a54146c223
        batch.kubernetes.io/job-name: pi
    spec:
      containers:
      - command:
        - perl
        - -Mbignum=bpi
        - -wle
        - print bpi(2000)
        image: perl:5.34.0
        imagePullPolicy: IfNotPresent
        name: pi
        resources: {}
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
      dnsPolicy: ClusterFirst
      restartPolicy: Never
      schedulerName: default-scheduler
      securityContext: {}
      terminationGracePeriodSeconds: 30
status:
  active: 1
  ready: 0
  startTime: "2022-11-10T17:53:57Z"
  uncountedTerminatedPods: {}

要查看工作的已完成 Pod,請使用 kubectl get pods

要以機器可讀的格式列出屬於某個工作的所有 Pod,您可以使用類似這樣的命令

pods=$(kubectl get pods --selector=batch.kubernetes.io/job-name=pi --output=jsonpath='{.items[*].metadata.name}')
echo $pods

輸出類似於此

pi-5rwd7

在這裡,選擇器與工作的選擇器相同。--output=jsonpath 選項指定了一個表達式,其中包含返回列表中每個 Pod 的名稱。

查看其中一個 Pod 的標準輸出

kubectl logs $pods

查看工作日誌的另一種方式

kubectl logs jobs/pi

輸出類似於此

3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412737245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094330572703657595919530921861173819326117931051185480744623799627495673518857527248912279381830119491298336733624406566430860213949463952247371907021798609437027705392171762931767523846748184676694051320005681271452635608277857713427577896091736371787214684409012249534301465495853710507922796892589235420199561121290219608640344181598136297747713099605187072113499999983729780499510597317328160963185950244594553469083026425223082533446850352619311881710100031378387528865875332083814206171776691473035982534904287554687311595628638823537875937519577818577805321712268066130019278766111959092164201989380952572010654858632788659361533818279682303019520353018529689957736225994138912497217752834791315155748572424541506959508295331168617278558890750983817546374649393192550604009277016711390098488240128583616035637076601047101819429555961989467678374494482553797747268471040475346462080466842590694912933136770289891521047521620569660240580381501935112533824300355876402474964732639141992726042699227967823547816360093417216412199245863150302861829745557067498385054945885869269956909272107975093029553211653449872027559602364806654991198818347977535663698074265425278625518184175746728909777727938000816470600161452491921732172147723501414419735685481613611573525521334757418494684385233239073941433345477624168625189835694855620992192221842725502542568876717904946016534668049886272327917860857843838279679766814541009538837863609506800642251252051173929848960841284886269456042419652850222106611863067442786220391949450471237137869609563643719172874677646575739624138908658326459958133904780275901

撰寫工作規格

與所有其他 Kubernetes 設定一樣,工作需要 apiVersionkindmetadata 欄位。

當控制平面為工作建立新的 Pod 時,工作的 .metadata.name 是命名這些 Pod 的基礎的一部分。工作的名稱必須是有效的 DNS 子網域 值,但這可能會對 Pod 的主機名稱產生意外結果。為了獲得最佳相容性,名稱應遵循 DNS 標籤 更嚴格的規則。即使名稱是 DNS 子網域,其長度也不得超過 63 個字元。

工作也需要一個 .spec 區塊

工作標籤

工作標籤會以 batch.kubernetes.io/ 作為 job-namecontroller-uid 的前綴。

Pod 範本

.spec.template.spec 中唯一必需的欄位。

.spec.template 是一個 Pod 範本。它與 Pod 具有完全相同的架構,只是它是巢狀的,並且沒有 apiVersionkind 欄位。

除了 Pod 的必填欄位外,工作中的 Pod 範本必須指定適當的標籤(請參閱 Pod 選擇器)和適當的重啟策略。

僅允許 RestartPolicy 等於 NeverOnFailure

Pod 選擇器

.spec.selector 欄位是可選的。在幾乎所有情況下,您都不應指定它。請參閱 指定您自己的 Pod 選擇器 章節。

工作的平行執行

有三種主要任務類型適合作為工作執行

  1. 非平行工作
    • 通常只啟動一個 Pod,除非 Pod 失敗。
    • 一旦其 Pod 成功終止,該工作即告完成。
  2. 具有 *固定完成計數* 的平行工作
    • .spec.completions 指定一個非零正值。
    • 工作代表整體任務,當有 .spec.completions 個 Pod 成功時,即告完成。
    • 當使用 .spec.completionMode="Indexed" 時,每個 Pod 會在 0 到 .spec.completions-1 範圍內獲得一個不同的索引。
  3. 具有 *工作佇列* 的平行工作
    • 不指定 .spec.completions,預設為 .spec.parallelism
    • Pod 必須在彼此之間或與外部服務協調,以確定每個 Pod 應該處理什麼。例如,一個 Pod 可能從工作佇列中獲取一批最多 N 個項目。
    • 每個 Pod 都能獨立判斷其所有同伴是否完成,從而判斷整個工作是否完成。
    • 當工作中 *任何* Pod 成功終止時,不會建立新的 Pod。
    • 一旦至少一個 Pod 成功終止且所有 Pod 都已終止,則該工作即成功完成。
    • 一旦任何 Pod 成功退出,其他 Pod 就不應再為此任務執行任何工作或寫入任何輸出。它們都應處於退出過程中。

對於 *非平行* 工作,您可以不設定 .spec.completions.spec.parallelism。當兩者都未設定時,兩者都預設為 1。

對於 *固定完成計數* 工作,您應將 .spec.completions 設定為所需完成的數量。您可以設定 .spec.parallelism,或者不設定它,它將預設為 1。

對於 *工作佇列* 工作,您必須不設定 .spec.completions,並將 .spec.parallelism 設定為非負整數。

有關如何使用不同類型工作的更多資訊,請參閱 工作模式 章節。

控制平行度

請求的平行度 (.spec.parallelism) 可以設定為任何非負值。如果未指定,則預設為 1。如果指定為 0,則工作會有效地暫停,直到其值增加為止。

實際平行度(任何時刻執行的 Pod 數量)可能多於或少於請求的平行度,原因有很多

  • 對於 *固定完成計數* 工作,實際平行執行的 Pod 數量不會超過剩餘完成的數量。較高的 .spec.parallelism 值會被有效忽略。
  • 對於 *工作佇列* 工作,在任何 Pod 成功後不會啟動新的 Pod -- 但剩餘的 Pod 仍然可以完成。
  • 如果工作 控制器 還沒有時間做出反應。
  • 如果工作控制器因任何原因(例如缺乏 ResourceQuota、缺乏權限等)未能建立 Pod,則實際執行的 Pod 可能會少於請求的數量。
  • 由於同一個工作中的 Pod 過去失敗次數過多,工作控制器可能會限制新的 Pod 建立。
  • 當 Pod 優雅地關閉時,需要時間停止。

完成模式

功能狀態: Kubernetes v1.24 [stable]

具有 *固定完成計數* 的工作——即 .spec.completions 不為空的工作——可以有一個在 .spec.completionMode 中指定的完成模式

  • NonIndexed(預設):當有 .spec.completions 個 Pod 成功完成時,該工作被視為完成。換句話說,每個 Pod 的完成都是彼此同質的。請注意,.spec.completions 為空的工作隱含為 NonIndexed

  • Indexed:工作的 Pod 會獲得一個相關的完成索引,從 0 到 .spec.completions-1。該索引可透過四種機制取得

    • Pod 註解 batch.kubernetes.io/job-completion-index
    • Pod 標籤 batch.kubernetes.io/job-completion-index(適用於 v1.28 及更高版本)。請注意,必須啟用功能門 PodIndexLabel 才能使用此標籤,並且它預設為啟用。
    • 作為 Pod 主機名稱的一部分,遵循模式 $(job-name)-$(index)。當您將索引工作與 服務 結合使用時,工作中的 Pod 可以使用確定性主機名稱透過 DNS 互相定址。有關如何配置此項的更多資訊,請參閱 具有 Pod 對 Pod 通訊的工作
    • 從容器化任務中,在環境變數 JOB_COMPLETION_INDEX 中。

    當每個索引都有一個成功完成的 Pod 時,該工作被視為完成。有關如何使用此模式的更多資訊,請參閱 用於靜態工作分配的平行處理的索引工作

注意

雖然罕見,但由於各種原因(例如節點故障、kubelet 重啟或 Pod 驅逐),可能會為同一個索引啟動多個 Pod。在這種情況下,只有第一個成功完成的 Pod 將計入完成計數並更新工作的狀態。其他為同一個索引正在執行或已完成的 Pod,一旦被偵測到,將由工作控制器刪除。

與工作負載 API 整合

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

當啟用 WorkloadWithJob 功能門時,工作控制器會在建立任何 Pod 之前,自動為 符合條件的平行工作 建立 工作負載 (Workload)PodGroup 物件。這使得原生 群組排程 (gang scheduling) 成為可能,即工作中所有 Pod 要麼一起排程,要麼都不排程。

合格條件

當工作符合以下所有條件時,工作控制器會建立一個具有 群組排程策略 的工作負載 (Workload)

  • .spec.parallelism 大於 1
  • .spec.completionModeIndexed
  • .spec.parallelism 等於 .spec.completions
  • .spec.template.spec.schedulingGroup 未設定

不符合這些條件的工作會繼續獨立排程 Pod,並且不建立 WorkloadPodGroup

例如,以下工作執行 8 個平行的索引工作者。當此功能啟用時,工作控制器會在建立任何 Pod 之前建立一個帶有 minCount: 8WorkloadPodGroup,確保所有 8 個工作者一起排程。

apiVersion: batch/v1
kind: Job
metadata:
  name: distributed-training
  namespace: training
spec:
  parallelism: 8
  completions: 8
  completionMode: Indexed
  template:
    spec:
      restartPolicy: Never
      containers:
      - name: trainer
        image: training-image:latest
        resources:
          limits:
            nvidia.com/gpu: 1

當工作控制器處理此工作時,它會自動執行以下操作:

  1. 在相同的命名空間中建立一個 工作負載 (Workload) 物件。該工作負載包含一個 podGroupTemplate,其中帶有 群組排程策略,其中 minCount 等於工作負載的平行度。
  2. 基於該範本建立一個 PodGroup 物件。PodGroup 是一個獨立的執行時排程單元,攜帶一份群組策略的內聯副本。
  3. 建立 Pod,並將 spec.schedulingGroup.podGroupName 設定為 PodGroup 的名稱,將每個 Pod 連結到其排程群組。

這些物件的發現基於規格參考 (controllerRefpodGroupTemplateRef)。

工作負載 (Workload) 和 PodGroup 由工作擁有(透過 ownerReferences),並在工作刪除時自動進行垃圾回收。

高階控制器退出選項

如果工作的 Pod 範本已經設定了 spec.schedulingGroup,則工作控制器不會建立 WorkloadPodGroup 物件。這允許 JobSet 等高階控制器自行管理 WorkloadPodGroup 的生命週期。

CronJob 行為

CronJob 建立的工作在其 PodTemplate 中沒有設定 schedulingGroup。如果 CronJob 建立的工作符合群組排程條件,工作控制器會為每個工作實例建立單獨的 WorkloadPodGroup

Alpha 版的限制

  • 每個工作都精確地映射到一個 PodGroup。工作中所有的 Pod 都屬於同一個排程群組。
  • 群組策略中的 minCount 是不可變的。對於使用群組排程的工作,對 .spec.parallelism 的更新將被拒絕。有關此限制的詳細資訊,請參閱 彈性索引工作
  • 暫停的工作會保留其 WorkloadPodGroup 物件;它們在暫停時不會被刪除,在恢復時也不會被重新建立。

處理 Pod 和容器故障

Pod 中的容器可能會因多種原因失敗,例如其中程序以非零退出碼退出,或容器因超出記憶體限制而被殺死等。如果發生這種情況,並且 .spec.template.spec.restartPolicy = "OnFailure",則 Pod 會留在節點上,但容器會重新執行。因此,您的程式需要處理在本機重新啟動的情況,否則應指定 .spec.template.spec.restartPolicy = "Never"。有關 restartPolicy 的更多資訊,請參閱 Pod 生命週期

整個 Pod 也可能因多種原因而失敗,例如當 Pod 從節點中被驅逐(節點升級、重啟、刪除等),或者 Pod 的容器失敗且 .spec.template.spec.restartPolicy = "Never"。當 Pod 失敗時,工作控制器會啟動一個新的 Pod。這意味著您的應用程式需要處理在新 Pod 中重新啟動的情況。特別是,它需要處理前一次執行造成的暫存檔案、鎖定、不完整輸出等。

預設情況下,每個 Pod 失敗都會計入 .spec.backoffLimit 限制,請參閱 Pod 退避失敗策略。但是,您可以透過設定工作的 Pod 失敗策略 來客製化處理 Pod 失敗。

此外,您可以透過設定 .spec.backoffLimitPerIndex 欄位,為 索引式 工作的每個索引獨立計算 Pod 失敗(有關更多資訊,請參閱 每個索引的退避限制)。

請注意,即使您指定 .spec.parallelism = 1.spec.completions = 1.spec.template.spec.restartPolicy = "Never",同一個程式有時仍可能被啟動兩次。

如果您指定 .spec.parallelism.spec.completions 都大於 1,則可能會有許多 Pod 同時執行。因此,您的 Pod 也必須能夠容忍並行。

如果您指定了 .spec.podFailurePolicy 欄位,工作控制器不會將正在終止的 Pod(即設定了 .metadata.deletionTimestamp 欄位的 Pod)視為失敗,直到該 Pod 達到終端狀態(其 .status.phaseFailedSucceeded)。然而,一旦終止變得明顯,工作控制器就會建立一個替換 Pod。一旦 Pod 終止,工作控制器會評估相關工作的 .backoffLimit.podFailurePolicy,將這個現在已終止的 Pod 納入考慮。

如果這些要求中的任何一個未滿足,工作控制器會將正在終止的 Pod 視為立即失敗,即使該 Pod 後來以 phase: "Succeeded" 終止。

Pod 退避失敗策略

在某些情況下,您希望在因配置中的邏輯錯誤等原因重試一定次數後使工作失敗。為此,請設定 .spec.backoffLimit 以指定在將工作視為失敗之前的重試次數。

.spec.backoffLimit 預設設定為 6,除非指定了 每個索引的退避限制(僅限索引式工作)。當指定 .spec.backoffLimitPerIndex 時,.spec.backoffLimit 預設為 2147483647 (MaxInt32)。

與工作相關聯的失敗 Pod 會由工作控制器以指數退避延遲(10 秒、20 秒、40 秒...)重新建立,上限為六分鐘。

重試次數透過兩種方式計算

  • .status.phase = "Failed" 的 Pod 數量。
  • 當使用 restartPolicy = "OnFailure" 時,所有 .status.phase 等於 PendingRunning 的 Pod 中所有容器的重試次數。

如果任一計算達到 .spec.backoffLimit,則該工作被視為失敗。

注意

如果您的工作具有 restartPolicy = "OnFailure",請記住,一旦達到工作的退避限制,執行該工作的 Pod 將被終止。這可能會使調試工作的可執行檔更加困難。我們建議在調試工作時設定 restartPolicy = "Never",或使用日誌系統以確保失敗工作的輸出不會意外遺失。

每個索引的退避限制

功能狀態: Kubernetes v1.33 [stable] (預設啟用)

當您執行 索引式 工作時,您可以選擇為每個索引獨立處理 Pod 失敗的重試。為此,請設定 .spec.backoffLimitPerIndex 以指定每個索引的 Pod 失敗的最大數量。

當索引的每索引退避限制被超出時,Kubernetes 會將該索引視為失敗,並將其新增到 .status.failedIndexes 欄位。成功執行的 Pod 所屬的成功索引,無論您是否設定 backoffLimitPerIndex 欄位,都會記錄在 .status.completedIndexes 欄位中。

請注意,失敗的索引不會中斷其他索引的執行。一旦您為工作指定了每個索引的退避限制,並且所有索引都完成,如果其中至少一個索引失敗,工作控制器會透過在狀態中設定 Failed 條件來將整個工作標記為失敗。即使部分(甚至幾乎所有)索引都已成功處理,工作仍會被標記為失敗。

您還可以透過設定 .spec.maxFailedIndexes 欄位來限制被標記為失敗的索引的最大數量。當失敗索引的數量超過 maxFailedIndexes 欄位時,工作控制器會觸發終止該工作中所有剩餘的執行中 Pod。一旦所有 Pod 都終止,工作控制器會透過在工作狀態中設定 Failed 條件來將整個工作標記為失敗。

這是一個定義了 backoffLimitPerIndex 的工作範例宣告

apiVersion: batch/v1
kind: Job
metadata:
  name: job-backoff-limit-per-index-example
spec:
  completions: 10
  parallelism: 3
  completionMode: Indexed  # required for the feature
  backoffLimitPerIndex: 1  # maximal number of failures per index
  maxFailedIndexes: 5      # maximal number of failed indexes before terminating the Job execution
  template:
    spec:
      restartPolicy: Never # required for the feature
      containers:
      - name: example
        image: python
        command:           # The jobs fails as there is at least one failed index
                           # (all even indexes fail in here), yet all indexes
                           # are executed as maxFailedIndexes is not exceeded.
        - python3
        - -c
        - |
          import os, sys
          print("Hello world")
          if int(os.environ.get("JOB_COMPLETION_INDEX")) % 2 == 0:
            sys.exit(1)          

在上述範例中,工作控制器允許每個索引重新啟動一次。當失敗索引的總數超過 5 時,則整個工作終止。

工作完成後,工作狀態如下所示

kubectl get -o yaml job job-backoff-limit-per-index-example
  status:
    completedIndexes: 1,3,5,7,9
    failedIndexes: 0,2,4,6,8
    succeeded: 5          # 1 succeeded pod for each of 5 succeeded indexes
    failed: 10            # 2 failed pods (1 retry) for each of 5 failed indexes
    conditions:
    - message: Job has failed indexes
      reason: FailedIndexes
      status: "True"
      type: FailureTarget
    - message: Job has failed indexes
      reason: FailedIndexes
      status: "True"
      type: Failed

工作控制器新增 FailureTarget 工作條件以觸發 工作的終止與清理。當所有工作 Pod 都終止後,工作控制器會新增 Failed 條件,其 reasonmessage 值與 FailureTarget 工作條件相同。有關詳細資訊,請參閱 工作 Pod 的終止

此外,您可能希望將每索引退避與 Pod 失敗策略 一起使用。當使用每索引退避時,有一個新的 FailIndex 動作可用,它允許您避免在索引內進行不必要的重試。

Pod 失敗策略

功能狀態: Kubernetes v1.31 [穩定版](預設啟用)

Pod 失敗策略,透過 .spec.podFailurePolicy 欄位定義,使您的叢集能夠根據容器退出碼和 Pod 條件來處理 Pod 失敗。

在某些情況下,您可能希望在處理 Pod 失敗時擁有比 Pod 退避失敗策略 更好的控制,後者是基於工作的 .spec.backoffLimit。以下是一些使用案例範例

  • 為了優化執行工作負載的成本,避免不必要的 Pod 重啟,一旦其中一個 Pod 因表示軟體錯誤的退出碼而失敗,您就可以終止該工作。
  • 為了確保您的工作即使在有中斷的情況下也能完成,您可以忽略由中斷引起的 Pod 失敗(例如 搶占 (preemption)API 驅動的驅逐 (API-initiated eviction) 或基於 污點 (taint) 的驅逐),這樣它們就不會計入 .spec.backoffLimit 的重試限制。

您可以在 .spec.podFailurePolicy 欄位中配置 Pod 失敗策略,以滿足上述使用案例。此策略可以根據容器退出碼和 Pod 條件來處理 Pod 失敗。

這是一個定義了 podFailurePolicy 的工作範例宣告

apiVersion: batch/v1
kind: Job
metadata:
  name: job-pod-failure-policy-example
spec:
  completions: 12
  parallelism: 3
  template:
    spec:
      restartPolicy: Never
      containers:
      - name: main
        image: docker.io/library/bash:5
        command: ["bash"]        # example command simulating a bug which triggers the FailJob action
        args:
        - -c
        - echo "Hello world!" && sleep 5 && exit 42
  backoffLimit: 6
  podFailurePolicy:
    rules:
    - action: FailJob
      onExitCodes:
        containerName: main      # optional
        operator: In             # one of: In, NotIn
        values: [42]
    - action: Ignore             # one of: Ignore, FailJob, Count
      onPodConditions:
      - type: DisruptionTarget   # indicates Pod disruption

在上述範例中,Pod 失敗策略的第一條規則指定,如果 main 容器以退出碼 42 失敗,則該工作應被標記為失敗。以下是針對 main 容器的具體規則

  • 退出碼為 0 表示容器成功
  • 退出碼為 42 表示 **整個工作** 失敗
  • 任何其他退出碼表示容器失敗,進而整個 Pod 失敗。如果總重啟次數低於 backoffLimit,則 Pod 將被重新建立。如果達到 backoffLimit,則 **整個工作** 失敗。

注意

因為 Pod 範本指定了 restartPolicy: Never,所以 kubelet 不會重新啟動該特定 Pod 中的 main 容器。

Pod 失敗策略的第二條規則,為具有條件 DisruptionTarget 的失敗 Pod 指定 Ignore 動作,將 Pod 中斷排除在 .spec.backoffLimit 的重試限制之外。

注意

如果工作因 Pod 失敗策略或 Pod 退避失敗策略而失敗,且該工作正在執行多個 Pod,Kubernetes 會終止該工作中所有仍處於 Pending 或 Running 狀態的 Pod。

以下是 API 的一些要求和語義

  • 如果您想為工作使用 .spec.podFailurePolicy 欄位,您還必須將該工作的 Pod 範本定義為 .spec.restartPolicy 設定為 Never
  • 您在 spec.podFailurePolicy.rules 下指定的 Pod 失敗策略規則會依序評估。一旦某條規則符合 Pod 失敗,其餘規則將被忽略。如果沒有規則符合 Pod 失敗,則套用預設處理方式。
  • 您可能希望透過在 spec.podFailurePolicy.rules[*].onExitCodes.containerName 中指定其名稱來將規則限制到特定容器。如果未指定,則該規則適用於所有容器。如果指定,它應與 Pod 範本中的某個容器或 initContainer 名稱匹配。
  • 您可以透過 spec.podFailurePolicy.rules[*].action 指定 Pod 失敗策略匹配時採取的動作。可能的值為
    • FailJob:用於指示 Pod 的工作應標記為失敗,並且所有執行中的 Pod 都應終止。
    • Ignore:用於指示不應增加 .spec.backoffLimit 的計數器,並且應建立一個替換 Pod。
    • Count:用於指示應以預設方式處理 Pod。應增加 .spec.backoffLimit 的計數器。
    • FailIndex:將此動作與 每個索引的退避限制 一起使用,以避免在失敗 Pod 的索引內進行不必要的重試。

注意

當您使用 podFailurePolicy 時,工作控制器只會匹配處於 Failed 階段的 Pod。具有刪除時間戳但未處於終端階段(FailedSucceeded)的 Pod 被視為仍在終止中。這意味著正在終止的 Pod 會保留一個 追蹤 finalizer,直到它們達到終端階段。自 Kubernetes 1.27 起,Kubelet 將已刪除的 Pod 轉換為終端階段(請參閱:Pod 階段)。這確保了已刪除的 Pod 其 finalizer 會被工作控制器移除。

注意

從 Kubernetes v1.28 開始,當使用 Pod 失敗策略時,工作控制器只會在這些 Pod 達到終端 Failed 階段後才重新建立正在終止的 Pod。此行為類似於 podReplacementPolicy: Failed。有關更多資訊,請參閱 Pod 替換策略

當您使用 podFailurePolicy,且工作因 Pod 符合帶有 FailJob 動作的規則而失敗時,工作控制器會透過新增 FailureTarget 條件來觸發工作終止程序。有關更多詳細資訊,請參閱 工作的終止與清理

成功策略

建立索引式工作時,您可以根據成功完成的 Pod 來定義何時將工作宣告為成功,方法是使用 .spec.successPolicy

預設情況下,當成功完成的 Pod 數量等於 .spec.completions 時,工作即告成功。以下是您可能希望對宣告工作成功擁有額外控制權的一些情況

  • 當使用不同參數執行模擬時,您可能不需要所有模擬都成功才能使整個工作成功。
  • 當遵循主從式 (leader-worker) 模式時,只有主節點 (leader) 的成功才決定工作的成功或失敗。例如 MPI 和 PyTorch 等框架就是如此。

您可以在 .spec.successPolicy 欄位中配置成功策略,以滿足上述使用案例。此策略可以根據成功的 Pod 處理工作成功。在工作符合成功策略後,工作控制器會終止殘留的 Pod。成功策略由規則定義。每個規則可以採用以下形式之一

  • 當您僅指定 succeededIndexes 時,一旦 succeededIndexes 中指定的所有索引成功,工作控制器會將工作標記為成功。succeededIndexes 必須是 0 到 .spec.completions-1 之間的區間列表。
  • 當您僅指定 succeededCount 時,一旦成功索引的數量達到 succeededCount,工作控制器會將工作標記為成功。
  • 當您同時指定 succeededIndexessucceededCount 時,一旦在 succeededIndexes 中指定索引子集中的成功索引數量達到 succeededCount,工作控制器會將工作標記為成功。

請注意,當您在 .spec.successPolicy.rules 中指定多個規則時,工作控制器會依序評估這些規則。一旦工作符合某條規則,工作控制器會忽略其餘規則。

這是一個帶有 successPolicy 的工作範例宣告

apiVersion: batch/v1
kind: Job
metadata:
  name: job-success
spec:
  parallelism: 10
  completions: 10
  completionMode: Indexed # Required for the success policy
  successPolicy:
    rules:
      - succeededIndexes: 0,2-3
        succeededCount: 1
  template:
    spec:
      containers:
      - name: main
        image: python
        command:          # Provided that at least one of the Pods with 0, 2, and 3 indexes has succeeded,
                          # the overall Job is a success.
          - python3
          - -c
          - |
            import os, sys
            if os.environ.get("JOB_COMPLETION_INDEX") == "2":
              sys.exit(0)
            else:
              sys.exit(1)            
      restartPolicy: Never

在上述範例中,同時指定了 succeededIndexessucceededCount。因此,當指定索引中的任一個(0、2 或 3)成功時,工作控制器會將工作標記為成功並終止殘留的 Pod。符合成功策略的工作會獲得帶有 SuccessPolicy 原因的 SuccessCriteriaMet 條件。在發出移除殘留 Pod 的指令後,工作會獲得 Complete 條件。

請注意,succeededIndexes 以連字號分隔的區間表示。數字列出方式是透過序列的第一個和最後一個元素,並以連字號分隔。

注意

當您同時指定成功策略和一些終止策略,例如 .spec.backoffLimit.spec.podFailurePolicy 時,一旦工作符合其中任何一個策略,工作控制器會遵守終止策略並忽略成功策略。

工作的終止與清理

當工作完成時,不會再建立 Pod,但這些 Pod 通常 也不會被刪除。保留它們可以讓您仍然查看已完成 Pod 的日誌,以檢查錯誤、警告或其他診斷輸出。工作物件在完成後也會保留,以便您可以查看其狀態。使用者應在記錄其狀態後刪除舊工作。使用 kubectl 刪除工作(例如 kubectl delete jobs/pikubectl delete -f ./job.yaml)。當您使用 kubectl 刪除工作時,它建立的所有 Pod 也會被刪除。

預設情況下,工作將不中斷地執行,除非 Pod 失敗 (restartPolicy=Never) 或容器錯誤退出 (restartPolicy=OnFailure),此時工作會依照上述 .spec.backoffLimit 處理。一旦達到 .spec.backoffLimit,工作將被標記為失敗,並且任何執行中的 Pod 都將被終止。

終止工作的另一種方法是設定活躍期限 (active deadline)。透過將工作的 .spec.activeDeadlineSeconds 欄位設定為秒數來實現。activeDeadlineSeconds 適用於工作的持續時間,無論建立多少個 Pod。一旦工作達到 activeDeadlineSeconds,所有執行中的 Pod 都會被終止,並且工作狀態將變為 type: Failed,其 reason: DeadlineExceeded

請注意,工作的 .spec.activeDeadlineSeconds 優先於其 .spec.backoffLimit。因此,正在重試一個或多個失敗 Pod 的工作,一旦達到 activeDeadlineSeconds 指定的時間限制,即使尚未達到 backoffLimit,也不會部署額外的 Pod。

範例:

apiVersion: batch/v1
kind: Job
metadata:
  name: pi-with-timeout
spec:
  backoffLimit: 5
  activeDeadlineSeconds: 100
  template:
    spec:
      containers:
      - name: pi
        image: perl:5.34.0
        command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]
      restartPolicy: Never

請注意,工作規格和工作中的 Pod 範本規格 都具有 activeDeadlineSeconds 欄位。請確保您在適當的層級設定此欄位。

請記住,restartPolicy 適用於 Pod,而不是工作本身:一旦工作狀態為 type: Failed,就不會自動重啟工作。也就是說,透過 .spec.activeDeadlineSeconds.spec.backoffLimit 啟動的工作終止機制會導致永久性的工作失敗,需要手動干預才能解決。

終止狀態的工作條件

工作有兩種可能的終端狀態,每種狀態都對應一個工作條件

  • 成功 (Succeeded):工作條件 Complete
  • 失敗 (Failed):工作條件 Failed

工作因以下原因失敗

  • Pod 失敗次數超過工作規格中指定的 .spec.backoffLimit。有關詳細資訊,請參閱 Pod 退避失敗策略
  • 工作執行時間超過指定的 .spec.activeDeadlineSeconds
  • 使用 .spec.backoffLimitPerIndex 的索引式工作具有失敗的索引。有關詳細資訊,請參閱 每個索引的退避限制
  • 工作中失敗索引的數量超過指定的 spec.maxFailedIndexes。有關詳細資訊,請參閱 每個索引的退避限制
  • 失敗的 Pod 符合 .spec.podFailurePolicy 中具有 FailJob 動作的規則。有關 Pod 失敗策略規則如何影響失敗評估的詳細資訊,請參閱 Pod 失敗策略

工作因以下原因成功

  • 成功 Pod 的數量達到指定的 .spec.completions
  • 符合 .spec.successPolicy 中指定的條件。有關詳細資訊,請參閱 成功策略

在 Kubernetes v1.31 及更高版本中,工作控制器會延遲新增終端條件 FailedComplete,直到所有工作 Pod 都終止。

在 Kubernetes v1.30 及更早版本中,工作控制器會在工作終止程序觸發且所有 Pod finalizer 被移除後立即新增 CompleteFailed 工作終端條件。然而,在新增終端條件時,某些 Pod 可能仍在執行或終止中。

在 Kubernetes v1.31 及更高版本中,控制器只在所有 Pod 終止 *之後* 才新增工作終端條件。您可以透過使用 JobManagedByJobPodReplacementPolicy(兩者預設均啟用)功能門 來控制此行為。

工作 Pod 的終止

工作控制器會將 FailureTarget 條件或 SuccessCriteriaMet 條件新增到工作中,以在工作符合成功或失敗條件後觸發 Pod 終止。

諸如 terminationGracePeriodSeconds 之類的因素可能會增加從工作控制器新增 FailureTarget 條件或 SuccessCriteriaMet 條件到所有工作 Pod 終止且工作控制器新增 終端條件FailedComplete)之間的時間量。

您可以使用 FailureTargetSuccessCriteriaMet 條件來評估工作是失敗還是成功,而無需等待控制器新增終端條件。

例如,您可能希望決定何時建立替換工作以替換失敗的工作。如果您在 FailureTarget 條件出現時替換失敗的工作,您的替換工作會更快執行,但可能導致失敗的工作和替換工作的 Pod 同時執行,佔用額外的計算資源。

或者,如果您的叢集資源容量有限,您可以選擇等到 Failed 條件出現在工作上,這會延遲您的替換工作,但能確保您透過等待所有失敗的 Pod 被移除來節省資源。

自動清理已完成的工作

已完成的工作通常不再需要留在系統中。將它們保留在系統中會對 API 伺服器造成壓力。如果工作由 CronJobs 等高階控制器直接管理,則 CronJobs 可以根據指定的基於容量的清理策略來清理這些工作。

已完成工作的 TTL 機制

功能狀態: Kubernetes v1.23 [穩定]

自動清理已完成工作(無論是 Complete 還是 Failed)的另一種方法是使用 TTL 控制器 為已完成資源提供的 TTL 機制,方法是指定工作的 .spec.ttlSecondsAfterFinished 欄位。

當 TTL 控制器清理工作時,它會級聯刪除該工作,即連同工作一起刪除其依賴物件,例如 Pod。請注意,當工作被刪除時,其生命週期保證,例如 finalizer,將被遵守。

例如

apiVersion: batch/v1
kind: Job
metadata:
  name: pi-with-ttl
spec:
  ttlSecondsAfterFinished: 100
  template:
    spec:
      containers:
      - name: pi
        image: perl:5.34.0
        command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]
      restartPolicy: Never

工作 pi-with-ttl 將在完成後 100 秒內符合自動刪除的資格。

如果該欄位設定為 0,工作將在完成後立即符合自動刪除的資格。如果該欄位未設定,則此工作在完成後不會被 TTL 控制器清理。

注意

建議設定 ttlSecondsAfterFinished 欄位,因為非託管工作(您直接建立而非透過其他工作負載 API,例如 CronJob 間接建立的工作)預設刪除策略為 orphanDependents,這會導致由非託管工作建立的 Pod 在該工作完全刪除後仍然存在。儘管 控制平面 (control plane) 最終會在已刪除工作的 Pod 失敗或完成後 垃圾回收 這些 Pod,但有時這些殘留的 Pod 可能會導致叢集效能下降,最壞的情況下甚至可能導致叢集因這種下降而離線。

您可以使用 LimitRangesResourceQuotas 來限制特定命名空間可以消耗的資源量。

工作模式

工作物件可用於處理一組獨立但相關的 *工作項目*。這些可能是要發送的電子郵件、要渲染的影格、要轉碼的檔案、要在 NoSQL 資料庫中掃描的鍵範圍等等。

在複雜系統中,可能有多個不同的工作項目集合。這裡我們只考慮使用者想要一起管理的一個工作項目集合——一個 *批次工作*。

平行計算有幾種不同的模式,每種模式都有其優點和缺點。權衡點在於

  • 每個工作項目一個 Job 物件,與所有工作項目共用單一 Job 物件。每個工作項目一個 Job 會為使用者和系統管理大量 Job 物件產生一些額外開銷。單一 Job 處理所有工作項目對於大量項目而言更好。
  • 建立的 Pod 數量等於工作項目數量,與每個 Pod 可以處理多個工作項目。當 Pod 數量等於工作項目數量時,通常只需要對現有程式碼和容器進行較少修改。讓每個 Pod 處理多個工作項目對於大量項目而言更好。
  • 有幾種方法使用工作佇列。這需要執行佇列服務,並修改現有程式或容器以使其使用工作佇列。其他方法更容易適應現有的容器化應用程式。
  • 當 Job 關聯到 無頭服務 (headless Service) 時,您可以讓 Job 中的 Pods 互相通訊以協同計算。

權衡總結如下,欄位 2 到 4 對應上述權衡。模式名稱也是範例和更詳細說明的連結。

模式單一 Job 物件Pod 數量少於工作項目嗎?使用未修改的應用程式嗎?
每個工作項目一個 Pod 的佇列有時
具可變 Pod 數量的佇列
具靜態工作分配的索引式 Job
帶有 Pod 到 Pod 通訊的工作有時有時
Job 範本擴展

當您使用 .spec.completions 指定完成數時,由 Job 控制器建立的每個 Pod 都具有相同的 spec。這表示任務的所有 Pods 將具有相同的命令列、相同的映像檔、相同的磁碟區,以及(幾乎)相同的環境變數。這些模式是安排 Pods 處理不同工作的不同方式。

此表格顯示了每個模式的 .spec.parallelism.spec.completions 所需設定。在此,W 是工作項目的數量。

模式.spec.completions.spec.parallelism
每個工作項目一個 Pod 的佇列W任何
具可變 Pod 數量的佇列null任何
具靜態工作分配的索引式 JobW任何
帶有 Pod 到 Pod 通訊的工作WW
Job 範本擴展1應為 1

進階用法

暫停工作

功能狀態: Kubernetes v1.24 [stable]

當 Job 建立時,Job 控制器會立即開始建立 Pods 以滿足 Job 的要求,並持續執行直到 Job 完成。然而,您可能希望暫時暫停 Job 的執行並稍後恢復,或者以暫停狀態啟動 Job,然後讓自訂控制器稍後決定何時啟動它們。

要暫停 Job,您可以將 Job 的 .spec.suspend 欄位更新為 true;稍後當您想再次恢復它時,將其更新為 false。建立一個 .spec.suspend 設定為 true 的 Job 將使其處於暫停狀態。

在 Kubernetes 1.35 或更高版本中,當 MutableSchedulingDirectivesForSuspendedJobs 功能閘道啟用時,.status.startTime 欄位會在 Job 暫停時被清除。

當 Job 從暫停中恢復時,其 .status.startTime 欄位將重設為目前時間。這表示當 Job 暫停和恢復時,.spec.activeDeadlineSeconds 計時器將停止並重設。

當您暫停 Job 時,任何狀態不為 Completed 的正在執行的 Pods 將會以 SIGTERM 訊號終止。Pod 的優雅終止期將被遵守,您的 Pod 必須在此期間處理此訊號。這可能涉及為以後儲存進度或撤銷變更。以這種方式終止的 Pods 將不計入 Job 的 completions 數。

處於暫停狀態的 Job 定義範例如下

kubectl get job myjob -o yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: myjob
spec:
  suspend: true
  parallelism: 1
  completions: 5
  template:
    spec:
      ...

您也可以透過使用命令列修補 Job 來切換 Job 的暫停狀態。

暫停啟用中的 Job

kubectl patch job/myjob --type=strategic --patch '{"spec":{"suspend":true}}'

恢復暫停的 Job

kubectl patch job/myjob --type=strategic --patch '{"spec":{"suspend":false}}'

Job 的狀態可用於判斷 Job 是否正在暫停中或過去是否曾被暫停

kubectl get jobs/myjob -o yaml
apiVersion: batch/v1
kind: Job
# .metadata and .spec omitted
status:
  conditions:
  - lastProbeTime: "2021-02-05T13:14:33Z"
    lastTransitionTime: "2021-02-05T13:14:33Z"
    status: "True"
    type: Suspended
  startTime: "2021-02-05T13:13:48Z"

類型為 "Suspended" 且狀態為 "True" 的 Job 條件表示 Job 正在暫停中;lastTransitionTime 欄位可用於判斷 Job 已暫停多久。如果該條件的狀態為 "False",則 Job 之前曾被暫停,現在正在執行。如果 Job 的狀態中不存在此類條件,則 Job 從未停止過。

當 Job 暫停和恢復時,也會建立事件。

kubectl describe jobs/myjob
Name:           myjob
...
Events:
  Type    Reason            Age   From            Message
  ----    ------            ----  ----            -------
  Normal  SuccessfulCreate  12m   job-controller  Created pod: myjob-hlrpl
  Normal  SuccessfulDelete  11m   job-controller  Deleted pod: myjob-hlrpl
  Normal  Suspended         11m   job-controller  Job suspended
  Normal  SuccessfulCreate  3s    job-controller  Created pod: myjob-jvb44
  Normal  Resumed           3s    job-controller  Job resumed

最後四個事件,特別是「Suspended」(已暫停)和「Resumed」(已恢復)事件,是直接切換 .spec.suspend 欄位的結果。在這兩個事件之間,我們看到沒有建立任何 Pods,但一旦 Job 恢復,Pod 的建立就重新開始了。

可變排程指令

功能狀態: Kubernetes v1.27 [穩定版]

在大多數情況下,平行 Job 會希望 Pods 在約束條件下執行,例如全部在同一可用區,或全部在 GPU 型號 x 或 y 上,而不是兩者混用。

暫停 欄位是實現這些語義的第一步。暫停允許自訂佇列控制器決定 Job 何時應該開始;然而,一旦 Job 取消暫停,自訂佇列控制器就無法影響 Job 的 Pods 實際上將被排程到哪裡。

此功能允許在 Job 啟動之前更新其排程指令,這使自訂佇列控制器能夠影響 Pod 的放置,同時將實際的 Pod 到節點指派工作卸載給 kube-scheduler。

Job 的 Pod 範本中可以更新的欄位包括節點親和性、節點選擇器、容忍度、標籤、註解和 排程閘道

暫停中 Job 的可變排程指令

功能狀態: Kubernetes v1.36 [beta](預設啟用)

在 Kubernetes 1.34 或更早版本中,只有從未取消暫停過的暫停中 Job 才允許變更 Pod 的排程指令。在 Kubernetes 1.35 中,當 MutableSchedulingDirectivesForSuspendedJobs 功能閘道啟用時,任何暫停中 Job 都允許這樣做。

此外,此功能閘道也啟用在 Job 暫停時清除 .status.startTime 欄位。

暫停工作的可變 Pod 資源

功能狀態: Kubernetes v1.36 [beta](預設啟用)

叢集管理員可以在 Kubernetes 中定義準入控制,根據策略規則修改 Job 的資源請求或限制。

透過此功能,Kubernetes 也讓您可以修改 暫停中 Job 的 Pod 範本,以變更 Job 中 Pods 的資源需求。這與讓您一次更新一個正在執行的 Pod 資源的「即時 Pod 大小調整」不同。

設定新資源請求或限制的用戶端可以與最初建立 Job 的用戶端不同,並且不需要是叢集管理員。

指定您自己的 Pod 選擇器

通常,當您建立 Job 物件時,您不需要指定 .spec.selector。系統預設邏輯會在建立 Job 時新增此欄位。它會選擇一個不會與任何其他 Job 重疊的選擇器值。

然而,在某些情況下,您可能需要覆寫此自動設定的選擇器。為此,您可以指定 Job 的 .spec.selector

執行此操作時請務必小心。如果您指定的標籤選擇器對該 Job 的 Pods 不唯一,並且符合不相關的 Pods,那麼不相關 Job 的 Pods 可能會被刪除,或者此 Job 可能會將其他 Pods 計為完成任務,或者一個或兩個 Job 可能會拒絕建立 Pods 或執行到完成。如果選擇了非唯一選擇器,那麼其他控制器(例如 ReplicationController)及其 Pods 也可能以不可預測的方式運行。當您指定 .spec.selector 時,Kubernetes 不會阻止您犯錯。

以下是您可能希望使用此功能的一個範例。

假設 Job old 已經在執行。您希望現有的 Pods 繼續執行,但希望它建立的其餘 Pods 使用不同的 Pod 範本,並且 Job 具有一個新名稱。您無法更新 Job,因為這些欄位不可更新。因此,您使用 kubectl delete jobs/old --cascade=orphan 刪除 Job old,但 讓它的 Pods 保持執行。在刪除之前,請記下它使用的選擇器。

kubectl get job old -o yaml

輸出類似於此

kind: Job
metadata:
  name: old
  ...
spec:
  selector:
    matchLabels:
      batch.kubernetes.io/controller-uid: a8f3d00d-c6d2-11e5-9f87-42010af00002
  ...

然後您建立一個名稱為 new 的新 Job,並明確指定相同的選擇器。由於現有的 Pods 具有標籤 batch.kubernetes.io/controller-uid=a8f3d00d-c6d2-11e5-9f87-42010af00002,它們也由 Job new 控制。

您需要在新 Job 中指定 manualSelector: true,因為您沒有使用系統通常為您自動產生的選擇器。

kind: Job
metadata:
  name: new
  ...
spec:
  manualSelector: true
  selector:
    matchLabels:
      batch.kubernetes.io/controller-uid: a8f3d00d-c6d2-11e5-9f87-42010af00002
  ...

新 Job 本身將具有與 a8f3d00d-c6d2-11e5-9f87-42010af00002 不同的 uid。設定 manualSelector: true 告訴系統您知道自己在做什麼,並允許這種不匹配。

使用 finalizer 追蹤工作

功能狀態: Kubernetes v1.26 [穩定版]

控制平面會追蹤屬於任何 Job 的 Pods,並注意是否有此類 Pod 從 API 伺服器中移除。為此,Job 控制器會建立帶有 finalizer batch.kubernetes.io/job-tracking 的 Pods。控制器僅在 Pods 已在 Job 狀態中被計算在內後才移除 finalizer,從而允許 Pods 被其他控制器或使用者移除。

注意

如果您發現 Job 的 Pods 被追蹤 finalizer 卡住,請參閱 我的 Pod 一直處於終止狀態

彈性索引工作

功能狀態: Kubernetes v1.31 [穩定版](預設啟用)

您可以透過同時變更 .spec.parallelism.spec.completions,使其滿足 .spec.parallelism == .spec.completions,來擴展或縮減索引式 Job。縮減時,Kubernetes 會移除索引較高的 Pods。

彈性索引式 Job 的使用案例包括需要擴展索引式 Job 的批次工作負載,例如 MPI、Horovod、Ray 和 PyTorch 訓練 Job。

注意

WorkloadWithJob 功能閘道啟用且 Job 符合 成批排程準則時,對 .spec.parallelism 的更新將被拒絕,因為 WorkloadminCount 欄位是不可變的。要擴展成批排程的 Job,請刪除並使用新的平行度值重新建立它。

延遲建立替換 Pod

功能狀態: Kubernetes v1.34 [穩定] (預設啟用)

預設情況下,Job 控制器會在 Pods 失敗或正在終止(具有刪除時間戳記)時立即重新建立它們。這意味著,在給定時間,當某些 Pods 正在終止時,Job 的正在執行 Pods 數量可能大於 parallelism 或每個索引超過一個 Pod(如果您正在使用索引式 Job)。

您可以選擇僅當正在終止的 Pod 完全終止(具有 status.phase: Failed)時才建立替代 Pod。為此,請設定 .spec.podReplacementPolicy: Failed。預設的替換策略取決於 Job 是否設定了 podFailurePolicy。如果 Job 沒有定義 Pod 失敗策略,則省略 podReplacementPolicy 欄位會選擇 TerminatingOrFailed 替換策略:控制平面會在 Pod 刪除時立即建立替代 Pod(一旦控制平面看到此 Job 的 Pod 設定了 deletionTimestamp)。對於設定了 Pod 失敗策略的 Job,預設的 podReplacementPolicyFailed,不允許其他值。請參閱 Pod 失敗策略 以了解更多關於 Job 的 Pod 失敗策略。

kind: Job
metadata:
  name: new
  ...
spec:
  podReplacementPolicy: Failed
  ...

如果您的叢集已啟用該功能閘道,您可以檢查 Job 的 .status.terminating 欄位。該欄位的值是歸 Job 擁有且目前正在終止的 Pods 數量。

kubectl get jobs/myjob -o yaml
apiVersion: batch/v1
kind: Job
# .metadata and .spec omitted
status:
  terminating: 3 # three Pods are terminating and have not yet reached the Failed phase

將管理工作物件委派給外部控制器

功能狀態: Kubernetes v1.35 [stable](預設啟用)

此功能允許您針對特定 Job 停用內建的 Job 控制器,並將 Job 的協調任務委託給外部控制器。

您可以透過為 spec.managedBy 欄位設定自訂值(任何非 kubernetes.io/job-controller 的值)來指示協調 Job 的控制器。該欄位的值是不可變的。

注意

使用此功能時,請確保欄位指示的控制器已安裝,否則 Job 可能根本無法被協調。

注意

開發外部 Job 控制器時,請注意您的控制器需要以符合 Job 物件 API 規範和狀態欄位定義的方式運行。

請在 Job API 中詳細審查這些內容。我們也建議您執行 Job 物件的端到端一致性測試,以驗證您的實作。

最後,開發外部 Job 控制器時,請確保它不使用保留給內建控制器的 batch.kubernetes.io/job-tracking finalizer。

替代方案

裸 Pod

當 Pod 正在執行的節點重啟或失敗時,該 Pod 將被終止且不會重新啟動。然而,Job 會建立新的 Pods 來替換已終止的 Pods。因此,我們建議您使用 Job 而不是裸 Pod,即使您的應用程式只需要一個 Pod。

Replication Controller

Job 與 Replication Controllers 互補。Replication Controller 管理不預期會終止的 Pods(例如網路伺服器),而 Job 管理預期會終止的 Pods(例如批次任務)。

Pod 生命週期 中所討論,Job 適用於 RestartPolicy 等於 OnFailureNever 的 Pods。

注意

如果未設定 RestartPolicy,預設值為 Always

單一工作啟動控制器 Pod

另一種模式是單一 Job 建立一個 Pod,然後該 Pod 再建立其他 Pods,充當這些 Pods 的某種自訂控制器。這提供了最大的靈活性,但開始使用可能有些複雜,且與 Kubernetes 的整合度較低。

這種方法的優點是,整個流程獲得 Job 物件的完成保證,但又可以完全控制建立哪些 Pods 以及如何將工作分配給它們。

接下來


最後修改時間:2026 年 4 月 22 日下午 7:20(PST):將 EnableWorkloadWithJob 功能閘道引用重新命名為 WorkloadWithJob (6a336f22bf)