用於靜態工作分配的索引作業
Kubernetes v1.24 [stable]
在此示例中,你將執行一個 Kubernetes Job,它使用多個並行工作程序。 每個工作程序都是一個在各自 Pod 中執行的不同容器。 Pod 具有由控制面自動設定的**索引號**,這使得每個 Pod 都能識別要處理的整體任務的哪個部分。
Pod 索引號可以在annotation `batch.kubernetes.io/job-completion-index` 中以十進位制字串表示。為了使容器化任務程序獲取此索引,你可以使用downward API 機制釋出該 annotation 的值。為方便起見,控制平面會自動設定 downward API,以在 `JOB_COMPLETION_INDEX` 環境變數中公開該索引。
以下是本示例中的步驟概述:
- 使用索引完成定義 Job 清單。downward API 允許你將 Pod 索引 annotation 作為環境變數或檔案傳遞給容器。
- 根據清單啟動一個 `Indexed` Job.
準備工作
你應該已經熟悉 Job 的基本非並行用法。
你需要擁有一個 Kubernetes 叢集,並且 kubectl 命令列工具已配置為與你的叢集通訊。 建議你在至少有兩個不充當控制平面主機的節點的叢集上執行本教程。 如果你還沒有叢集,可以使用 minikube 建立一個,或者使用這些 Kubernetes 操場之一
你的 Kubernetes 伺服器版本必須是 v1.21 或更高。要檢查版本,請輸入 kubectl version
。
選擇一種方法
要從 worker 程式訪問工作項,你有以下幾種選擇
- 讀取 `JOB_COMPLETION_INDEX` 環境變數。Job 控制器自動將此變數連結到包含完成索引的 Annotation。
- 讀取包含完成索引的檔案。
- 假設你無法修改程式,你可以用一個指令碼將其包裝起來,該指令碼使用上述任何方法讀取索引並將其轉換為程式可以用作輸入的內容。
對於此示例,假設你選擇了選項 3,並且你想執行 rev 工具。此程式接受一個檔案作為引數,並反向列印其內容。
rev data.txt
你將使用 `busybox` 容器映象中的 `rev` 工具。
由於這只是一個示例,每個 Pod 只做一點點工作(反轉一個短字串)。在實際工作負載中,你可能會建立一個 Job,例如,該 Job 代表根據場景資料生成 60 秒影片的任務。影片渲染 Job 中的每個工作項將是渲染該影片剪輯的特定幀。索引完成意味著 Job 中的每個 Pod 都知道要渲染和釋出的幀,透過從剪輯的開頭計算幀來確定。
定義一個索引 Job
這是一個使用 `Indexed` 完成模式的 Job 清單示例
apiVersion: batch/v1
kind: Job
metadata:
name: 'indexed-job'
spec:
completions: 5
parallelism: 3
completionMode: Indexed
template:
spec:
restartPolicy: Never
initContainers:
- name: 'input'
image: 'docker.io/library/bash'
command:
- "bash"
- "-c"
- |
items=(foo bar baz qux xyz)
echo ${items[$JOB_COMPLETION_INDEX]} > /input/data.txt
volumeMounts:
- mountPath: /input
name: input
containers:
- name: 'worker'
image: 'docker.io/library/busybox'
command:
- "rev"
- "/input/data.txt"
volumeMounts:
- mountPath: /input
name: input
volumes:
- name: input
emptyDir: {}
在上面的示例中,你使用了 Job 控制器為所有容器設定的內建 `JOB_COMPLETION_INDEX` 環境變數。一個Init 容器將索引對映到一個靜態值,並將其寫入一個檔案,該檔案透過emptyDir 卷與執行 worker 的容器共享。你還可以選擇透過 Downward API 定義自己的環境變數來將索引發布到容器。你還可以選擇從 ConfigMap 載入值列表作為環境變數或檔案。
或者,你也可以直接使用 Downward API 將註解值作為卷檔案傳遞,如下例所示
apiVersion: batch/v1
kind: Job
metadata:
name: 'indexed-job'
spec:
completions: 5
parallelism: 3
completionMode: Indexed
template:
spec:
restartPolicy: Never
containers:
- name: 'worker'
image: 'docker.io/library/busybox'
command:
- "rev"
- "/input/data.txt"
volumeMounts:
- mountPath: /input
name: input
volumes:
- name: input
downwardAPI:
items:
- path: "data.txt"
fieldRef:
fieldPath: metadata.annotations['batch.kubernetes.io/job-completion-index']
執行 Job
現在執行 Job
# This uses the first approach (relying on $JOB_COMPLETION_INDEX)
kubectl apply -f https://kubernetes.club.tw/examples/application/job/indexed-job.yaml
當你建立此 Job 時,控制平面會建立一系列 Pod,每個 Pod 對應你指定的每個索引。`。spec.parallelism` 的值決定了可以同時執行多少個 Pod,而 `。spec.completions` 決定了 Job 總共建立多少個 Pod。
因為 `。spec.parallelism` 小於 `。spec.completions`,所以控制面會等待一些第一個 Pod 完成,然後才啟動更多的 Pod。
你可以等待 Job 成功,並設定超時:
# The check for condition name is case insensitive
kubectl wait --for=condition=complete --timeout=300s job/indexed-job
現在,描述 Job 並檢查它是否成功。
kubectl describe jobs/indexed-job
輸出類似於:
Name: indexed-job
Namespace: default
Selector: controller-uid=bf865e04-0b67-483b-9a90-74cfc4c3e756
Labels: controller-uid=bf865e04-0b67-483b-9a90-74cfc4c3e756
job-name=indexed-job
Annotations: <none>
Parallelism: 3
Completions: 5
Start Time: Thu, 11 Mar 2021 15:47:34 +0000
Pods Statuses: 2 Running / 3 Succeeded / 0 Failed
Completed Indexes: 0-2
Pod Template:
Labels: controller-uid=bf865e04-0b67-483b-9a90-74cfc4c3e756
job-name=indexed-job
Init Containers:
input:
Image: docker.io/library/bash
Port: <none>
Host Port: <none>
Command:
bash
-c
items=(foo bar baz qux xyz)
echo ${items[$JOB_COMPLETION_INDEX]} > /input/data.txt
Environment: <none>
Mounts:
/input from input (rw)
Containers:
worker:
Image: docker.io/library/busybox
Port: <none>
Host Port: <none>
Command:
rev
/input/data.txt
Environment: <none>
Mounts:
/input from input (rw)
Volumes:
input:
Type: EmptyDir (a temporary directory that shares a pod's lifetime)
Medium:
SizeLimit: <unset>
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal SuccessfulCreate 4s job-controller Created pod: indexed-job-njkjj
Normal SuccessfulCreate 4s job-controller Created pod: indexed-job-9kd4h
Normal SuccessfulCreate 4s job-controller Created pod: indexed-job-qjwsz
Normal SuccessfulCreate 1s job-controller Created pod: indexed-job-fdhq5
Normal SuccessfulCreate 1s job-controller Created pod: indexed-job-ncslj
在此示例中,你為每個索引執行具有自定義值的 Job。你可以檢查其中一個 Pod 的輸出
kubectl logs indexed-job-fdhq5 # Change this to match the name of a Pod from that Job
輸出類似於:
xuq