4.5 运行执行单个任务的pod+4.6 安排Job定期运行或在将来运行一次

4.5 运行执行单个任务的pod

到目前为止,我们只谈论了需要持续运行的pod。你会遇到只想运行完成工作后就终止任务的情况。ReplicationController、ReplicaSet和DaemonSet会持续运行任务,永远达不到完成态。这些pod中的进程在退出时会重新启动。但是在一个可完成的任务中,其进程终止后,不应该再重新启动。

4.5.1 介绍Job资源

Kubernetes通过Job资源提供了对此的支持,这与我们在本章中讨论的其他资源类似,但它允许你运行一种pod,该pod在内部进程成功结束时,不重启容器。一旦任务完成,pod就被认为处于完成状态。

在发生节点故障时,该节点上由Job管理的pod将按照ReplicaSet的pod的方式,重新安排到其他节点。如果进程本身异常退出(进程返回错误退出代码时),可以将Job配置为重新启动容器。

图4.10显示了如果一个Job所创建的pod,在最初被调度节点上异常退出后,被重新安排到一个新节点上的情况。该图还显示了托管的pod(未重新安排)和由ReplicaSet管理的pod(被重新安排)。

例如,Job对于临时任务很有用,关键是任务要以正确的方式结束。可以在未托管的pod中运行任务并等待它完成,但是如果发生节点异常或pod在执行任务时被从节点中逐出,则需要手动重新创建该任务。手动做这件事并不合理 —— 特别是如果任务需要几个小时才能完成。

这样的任务的一个例子是,如果有数据存储在某个地方,需要转换并将其导出到某个地方。你将通过运行构建在busybox镜像上的容器镜像来模拟此操作,该容器将调用sleep命令两分钟。笔者已经构建了镜像并将其推送到Docker Hub,但你可以在本书的代码档案中查看它的Dockerfile。

FROM busybox
ENTRYPOINT echo "$(date) Batch job starting"; sleep 120; echo "$(date) Finished succesfully"

4.5.2 定义Job资源

vi/vim编辑器粘贴yaml 文件会自动缩进, 粘贴前执行如下命令

:set paste

不再缩进,完美解决

按照下面的代码清单创建Job manifest。

apiVersion: batch/v1
kind: Job
metadata:
  name: batch-job
spec:
  template:
    metadata:
      labels:
        app: batch-job
    spec:
      restartPolicy: OnFailure
      containers:
      - name: main
        image: luksa/batch-job

代码清单4.11 Job的YAML定义:exporter.yaml(应为batch-job.yaml

Job是batch API组v1 API版本的一部分。YAML定义了一个Job类型的资源,它将运行luksa/batch-job镜像,该镜像调用一个运行120秒的进程,然后退出。

在一个pod的定义中,可以指定在容器中运行的进程结束时,Kubernetes会做什么。这是通过pod配置的属性restartPolicy完成的,默认为Always。Job pod不能使用默认策略,因为它们不是要无限期地运行。因此,需要明确地将重启策略设置为OnFailure或Never。此设置防止容器在完成任务时重新启动(pod被Job管理时并不是这样的)。

4.5.3 看Job运行一个pod

在使用kubectl create命令创建此作业后,应该看到它立即启动一个pod:

$ kubectl get jobs

$ kubectl get po

两分钟过后,pod将不再出现在pod列表中,工作将被标记为已完成。默认情况下,除非使用--show-all(或-a)开关,否则在列出pod时不显示已完成的pod:

$ kubectl get po -A

完成后pod未被删除的原因是允许你查阅其日志。例如:

$ kubectl logs batch-job-28qf4

pod可以被直接删除,或者在删除创建它的Job时被删除。在你删除它之前,让我们再看一下Job资源:

$ kubectl get job

作业显示已成功完成。但为什么这样的信息显示为一个数字而不是yes或true?DESIRED列表示什么意思?

4.5.4 在Job中运行多个pod实例

作业可以配置为创建多个pod实例,并以并行或串行方式运行它们。这是通过在Job配置中设置completionsparallelism 属性来完成的。

顺序运行Job pod

如果你需要一个Job运行多次,则可以将completions设为你希望作业的pod运行多少次。下面的代码清单显示了一个例子。

代码清单4.12 需要多次完成的Job:multi-completion-batch-job.yaml

apiVersion: batch/v1
kind: Job
metadata:
  name: multi-completion-batch-job # 此任务顺序运行五个pod
spec:
  completions: 5
  template:
    metadata:
      labels:
        app: batch-job
    spec:
      restartPolicy: OnFailure
      containers:
      - name: main
        image: luksa/batch-job

Job将一个接一个地运行五个pod。它最初创建一个pod,当pod的容器运行完成时,它创建第二个pod,以此类推,直到五个pod成功完成。如果其中一个pod发生故障,工作会创建一个新的pod,所以Job总共可以创建五个以上的pod。

并行运行Job pod

不必一个接一个地运行单个Job pod,也可以让该Job并行运行多个pod。可以通过parallelism Job配置属性,指定允许多少个pod并行执行,如下面的代码清单所示。

代码清单4.13 并行运行Job pod:multi-completion-parallel-batch-job.yaml

apiVersion: batch/v1
kind: Job
metadata:
  name: multi-completion-batch-job
spec:
  completions: 5
  parallelism: 2
  template:
    metadata:
      labels:
        app: batch-job
    spec:
      restartPolicy: OnFailure
      containers:
      - name: main
        image: luksa/batch-job

通过将parallelism设置为2,Job创建两个pod并行运行它们:

$ kubectl get po

只要其中一个pod完成任务,工作将运行下一个pod,直到五个pod都成功完成任务。

Job的缩放

你甚至可以在Job运行时更改Job的parallelism属性。这与缩放ReplicaSet或ReplicationController类似,可以使用kubectl scale命令完成:

$ kubectl scale job multi-completion-batch-job --replicas 3

由于你将parallelism从2增加到3,另一个pod立即启动,因此现在有三个pod在运行。

4.5.5 限制Job pod完成任务的时间

关于Job我们需要讨论最后一件事。Job要等待一个pod多久来完成任务?如果pod卡住并且根本无法完成(或者无法足够快完成),该怎么办?

通过在pod配置中设置activeDeadlineSeconds属性,可以限制pod的时间。如果pod运行时间超过此时间,系统将尝试终止pod,并将Job标记为失败。

注意 通过指定Job manifest中的spec.backoffLimit字段,可以配置Job在被标记为失败之前可以重试的次数。如果你没有明确指定它,则默认为6。

Job资源在创建时会立即运行pod。但是许多批处理任务需要在特定的时间运行,或者在指定的时间间隔内重复运行。在Linux和类UNIX操作系统中,这些任务通常被称为cron任务。Kubernetes也支持这种任务。

Kubernetes中的cron任务通过创建CronJob资源进行配置。运行任务的时间表以知名的cron格式指定,所以如果你熟悉常规cron任务,你将在几秒钟内了解Kubernetes的CronJob。

在配置的时间,Kubernetes将根据在CronJob对象中配置的Job模板创建Job资源。创建Job资源时,将根据任务的pod模板创建并启动一个或多个pod副本,如你在前一部分中所了解的那样。

让我们来看看如何创建CronJob。

4.6 安排Job定期运行或在将来运行一次

4.6.1 创建一个CronJob

想象一下,你需要每15分钟运行一次前一个示例中的批处理任务。为此,请使用以下规范创建一个CronJob资源。

代码清单4.14 CronJob资源的YAML:cronjob.yaml

apiVersion: batch/v1
kind: CronJob
metadata:
  name: hello
spec:
  schedule: "*/1 * * * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: hello
            image: busybox
            imagePullPolicy: IfNotPresent
            command:
            - /bin/sh
            - -c
            - date; echo Hello from the Kubernetes cluster
          restartPolicy: OnFailure

正如你所看到的,它不是太复杂。你已经指定了创建Job对象的时间表和模板。

配置时间表安排

如果你不熟悉cron时间表格式,你会在网上找到很棒的教程和解释,但作为一个快速介绍,时间表从左到右包含以下五个条目:

  • 分钟
  • 小时
  • 每月中的第几天
  • 星期几

在该示例中,你希望每15分钟运行一次任务因此schedule字段的值应该是 0,15,30,45**** 这意味着每小时的0、15、30和45分钟(第一个星号),每月的每一天(第二个星号),每月(第三个星号)和每周的每一天(第四个星号)。

相反,如果你希望每隔30分钟运行一次,但仅在每月的第一天运行,则应将计划设置为0,30 * 1 * * ,并且如果你希望它每个星期天的3AM运行,将它设置为0 3 * * 0 (最后一个零代表星期天)。

配置Job模板

CronJob通过CronJob规范中配置的jobTemplate属性创建任务资源,更多有关如何配置它的信息,请参阅4.5节。

4.6.2 了解计划任务的运行方式

使用 CronJob 运行自动化任务 一文会为你详细讲解此例。

Cron 时间表语法

# ┌───────────── 分钟 (0 - 59)
# │ ┌───────────── 小时 (0 - 23)
# │ │ ┌───────────── 月的某天 (1 - 31)
# │ │ │ ┌───────────── 月份 (1 - 12)
# │ │ │ │ ┌───────────── 周的某天 (0 - 6) (周日到周一;在某些系统上,7 也是星期日)
# │ │ │ │ │                                   
# │ │ │ │ │
# │ │ │ │ │
# * * * * *
输入 描述 相当于
@yearly (or @annually) 每年 1 月 1 日的午夜运行一次 0 0 1 1 *
@monthly 每月第一天的午夜运行一次 0 0 1 * *
@weekly 每周的周日午夜运行一次 0 0 * * 0
@daily (or @midnight) 每天午夜运行一次 0 0 * * *
@hourly 每小时的开始一次 0 * * * *

例如,下面这行指出必须在每个星期五的午夜以及每个月 13 号的午夜开始任务:

0 0 13 * 5

要生成 CronJob 时间表表达式,你还可以使用 crontab.guru 之类的 Web 工具。

在计划的时间内,CronJob资源会创建Job资源,然后Job创建pod。

可能发生Job或pod创建并运行得相对较晚的情况。你可能对这项工作有很高的要求,任务开始不能落后于预定的时间过多。在这种情况下,可以通过指定CronJob规范中的startingDeadlineSeconds字段来指定截止日期,如下面的代码清单所示。

代码清单4.15 为CronJob指定一个startingDeadlineSeconds

[图片上传失败...(image-952b09-1626483188040)]

在代码清单4.15的例子中,工作运行的时间应该是10:30:00。如果因为任何原因10:30:15不启动,任务将不会运行,并将显示为Failed。

在正常情况下,CronJob总是为计划中配置的每个执行创建一个Job,但可能会同时创建两个Job,或者根本没有创建。为了解决第一个问题,你的任务应该是幂等的(多次而不是一次运行不会得到不希望的结果)。对于第二个问题,请确保下一个任务运行完成本应该由上一次的(错过的)运行完成的任何工作。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,874评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,102评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,676评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,911评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,937评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,935评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,860评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,660评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,113评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,363评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,506评论 1 346
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,238评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,861评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,486评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,674评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,513评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,426评论 2 352