Kubernetes v1.34: Job 的 Pod 替换策略进入 GA 阶段
在 Kubernetes v1.34 中,**Pod 替换策略(Pod replacement policy)** 特性已达到正式发布(GA)阶段。这篇博文将介绍 Pod 替换策略特性以及如何在你的 Job 中使用它。
关于 Pod 替换策略
默认情况下,Job 控制器会在 Pod 失败或开始终止(当它们具有删除时间戳时)时立即重新创建 Pod。
因此,在某些 Pod 正在终止时,一个 Job 的正在运行的 Pod 总数可能会暂时超过指定的并行度。对于 Indexed Job,这甚至可能意味着多个 Pod 同时为同一个索引运行。
这种行为对许多工作负载来说没有问题,但在某些情况下可能会导致问题。
例如,像 TensorFlow 和 JAX 这样流行的机器学习框架,期望每个工作程序索引(worker index)只有一个 Pod。如果两个 Pod 同时运行,你可能会遇到类似下面的错误:
/job:worker/task:4: Duplicate task registration with task_name=/job:worker/replica:0/task:4
此外,在旧 Pod 完全终止之前启动替换 Pod 可能会导致:
- 由于节点仍被占用,kube-scheduler 会出现调度延迟。
- 为了容纳替换的 Pod,集群会进行不必要的扩容。
- 像 Kueue 这样的工作负载编排器会暂时绕过配额检查。
有了 Pod 替换策略,Kubernetes 让你能够控制控制平面何时替换正在终止的 Pod,从而帮助你避免这些问题。
Pod 替换策略的工作原理
这项增强意味着 Kubernetes 中的 Job 有一个可选字段 .spec.podReplacementPolicy
。
你可以选择以下两种策略之一:
TerminatingOrFailed
(默认):一旦 Pod 开始终止就替换它们。Failed
:仅在 Pod 完全终止并转换到Failed
阶段后才替换它们。
将策略设置为 Failed
可以确保只有在前一个 Pod 完全终止后才会创建新的 Pod。
对于具有 Pod 失效策略(Pod Failure Policy)的 Job,默认的 podReplacementPolicy
是 Failed
,并且不允许其他值。要了解更多关于 Job 的 Pod 失效策略的信息,请参阅Pod 失效策略。
你可以通过检查 Job 的 .status.terminating
字段来查看当前有多少 Pod 正在终止:
kubectl get job myjob -o=jsonpath='{.status.terminating}'
示例
下面是一个 Job 示例,它并行执行一个任务两次(spec.completions: 2
),并行度为 2(spec.parallelism: 2
),并且仅在 Pod 完全终止后才替换它们(spec.podReplacementPolicy: Failed
):
apiVersion: batch/v1
kind: Job
metadata:
name: example-job
spec:
completions: 2
parallelism: 2
podReplacementPolicy: Failed
template:
spec:
restartPolicy: Never
containers:
- name: worker
image: your-image
如果 Pod 收到 SIGTERM 信号(删除、驱逐、抢占...),它将开始终止。当容器优雅地处理终止时,清理工作可能需要一些时间。
当 Job 启动时,我们会看到两个 Pod 正在运行:
kubectl get pods
NAME READY STATUS RESTARTS AGE
example-job-qr8kf 1/1 Running 0 2s
example-job-stvb4 1/1 Running 0 2s
让我们删除其中一个 Pod(example-job-qr8kf
)。
使用 TerminatingOrFailed
策略时,一旦一个 Pod(example-job-qr8kf
)开始终止,Job 控制器会立即创建一个新的 Pod(example-job-b59zk
)来替换它。
kubectl get pods
NAME READY STATUS RESTARTS AGE
example-job-b59zk 1/1 Running 0 1s
example-job-qr8kf 1/1 Terminating 0 17s
example-job-stvb4 1/1 Running 0 17s
使用 Failed
策略时,当旧 Pod(example-job-qr8kf
)正在终止时,不会创建新的 Pod(example-job-b59zk
)。
kubectl get pods
NAME READY STATUS RESTARTS AGE
example-job-qr8kf 1/1 Terminating 0 17s
example-job-stvb4 1/1 Running 0 17s
当正在终止的 Pod 完全转换到 Failed
阶段时,才会创建一个新的 Pod:
kubectl get pods
NAME READY STATUS RESTARTS AGE
example-job-b59zk 1/1 Running 0 1s
example-job-stvb4 1/1 Running 0 25s
如何了解更多?
- 阅读用户文档中关于Pod 替换策略、按索引的回退限制和Pod 失效策略的部分。
- 阅读 KEP(Kubernetes Enhancement Proposals)文档:Pod 替换策略、按索引的回退限制和Pod 失效策略。
致谢
与任何 Kubernetes 特性一样,许多人都为完成这项工作做出了贡献,从测试、提交错误到代码审查。
在这个特性经过 2 年的发展进入稳定阶段之际,我们想感谢以下人员:
- Kevin Hannon - 编写了 KEP 和初始实现。
- Michał Woźniak - 提供了指导、辅导和审查。
- Aldo Culquicondor - 提供了指导、辅导和审查。
- Maciej Szulik - 提供了指导、辅导和审查。
- Dejan Zele Pejchev - 接手了该特性,并将其从 Alpha 阶段推进到 Beta 阶段,最终达到 GA 阶段。
参与其中
这项工作由 Kubernetes 批处理工作组(batch working group)赞助,并与 SIG Apps 社区密切合作。
如果你有兴趣在该领域开发新功能,我们建议你订阅我们的 Slack 频道并参加定期的社区会议。