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

Kubernetes 1.21:CronJob 达到 GA

在 Kubernetes v1.21 中,CronJob 资源已达到正式发布 (GA) 状态。自 Kubernetes v1.19 以来,通过实施新的控制器,我们还大幅提高了 CronJob 的性能。

在 Kubernetes v1.20 中,我们推出了修订后的 CronJob v2 控制器,最初作为 alpha 功能。Kubernetes 1.21 默认使用较新的控制器,并且 CronJob 资源本身现在是 GA (组版本:batch/v1)。

在本文中,我们将带您了解此项新开发背后的驱动力,简要介绍核心 Kubernetes 的控制器设计,并概述您将从改进的控制器中获得什么。

提升 API 的背后驱动力是 Kubernetes 的政策选择,即确保 API 超出 beta 阶段。该政策旨在防止 API 停留在“永久 beta”状态。多年来,旧的 CronJob 控制器实现收到了来自社区的健康反馈,并报告了几个广为人知的问题

如果要将 CronJob 的 beta API 作为 GA 支持,则现有的控制器代码将需要进行大量返工。相反,SIG Apps 社区决定引入一个新的控制器,并逐步替换旧的控制器。

控制器如何工作?

Kubernetes 控制器是控制循环,用于监视集群中资源的状态,然后在需要时进行或请求更改。每个控制器都尝试使当前集群状态的一部分更接近期望的状态。

v1 CronJob 控制器的工作方式是对集群中的所有 CronJob 对象执行定期轮询和扫描,以便对它们执行操作。这是一个单工作器实现,每 10 秒获取所有 CronJob,迭代每个 CronJob,并将其同步到所需的状态。这是大约 5 年前控制器最初编写时的默认方式。事后看来,我们当然可以说这种方法可能会在大规模下使 API 服务器过载。

如今,kubernetes 中的每个核心控制器都必须遵循编写控制器中描述的指南。在许多细节中,该文档规定使用共享信息器来“接收特定资源的添加、更新和删除的通知”。在发生任何此类事件时,相关对象将被放入队列中。工作器从队列中提取项并一次处理一个。这种方法可确保一致性和可扩展性。

下图显示了信息从 kubernetes API 服务器通过共享信息器和队列到控制器的主要部分(即负责执行核心功能的协调循环)的流程。

Controller flowchart

CronJob 控制器 V2 使用实现 DelayingInterface 的队列来处理调度方面。此队列允许在特定的时间间隔后处理元素。每次 CronJob 或其相关 Job 发生更改时,表示 CronJob 的密钥都会被推送到队列中。主处理程序弹出密钥,处理 CronJob,并在完成后将密钥推回队列以进行下一次计划的时间间隔。这立即是一个性能更高的实现,因为它不再需要线性扫描所有 CronJob。最重要的是,可以通过增加并行处理 CronJob 的工作器数量来扩展此控制器。

新控制器的性能影响

为了测试两个控制器的性能差异,使用了具有 128 GiB RAM 和 64 个 vCPU 的 VM 实例来设置单节点 Kubernetes 集群。最初,创建了一个示例工作负载,其中包含 20 个计划每分钟运行的 CronJob 实例和 2100 个计划每 20 小时运行的 CronJob。此外,在接下来的几分钟内,我们添加了 1000 个计划每 20 小时运行的 CronJob,直到我们达到总共 5120 个 CronJob。

Visualization of performance

我们观察到,每增加 1000 个 CronJob,旧控制器就需要多花费大约 90 到 120 秒的实际时间才能在每个周期安排 20 个 Job。也就是说,在 5120 个 CronJob 时,旧控制器大约需要 9 分钟才能创建 20 个 Job。因此,在每个周期中,大约错过了 8 个计划。新的控制器通过上述架构更改实现,即使我们创建了另外一批 1000 个 CronJob(总共达到 6120 个),也可以毫无延迟地创建 20 个 Job。

最后,新的控制器公开了一个直方图指标 cronjob_controller_cronjob_job_creation_skew_duration_seconds,该指标有助于监视 CronJob 计划运行的时间与实际创建 Job 的时间之间的差异。

希望以上描述足以支持您遵循 Kubernetes 项目中设置的指南和标准,即使对于您自己的控制器也是如此。如前所述,从 Kubernetes v1.21 开始,默认启用新的控制器;如果您想在之前的版本 (1.20) 中查看,可以为 kube-controller-manager 启用 CronJobControllerV2 特性门--feature-gate="CronJobControllerV2=true"