Kubernetes 1.31:Job 的 Pod 失败策略达到 GA
本文介绍了 Pod 故障策略 (Pod failure policy),该策略在 Kubernetes 1.31 中进入稳定版,以及如何在 Job 中使用它。
关于 Pod 故障策略
在 Kubernetes 上运行工作负载时,Pod 可能由于各种原因而失败。理想情况下,像 Job 这样的工作负载应该能够忽略瞬时、可重试的故障,并继续运行直至完成。
为了允许这些瞬时故障,Kubernetes Job 包含了 backoffLimit
字段,该字段允许你指定在 Job 执行期间愿意容忍的 Pod 故障次数。但是,如果为 backoffLimit
字段设置较大的值并仅依赖此字段,你可能会注意到运营成本不必要的增加,因为 Pod 会过度重启直到达到 backoffLimit。
当在大规模 Job 中运行成千上万个跨越成千上万个节点的长期运行 Pod 时,这会变得尤为棘手。
Pod 故障策略扩展了 backoff limit 机制,可以通过以下方式帮助你降低成本:
- 让你在发生不可重试的 Pod 故障时立即失败 Job。
- 允许你忽略可重试错误,而无需增加
backoffLimit
字段。
例如,你可以通过忽略由优雅节点关机 (graceful node shutdown) 导致的 Pod 故障,使用 Pod 故障策略在更经济的 Spot 实例上运行工作负载。
该策略允许你根据失败 Pod 的容器退出码或 Pod Conditions 来区分可重试和不可重试的 Pod 故障。
工作原理
你在 Job 的 Spec 中指定 Pod 故障策略,它表示为一个规则列表。
对于每条规则,你根据以下属性之一定义 匹配要求:
- 容器退出码:
onExitCodes
属性。 - Pod Conditions:
onPodConditions
属性。
此外,对于每条规则,当 Pod 匹配该规则时,你指定以下操作之一:
Ignore
:不将此故障计入backoffLimit
或backoffLimitPerIndex
。FailJob
:使整个 Job 失败并终止所有正在运行的 Pod。FailIndex
:使与失败 Pod 对应的索引失败。此操作与基于索引的重试限制 (Backoff limit per index) 特性配合使用。Count
:将此故障计入backoffLimit
或backoffLimitPerIndex
。这是默认行为。
当运行中的 Job 发生 Pod 故障时,Kubernetes 会按照指定的顺序将失败 Pod 的状态与 Pod 故障策略规则列表进行匹配,并对第一个匹配的规则执行相应的操作。
注意,在指定 Pod 故障策略时,你还必须将 Job 的 Pod 模板中的 restartPolicy
设置为 Never
。这可以防止 kubelet 和 Job 控制器在计算 Pod 故障时出现竞态条件。
Kubernetes 发起的 Pod 中断
为了允许 Pod 故障策略规则匹配由 Kubernetes 发起的中断引起的故障,此特性引入了 DisruptionTarget
Pod Condition。
Kubernetes 会将此 Condition 添加到任何 Pod,无论其是否由 Job 控制器管理,只要该 Pod 因可重试的中断场景 (disruption scenario) 而失败。DisruptionTarget
Condition 包含以下对应于这些中断场景的原因之一:
PreemptionByKubeScheduler
:由kube-scheduler
为容纳更高优先级的 Pod 而进行的抢占 (Preemption)。DeletionByTaintManager
- 由于 Pod 不容忍某个NoExecute
污点 (taint),Pod 将由kube-controller-manager
删除。EvictionByEvictionAPI
- Pod 将由API 发起的驱逐 (API-initiated eviction) 删除。DeletionByPodGC
- Pod 绑定到一个已不存在的节点,将由Pod 垃圾收集 (Pod garbage collection) 删除。TerminationByKubelet
- Pod 由优雅节点关机 (graceful node shutdown)、节点压力驱逐 (node pressure eviction) 或针对系统关键 Pods (system critical pods) 的抢占终止。
在所有其他中断场景中,例如由于超出Pod 容器限制 (Pod container limits) 导致的驱逐,Pod 不会收到 DisruptionTarget
Condition,因为这些中断很可能是由 Pod 自身引起的,重试后仍会再次发生。
示例
下面的 Pod 故障策略代码片段展示了一个用例:
podFailurePolicy:
rules:
- action: Ignore
onPodConditions:
- type: DisruptionTarget
- action: FailJob
onPodConditions:
- type: ConfigIssue
- action: FailJob
onExitCodes:
operator: In
values: [ 42 ]
在此示例中,Pod 故障策略执行以下操作:
- 忽略任何带有内置
DisruptionTarget
Condition 的失败 Pods。这些 Pod 不计入 Job 的 backoff limit。 - 如果任何失败 Pod 带有用户提供的自定义
ConfigIssue
Condition(由自定义控制器或 webhook 添加),则 Job 失败。 - 如果任何容器以退出码 42 退出,则 Job 失败。
- 将所有其他 Pod 故障计入默认的
backoffLimit
(如果使用backoffLimitPerIndex
则计入该值)。
了解更多
- 有关使用 Pod 故障策略的实践指南,请参阅使用 Pod 故障策略处理可重试和不可重试的 Pod 故障
- 阅读Pod 故障策略和基于索引的重试限制 (Backoff limit per index) 的文档
- 阅读Pod 中断 Conditions 的文档
- 阅读Pod 故障策略的 KEP
相关工作
基于 Pod 故障策略引入的概念,以下附加工作正在进行中:
- JobSet 集成:可配置故障策略 API
- Pod 故障策略扩展,以添加更细粒度的故障原因
- 通过 JobSet 在Kubeflow Training v2 中支持 Pod 故障策略
- 提案:中断的 Pod 应该从 Endpoints 中移除
参与其中
这项工作由批处理工作组 (batch working group) 赞助,并与 SIG Apps、SIG Node 和 SIG Scheduling 社区密切协作完成。
如果您有兴趣在该领域参与新特性开发,我们建议您订阅我们的 Slack 频道并参加定期的社区会议。
致谢
我要感谢多年来参与此项目的所有人——这是一段旅程,也是社区共同努力的结果!下面的列表是我尽最大努力记住和感谢那些做出贡献的人。谢谢你们!
- Aldo Culquicondor:在此过程中提供的指导和评审
- Jordan Liggitt:KEP 和 API 评审
- David Eads:API 评审
- Maciej Szulik:从 SIG Apps 视角进行的 KEP 评审
- Clayton Coleman:提供的指导和 SIG Node 评审
- Sergey Kanzhelev:从 SIG Node 视角进行的 KEP 评审
- Dawn Chen:从 SIG Node 视角进行的 KEP 评审
- Daniel Smith:从 SIG API machinery 视角进行的评审
- Antoine Pelisse:从 SIG API machinery 视角进行的评审
- John Belamaric:PRR 评审
- Filip Křepinský:从 SIG Apps 视角进行的全面评审和 bug 修复
- David Porter:从 SIG Node 视角进行的全面评审
- Jensen Lo:早期的需求讨论、测试和问题报告
- Daniel Vega-Myhre:推进 JobSet 集成和问题报告
- Abdullah Gharaibeh:早期的设计讨论和指导
- Antonio Ojea:测试评审
- Yuki Iwai:评审和协调密切相关的 Job 特性实现
- Kevin Hannon:评审和协调密切相关的 Job 特性实现
- Tim Bannister:文档评审
- Shannon Kularathna:文档评审
- Paola Cortés:文档评审