中文内容
Kubernetes v1.35:通过 Pod 原地重启实现新的效率水平
Kubernetes 1.35 版本引入了一项强大的新功能,提供了一个备受期待的能力:触发 Pod 的完整原地重启。该功能名为 Restart All Containers(在 1.35 中为 alpha),与删除并重新创建整个 Pod 这种资源密集型方式相比,它提供了一种更高效的方式来重置 Pod 状态。该功能对 AI/ML 工作负载尤其有用,使应用开发者能够专注于核心训练逻辑,同时将复杂的故障处理和恢复机制交给 sidecar 与声明式 Kubernetes 配置。借助 RestartAllContainers 以及其他计划中的增强功能,Kubernetes 将继续增加构建模块,用于创建面向 AI/ML 工作负载的最灵活、稳健且高效的平台。
通过启用 RestartAllContainersOnContainerExits feature gate,即可使用这项新功能。这个 alpha 特性扩展了 Container Restart Rules 功能,后者已在 Kubernetes 1.35 中升至 beta。
问题:当单个容器重启不够,而重建 Pod 成本又过高时
Kubernetes 长期以来一直支持 Pod 级别的重启策略(restartPolicy),最近也支持了单个容器级别的重启策略。这些策略非常适合处理单个、隔离进程中的崩溃。然而,许多现代应用具有更复杂的容器间依赖关系。例如:
- 一个 init container 通过挂载卷或生成配置文件来准备环境。如果主应用容器破坏了这个环境,仅重启该容器是不够的。整个初始化过程需要再次运行。
- 一个 watcher sidecar 监控系统健康状况。如果它检测到不可恢复但可重试的错误状态,就必须从干净状态触发主应用容器重启。
- 一个管理远程资源的 sidecar 发生故障。即使该 sidecar 自行重启,主容器也可能因尝试访问过期或损坏的连接而卡住。
在所有这些情况下,期望的操作不是重启单个容器,而是重启所有容器。此前,实现这一点的唯一方式是删除 Pod,并让控制器(如 Job 或 ReplicaSet)创建一个新的 Pod。这个过程缓慢且成本高,涉及调度器、节点资源分配,以及网络和存储的重新初始化。
在处理大规模 AI/ML 工作负载(>= 1,000 个节点,且每个节点一个 Pod)时,这种低效会进一步恶化。对于这些同步工作负载,一个常见需求是:当发生故障(例如节点崩溃)时,即使其他所有 Pod 未直接受到故障影响,也必须重新创建集群中的所有 Pod,以便在训练恢复前重置状态。同时删除、创建和调度数千个 Pod 会造成巨大瓶颈。据估计,这类故障带来的额外开销可能导致每月浪费 100,000 美元的资源。
为 AI/ML 训练任务处理这些故障,需要在训练框架和 Kubernetes 之间进行复杂集成,而这些集成往往脆弱且繁琐。该功能引入了一种 Kubernetes 原生解决方案,提升系统稳健性,并使应用开发者能够专注于核心训练逻辑。
原地重启 Pod 的另一个重要好处是,让 Pod 保持在其已分配的节点上,可以实现进一步优化。例如,可以实现与特定 Pod 身份绑定的节点级缓存;如果 Pod 被不必要地重新创建到不同节点上,这一点就无法实现。
介绍 RestartAllContainers 操作
为解决这一问题,Kubernetes v1.35 在容器重启规则中新增了一个操作:RestartAllContainers。当某个容器以匹配该操作规则的方式退出时,kubelet 会发起一次快速的 Pod 原地重启。
这种原地重启非常高效,因为它保留了 Pod 最重要的资源:
- Pod 的 UID、IP 地址和网络命名空间。
- Pod 的沙箱以及任何已附加设备。
- 所有卷,包括 emptyDir 以及来自 PVC 的挂载卷。
在终止所有正在运行的容器后,Pod 的启动序列会从最开始重新执行。这意味着所有 init container 会按顺序再次运行,然后是 sidecar 和常规容器,从而确保在一个已知良好的环境中完全重新开始。除 ephemeral container(会被终止)外,所有其他容器——包括此前已成功或失败的容器——都将重启,无论其各自的重启策略如何。
使用场景
1. 面向 ML/批处理任务的高效重启
对于 ML 训练任务,在发生故障时重新调度一个 worker Pod 是一项成本高昂的操作,会浪费宝贵的计算资源。在一个 1,000 节点的训练集群上,重新调度开销每月可能浪费超过 100,000 美元的计算资源。
通过 RestartAllContainers 操作,可以启用一种更快速的混合恢复策略来解决这一问题:仅重新创建“异常”Pod(例如位于不健康节点上的 Pod),同时对其余健康 Pod 触发 RestartAllContainers。基准测试显示,这会将恢复开销从数分钟降低到几秒钟。
通过原地重启,watcher sidecar 可以监控主训练进程。如果遇到特定的可重试错误,watcher 可以使用指定退出码退出,以触发 worker Pod 的快速重置,使其无需 Job 控制器介入即可从最近的 checkpoint 重新启动。Kubernetes 现在原生支持这种能力。
可在 KEP-467 JobSet in-place restart 中阅读有关未来开发和 JobSet 功能的更多详细信息。
apiVersion: v1
kind: Pod
metadata:
name: ml-worker-pod
spec:
restartPolicy: Never
initContainers:
# This init container will re-run on every in-place restart
- name: setup-environment
image: my-repo/setup-worker:1.0
- name: watcher-sidecar
image: my-repo/watcher:1.0
restartPolicy: Always
restartPolicyRules:
- action: RestartAllContainers
exitCodes:
operator: In
# A specific exit code from the watcher triggers a full pod restart
values: [88]
containers:
- name: main-application
image: my-repo/training-app:1.0
2. 重新运行 init container 以获得干净状态
设想一个场景:init container 负责获取凭据或设置共享卷。如果主应用以某种方式失败并破坏了这个共享状态,就需要重新运行 init container。
通过配置主应用在检测到这类破坏时以特定代码退出,可以触发 RestartAllContainers 操作,确保 init container 在应用重启前提供干净的设置。
3. 处理高频率的相似任务执行
有些情况下,任务最适合表示为一次 Pod 执行。并且每个任务都需要干净的执行环境。任务可能是游戏会话后端,也可能是某个队列项处理。如果任务频率很高,运行完整的 Pod 创建、调度和初始化周期成本就会过高,尤其是在任务可能很短的情况下。从零开始重启所有容器的能力,提供了一种 Kubernetes 原生方式来处理这一场景,无需自定义解决方案或框架。
如何使用
要试用该功能,必须在运行 Kubernetes v1.35+ 的 Kubernetes 集群组件(API server 和 kubelet)上启用 RestartAllContainersOnContainerExits feature gate。该 alpha 特性扩展了 ContainerRestartRules 功能,后者已在 v1.35 中升至 beta,并默认启用。
启用后,可以向任何容器(init、sidecar 或常规容器)添加 restartPolicyRules,并使用 RestartAllContainers 操作。
该功能设计为可在现有应用中轻松使用。不过,如果应用没有遵循某些最佳实践,可能会给应用或可观测性工具带来问题。启用该功能时,请确保所有容器都是可重入的,并且外部工具已准备好应对 init container 的重新运行。另外,在重启所有容器时,kubelet 不会运行 preStop hooks。这意味着容器必须设计为能够处理突然终止,而不能依赖 preStop hooks 来实现优雅关闭。
观察重启过程
为了使该过程可观测,Pod 状态中新增了一个 Pod condition:AllContainersRestarting。当触发重启时,该 condition 会变为 True;一旦所有容器都已终止且 Pod 准备好重新开始其生命周期,它会恢复为 False。这为用户和其他集群组件提供了有关 Pod 状态的明确信号。
由该操作重启的所有容器,其容器状态中的重启计数都会增加。
了解更多
- 阅读关于 Pod Lifecycle 的官方文档。
- 阅读 KEP-5532: Restart All Containers on Container Exits 中的详细提案。
- 阅读 JobSet issue #467 中关于 JobSet 原地重启的提案。
我们希望听到你的反馈!
作为一项 alpha 特性,RestartAllContainers 已可供试验,欢迎提供任何使用场景和反馈。该功能由 SIG Node 社区推动。如果你有兴趣参与、分享想法或作出贡献,欢迎加入我们!
你可以通过以下方式联系 SIG Node:
- 正文:Slack:#sig-node
- 邮件列表
- ← 上一篇
- 下一篇 →