使用擴展進行平行處理

此任務示範根據通用範本執行多個 Jobs。您可以使用此方法平行處理批次工作。

在此範例中,只有三個項目:applebananacherry。範例 Jobs 透過列印字串然後暫停來處理每個項目。

請參閱在真實工作負載中使用 Jobs,以瞭解此模式如何更符合實際使用案例。

開始之前

您應該熟悉 Job 的基本、非平行使用方式。

您需要有一個 Kubernetes 叢集,並且必須設定 kubectl 命令列工具以與您的叢集通訊。建議在至少有兩個節點且未充當控制平面主機的叢集上執行本教學課程。如果您還沒有叢集,可以使用 minikube 建立一個,或者您可以使用這些 Kubernetes 練習場之一

對於基本範本,您需要命令列工具 sed

若要遵循進階範本範例,您需要安裝可運作的 Python,以及 Python 的 Jinja2 範本庫。

一旦您設定好 Python,您就可以執行以下命令來安裝 Jinja2

pip install --user jinja2

根據範本建立 Job

首先,將以下 Job 範本下載到名為 job-tmpl.yaml 的檔案中。以下是您將下載的內容

apiVersion: batch/v1
kind: Job
metadata:
  name: process-item-$ITEM
  labels:
    jobgroup: jobexample
spec:
  template:
    metadata:
      name: jobexample
      labels:
        jobgroup: jobexample
    spec:
      containers:
      - name: c
        image: busybox:1.28
        command: ["sh", "-c", "echo Processing item $ITEM && sleep 5"]
      restartPolicy: Never
# Use curl to download job-tmpl.yaml
curl -L -s -O https://k8s.io/examples/application/job/job-tmpl.yaml

您下載的檔案還不是有效的 Kubernetes manifest(manifest)。相反地,該範本是 Job 物件的 YAML 表示法,其中包含一些佔位符,需要先填寫才能使用。$ITEM 語法對於 Kubernetes 沒有意義。

從範本建立 manifests

以下 shell 片段使用 sed 將字串 $ITEM 替換為迴圈變數,並寫入名為 jobs 的暫存目錄中。立即執行此操作

# Expand the template into multiple files, one for each item to be processed.
mkdir ./jobs
for i in apple banana cherry
do
  cat job-tmpl.yaml | sed "s/\$ITEM/$i/" > ./jobs/job-$i.yaml
done

檢查是否運作

ls jobs/

輸出結果應與此類似

job-apple.yaml
job-banana.yaml
job-cherry.yaml

您可以使用任何類型的範本語言(例如:Jinja2;ERB),或編寫程式來產生 Job manifests。

從 manifests 建立 Jobs

接下來,使用一個 kubectl 命令建立所有 Jobs

kubectl create -f ./jobs

輸出結果應與此類似

job.batch/process-item-apple created
job.batch/process-item-banana created
job.batch/process-item-cherry created

現在,檢查 jobs

kubectl get jobs -l jobgroup=jobexample

輸出結果應與此類似

NAME                  COMPLETIONS   DURATION   AGE
process-item-apple    1/1           14s        22s
process-item-banana   1/1           12s        21s
process-item-cherry   1/1           12s        20s

使用 -l 選項搭配 kubectl 僅選取屬於此 jobs 群組的 Jobs(系統中可能存在其他不相關的 jobs)。

您也可以使用相同的標籤選擇器來檢查 Pods

kubectl get pods -l jobgroup=jobexample

輸出結果應與此類似

NAME                        READY     STATUS      RESTARTS   AGE
process-item-apple-kixwv    0/1       Completed   0          4m
process-item-banana-wrsf7   0/1       Completed   0          4m
process-item-cherry-dnfu9   0/1       Completed   0          4m

我們可以一次使用這個單一命令來檢查所有 jobs 的輸出

kubectl logs -f -l jobgroup=jobexample

輸出結果應為

Processing item apple
Processing item banana
Processing item cherry

清除

# Remove the Jobs you created
# Your cluster automatically cleans up their Pods
kubectl delete job -l jobgroup=jobexample

使用進階範本參數

第一個範例中,範本的每個實例都有一個參數,並且該參數也用於 Job 的名稱中。但是,名稱僅限於包含某些字元。

這個稍微複雜的範例使用 Jinja 範本語言來產生 manifests,然後從這些 manifests 產生物件,每個 Job 具有多個參數。

對於此任務的這部分,您將使用單行 Python 腳本將範本轉換為一組 manifests。

首先,複製並貼上以下 Job 物件的範本到名為 job.yaml.jinja2 的檔案中

{% set params = [{ "name": "apple", "url": "http://dbpedia.org/resource/Apple", },
                  { "name": "banana", "url": "http://dbpedia.org/resource/Banana", },
                  { "name": "cherry", "url": "http://dbpedia.org/resource/Cherry" }]
%}
{% for p in params %}
{% set name = p["name"] %}
{% set url = p["url"] %}
---
apiVersion: batch/v1
kind: Job
metadata:
  name: jobexample-{{ name }}
  labels:
    jobgroup: jobexample
spec:
  template:
    metadata:
      name: jobexample
      labels:
        jobgroup: jobexample
    spec:
      containers:
      - name: c
        image: busybox:1.28
        command: ["sh", "-c", "echo Processing URL {{ url }} && sleep 5"]
      restartPolicy: Never
{% endfor %}

上面的範本使用 Python 字典列表(第 1-4 行)為每個 Job 物件定義了兩個參數。for 迴圈為每個參數集發出一個 Job manifest(其餘行)。

此範例依賴 YAML 的一個功能。一個 YAML 檔案可以包含多個文件(在本例中為 Kubernetes manifests),以單獨一行的 --- 分隔。您可以將輸出直接通過管道傳輸到 kubectl 以建立 Jobs。

接下來,使用這個單行 Python 程式來擴展範本

alias render_template='python -c "from jinja2 import Template; import sys; print(Template(sys.stdin.read()).render());"'

使用 render_template 將參數和範本轉換為包含 Kubernetes manifests 的單個 YAML 檔案

# This requires the alias you defined earlier
cat job.yaml.jinja2 | render_template > jobs.yaml

您可以檢視 jobs.yaml 以驗證 render_template 腳本是否正常運作。

一旦您滿意 render_template 按照您的意圖運作,您可以將其輸出通過管道傳輸到 kubectl

cat job.yaml.jinja2 | render_template | kubectl apply -f -

Kubernetes 接受並執行您建立的 Jobs。

清除

# Remove the Jobs you created
# Your cluster automatically cleans up their Pods
kubectl delete job -l jobgroup=jobexample

在實際工作負載中使用 Jobs

在實際使用案例中,每個 Job 都會執行一些大量的計算,例如渲染電影的幀,或處理資料庫中的一系列行。如果您要渲染電影,您可以將 $ITEM 設定為幀編號。如果您要處理資料庫表中的行,您可以將 $ITEM 設定為表示要處理的資料庫行範圍。

在此任務中,您執行了一個命令,透過提取 Pods 的日誌來收集 Pods 的輸出。在實際使用案例中,Job 的每個 Pod 在完成之前都會將其輸出寫入持久儲存空間。您可以為每個 Job 使用 PersistentVolume,或使用外部儲存服務。例如,如果您要渲染電影的幀,請使用 HTTP 將渲染的幀數據 PUT 到 URL,每個幀使用不同的 URL。

Jobs 和 Pods 上的標籤

在您建立 Job 之後,Kubernetes 會自動新增額外的標籤,以區分一個 Job 的 Pods 與另一個 Job 的 Pods。

在本範例中,每個 Job 及其 Pod 範本都有一個標籤:jobgroup=jobexample

Kubernetes 本身不關注名為 jobgroup 的標籤。為您從範本建立的所有 Jobs 設定標籤,可以方便地一次操作所有這些 Jobs。在第一個範例中,您使用範本建立了多個 Jobs。該範本確保每個 Pod 也獲得相同的標籤,因此您可以使用單一命令檢查這些範本化 Jobs 的所有 Pods。

替代方案

如果您計劃建立大量 Job 物件,您可能會發現

  • 即使使用標籤,管理如此多的 Jobs 也很麻煩。
  • 如果您在一批次中建立許多 Jobs,您可能會對 Kubernetes 控制平面造成高負載。或者,Kubernetes API 伺服器可能會對您進行速率限制,暫時以 429 狀態拒絕您的請求。
  • 您受到 Jobs 的資源配額的限制:當您在一批次中建立大量工作時,API 伺服器會永久拒絕您的某些請求。

還有其他job 模式,您可以使用它們來處理大量工作,而無需建立非常多的 Job 物件。

您也可以考慮編寫自己的控制器來自動管理 Job 物件。

上次修改時間:2023 年 8 月 24 日下午 6:38 PST:Use code_sample shortcode instead of code shortcode (e8b136c3b3)