Kubernetes 使用索引作業(yè)完成靜態(tài)工作分配下的并行處理

2022-06-15 10:08 更新

使用索引作業(yè)完成靜態(tài)工作分配下的并行處理

特性狀態(tài): Kubernetes v1.24 [stable]

在此示例中,你將運(yùn)行一個(gè)使用多個(gè)并行工作進(jìn)程的 Kubernetes Job。 每個(gè) worker 都是在自己的 Pod 中運(yùn)行的不同容器。 Pod 具有控制平面自動(dòng)設(shè)置的 索引編號(hào)(index number), 這些編號(hào)使得每個(gè) Pod 能識(shí)別出要處理整個(gè)任務(wù)的哪個(gè)部分。

Pod 索引在注解 ?batch.kubernetes.io/job-completion-index? 中呈現(xiàn),具體表示為一個(gè)十進(jìn)制值字符串。 為了讓容器化的任務(wù)進(jìn)程獲得此索引,你可以使用 downward API 機(jī)制發(fā)布注解的值。為方便起見(jiàn), 控制平面自動(dòng)設(shè)置 downward API 以在 ?JOB_COMPLETION_INDEX ?環(huán)境變量中公開(kāi)索引。

以下是此示例中步驟的概述:

  1. 定義使用帶索引完成信息的 Job 清單。 Downward API 使你可以將 Pod 索引注釋作為環(huán)境變量或文件傳遞給容器。
  2. 根據(jù)該清單啟動(dòng)一個(gè)帶索引(?Indexed?)的 Job。

在開(kāi)始之前

你應(yīng)該已經(jīng)熟悉 Job 的基本的、非并行的用法。

你必須擁有一個(gè) Kubernetes 的集群,同時(shí)你的 Kubernetes 集群必須帶有 kubectl 命令行工具。 建議在至少有兩個(gè)節(jié)點(diǎn)的集群上運(yùn)行本教程,且這些節(jié)點(diǎn)不作為控制平面主機(jī)。 如果你還沒(méi)有集群,你可以通過(guò) Minikube 構(gòu)建一個(gè)你自己的集群,或者你可以使用下面任意一個(gè) Kubernetes 工具構(gòu)建:

您的 Kubernetes 服務(wù)器版本必須不低于版本 v1.21. 要獲知版本信息,請(qǐng)輸入 ?kubectl version?。

選擇一種方法 

要從工作程序訪問(wèn)工作項(xiàng),你有幾個(gè)選擇:

  1. 讀取 ?JOB_COMPLETION_INDEX ?環(huán)境變量。Job 控制器 自動(dòng)將此變量鏈接到包含完成索引的注解。
  2. 讀取包含完整索引的文件。
  3. 假設(shè)你無(wú)法修改程序,你可以使用腳本包裝它, 該腳本使用上述任意方法讀取索引并將其轉(zhuǎn)換為程序可以用作輸入的內(nèi)容。

對(duì)于此示例,假設(shè)你選擇了方法 3 并且想要運(yùn)行 rev 實(shí)用程序。 這個(gè)程序接受一個(gè)文件作為參數(shù)并按逆序打印其內(nèi)容。

rev data.txt

你將使用 busybox 容器映像中的 ?rev ?工具。

由于這只是一個(gè)例子,每個(gè) Pod 只做一小部分工作(反轉(zhuǎn)一個(gè)短字符串)。 例如,在實(shí)際工作負(fù)載中,你可能會(huì)創(chuàng)建一個(gè)表示基于場(chǎng)景數(shù)據(jù)制作 60 秒視頻的任務(wù)的 Job 。 視頻渲染 Job 中的每個(gè)工作項(xiàng)都將渲染該視頻剪輯的特定幀。 索引完成意味著 Job 中的每個(gè) Pod 都知道通過(guò)從剪輯開(kāi)始計(jì)算幀數(shù),來(lái)確定渲染和發(fā)布哪一幀。

定義索引作業(yè)

這是一個(gè)使用 ?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 控制器為所有容器設(shè)置的內(nèi)置 ?JOB_COMPLETION_INDEX ?環(huán)境變量。 Init 容器 將索引映射到一個(gè)靜態(tài)值,并將其寫(xiě)入一個(gè)文件,該文件通過(guò) emptyDir 卷 與運(yùn)行 worker 的容器共享?;蛘?,你可以 通過(guò) Downward API 定義自己的環(huán)境變量 將索引發(fā)布到容器。你還可以選擇從 包含 ConfigMap 的環(huán)境變量或文件 加載值列表。

或者也可以直接 使用 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']

執(zhí)行 Job

現(xiàn)在執(zhí)行 Job:

# 使用第一種方法(依賴于 $JOB_COMPLETION_INDEX)
kubectl apply -f https://kubernetes.io/examples/application/job/indexed-job.yaml

當(dāng)你創(chuàng)建此 Job 時(shí),控制平面會(huì)創(chuàng)建一系列 Pod,每個(gè)索引都由你指定。 ?.spec.parallelism? 的值決定了一次可以運(yùn)行多少個(gè), 而 ?.spec.completions? 決定了 Job 總共創(chuàng)建了多少個(gè) Pod。

因?yàn)?nbsp;?.spec.parallelism? 小于 ?.spec.completions?, 控制平面在啟動(dòng)更多 Pod 之前,等待部分第一批 Pod 完成。

創(chuàng)建 Job 后,稍等片刻,然后檢查進(jìn)度:

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

在此示例中,你使用每個(gè)索引的自定義值運(yùn)行 Job。 你可以檢查其中一個(gè) Pod 的輸出:

kubectl logs indexed-job-fdhq5 # 更改它以匹配來(lái)自該 Job 的 Pod 的名稱

輸出類似于:

xuq


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)