Tasks

Step-by-step instructions for performing operations with Kubernetes.

Edit This Page

使用扩展并行处理

示例:使用扩展模板创建多个 Job 对象

在本示例中,我们将使用同一个模板创建多个 Kubernetes job。这可能需要您先熟悉下如何使用普通的非并行的 Job

基本扩展模板

首先,下载下面的名为 job.yaml 的 Job 模板文件。

job.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
        command: ["sh", "-c", "echo Processing item $ITEM && sleep 5"]
      restartPolicy: Never

pod 的模板 不同, job 模板不是 Kubernetes API 类型。 Job 对象的 yaml 表示,这里面有很多占位符,必须填充后才能使用。$ITEM 语法对于 Kubernetes 来说没有意义。

在这个例子中,容器只做了一件事,就是 echo 一个字符串然后休眠一会儿。在实际使用场景下,容器通常是处理一些实质的计算,例如渲染电影的画面帧,或者是处理数据库中的一系列行。“$ITEM” 参数将指定为,例如帧号或行范围。

该 Job 和其 Pod 的模板具有标签:jobgroup-jobexample。这个标签对于系统没有什么特别之处。使用标签可以很方便地一次性操作一组中的所有 Job。我们还在 pod 模板上放置了相同的标签,以便我们可以使用单个命令检查这些 Job 的所有 Pod。Job 创建好了之后,系统将添加更多的标签,将一个作业的 Pod 与另一个作业的 Pod 区分开来。请注意,jobgroup 标签的 key 对于 Kubernetes 来说并没有什么特别的意义。您可以选择自己的标签方案。

# Expand files into a temporary directory
mkdir ./jobs
for i in apple banana cherry
do
  cat job.yaml.txt | sed "s/\$ITEM/$i/" > ./jobs/job-$i.yaml
done

查看它是否能正常工作:

$ ls jobs/
job-apple.yaml
job-banana.yaml
job-cherry.yaml

在此,我们使用 sed 命令和循环变量替换文件中的 $ITEM 。你可以使用任何一种模板语言(jinja2、erb)或编写程序来生成 Job 对象。

接下来,使用 kubectl 命令创建所有的 job。

$ kubectl create -f ./jobs
job "process-item-apple" created
job "process-item-banana" created
job "process-item-cherry" created

现在,检查创建的 Job:

$ kubectl get jobs -l jobgroup=jobexample
JOB                   CONTAINER(S)   IMAGE(S)   SELECTOR                               SUCCESSFUL
process-item-apple    c              busybox    app in (jobexample),item in (apple)    1
process-item-banana   c              busybox    app in (jobexample),item in (banana)   1
process-item-cherry   c              busybox    app in (jobexample),item in (cherry)   1

我们使用 -l 选项来选择属于该 job 组的所有 job(因为系统中可能有很多其他的我们不想看到的 job)。

我们可以使用相同的标签选择器来查看 pod:

$ kubectl get pods -l jobgroup=jobexample --show-all
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

当前还没有办法直接使用一条命令一次性查看所有的 job 的输出,但是循环查看所有的 pod 的输出还是十分简单的:

$ for p in $(kubectl get pods -l jobgroup=jobexample --show-all -o name)
do
  kubectl logs $p
done
Processing item apple
Processing item banana
Processing item cherry

多参数模版

在第一个例子中,每个模板的实例都有一个参数,那个参数也会作为标签来使用。但是 label 的 key 受 可以包含的字符 限制。

这个稍微复杂的例子使用 jinja2 模板语言来生成我们的对象。

我们将使用一行 python 脚本将模板转换为文件。

首先,复制粘贴下面的 Job 对象模板到 job.yaml.jinja2 文件中。

{%- set params = [{ "name": "apple", "url": "http://www.orangepippin.com/apples", },
                  { "name": "banana", "url": "https://en.wikipedia.org/wiki/Banana", },
                  { "name": "raspberry", "url": "https://www.raspberrypi.org/" }]
%}
{%- 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
        command: ["sh", "-c", "echo Processing URL {{ url }} && sleep 5"]
      restartPolicy: Never
---
{%- endfor %}

上面的模版中为每个 job 对象都定义了一个参数,这个参数使用的是 python dicst(第1-4行)。 然后使用一个 for 循环为每个参数集(接下来一行)产生一个 job yaml 对象。 我们利用了多个 yaml 文档可以使用 --- 分隔符连接的特性(倒数第二行)。我们可以其管道输出到 kubectl 来创建对象。

您需要使用 jinja2 包,如果没有话可以该命令安装:pip install --user jinja2

现在,使用这一行 python 程序来扩展模版:

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

输出可以保存到文件中,例如:

cat job.yaml.jinja2 | render_template > jobs.yaml

或者直接发送给 kubectl,例如:

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

备选方案

如果您有大量的 job 对象,你可能会发现:

在这种情况下,您可以考虑其他 job 模式

Analytics

Create an Issue Edit this Page