这篇文章已超过一年。较旧的文章可能包含过时的内容。请检查页面中的信息自发布以来是否已变得不正确。

引入暂停的作业

作业(Jobs)是 Kubernetes API 的关键组成部分。虽然其他类型的工作负载(如部署(Deployments)副本集(ReplicaSets)有状态集(StatefulSets)守护进程集(DaemonSets))解决了需要 Pod 永久运行的用例,但当 Pod 需要运行至完成时,作业非常有用。作业通常用于并行批量处理,可用于各种应用程序,从视频渲染和数据库维护到发送批量电子邮件和科学计算。

虽然并行度以及作业完成的条件是可配置的,但 Kubernetes API 缺少暂停和恢复作业的功能。当集群资源有限且需要执行优先级更高的作业来替代另一个作业时,通常需要这样做。删除优先级较低的作业是一种糟糕的解决方法,因为与作业关联的 Pod 完成历史记录和其他指标将会丢失。

随着最近发布的 Kubernetes 1.21 版本,您可以通过更新作业的 spec 来暂停作业。此功能目前处于 alpha 状态,需要您在 API 服务器控制器管理器 上启用 SuspendJob 功能门控 才能使用它。

API 变更

我们在作业的 .spec 中引入了一个新的布尔字段 suspend。假设我创建了以下作业:

apiVersion: batch/v1
kind: Job
metadata:
  name: my-job
spec:
  suspend: true
  parallelism: 2
  completions: 10
  template:
    spec:
      containers:
      - name: my-container
        image: busybox
        command: ["sleep", "5"]
      restartPolicy: Never

默认情况下,作业不会被暂停,因此我显式地将上述作业清单的 .spec 中的 suspend 字段设置为 _true_。在上面的示例中,作业控制器将不会创建 Pod,直到我准备好启动作业,这可以通过将 suspend 更新为 false 来实现。

作为另一个示例,考虑一个创建时省略了 suspend 字段的作业。作业控制器将很乐意创建 Pod 以实现作业完成。但是,在作业完成之前,如果我通过作业更新显式地将该字段设置为 true,则作业控制器将终止所有正在运行的活动 Pod,并无限期地等待该标志翻转回 false。通常,Pod 终止是通过向 Pod 中的所有容器进程发送 SIGTERM 信号来完成的;将遵守 Pod spec 中定义的优雅终止期。以这种方式终止的 Pod 不会被作业控制器视为失败。

重要的是要理解,过去成功的和失败的 Pod 在您暂停作业后将继续存在。也就是说,一旦您恢复作业,它们将计入作业完成。您可以通过在暂停前后查看作业的状态来验证这一点。

阅读文档以全面了解这项新功能。

这在哪里有用?

假设我是大型集群的运营商。我有很多用户向集群提交作业,但并非所有作业都是平等的 — 有些作业比其他作业更重要。集群资源也不是无限的,因此所有用户都必须共享资源。如果所有作业都在暂停状态下创建并放入等待队列,我可以通过按正确的顺序恢复作业来实现基于优先级的作业调度。

作为另一个激励性的用例,考虑一个云提供商,其计算资源在晚上比早上便宜。如果我有一个需要多天才能完成的长时间运行的作业,能够每天早上暂停该作业并在晚上恢复该作业可以降低成本。

由于此字段是作业规范的一部分,因此定时作业(CronJobs)也会自动免费获得此功能。

参考和后续步骤

如果您有兴趣深入了解此功能背后的原理以及我们所做的决策,请考虑阅读增强提案。有关暂停和恢复作业的更多详细信息,请参见 作业的文档。

如前所述,此功能目前处于 alpha 状态,仅当您通过 SuspendJob 功能门控 显式选择加入时才可用。如果您对这项功能感兴趣,请考虑在您的集群中测试暂停的作业并提供反馈。您可以在 GitHub 上讨论此增强功能。SIG Apps 社区也 定期开会,可以通过 Slack 或邮件列表联系。如果没有对 API 进行任何意外的更改,我们打算在 Kubernetes 1.22 中将此功能升级到 beta 版,以便默认情况下可以使用此功能。