Kubernetes v1.33:容器生命周期更新

Kubernetes v1.33 引入了对容器生命周期的一些更新。 容器生命周期回调的 Sleep 动作现在支持零睡眠时长(特性默认启用)。 同时还为定制发送给终止中的容器的停止信号提供了 Alpha 级别支持。

这篇博客文章深入介绍了容器生命周期的这些新内容,以及如何使用它们。

Sleep 动作的零值

Kubernetes v1.29 引入了容器 PreStop 和 PostStart 生命周期回调的 Sleep 动作。 Sleep 动作允许你的容器在启动后或终止前暂停指定的时长。这为管理优雅关闭提供了一种直接的方法。 在 Sleep 动作之前,人们常使用生命周期回调中的 exec 动作运行 sleep 命令。 如果你想这样做,则需要在你的容器镜像中包含 sleep 命令的二进制文件。 如果你使用第三方镜像,这可能会比较困难。

最初添加 Sleep 动作时,并不支持零秒的睡眠时间。 然而,time.Sleep(Sleep 动作底层使用的机制)是支持零秒的持续时间的。 使用负值或零值进行睡眠会立即返回,导致无操作。我们希望 Sleep 动作也有相同的行为。 后来在 v1.32 中通过特性门控 PodLifecycleSleepActionAllowZero 添加了这种对零持续时间的支持。

PodLifecycleSleepActionAllowZero 特性门控在 v1.33 中已升级到 Beta 阶段,并且现在默认启用。 从 Kubernetes v1.30 开始,preStoppostStart 回调的原始 Sleep 动作默认情况下已启用。 使用运行 Kubernetes v1.33 的集群时,你可以为 Sleep 生命周期钩子设置零持续时间。 对于采用默认配置的集群,你无需启用任何特性门控即可实现这一点。

容器停止信号

容器运行时如 containerd 和 CRI-O 支持容器镜像定义中的 StopSignal 指令。 这可以用来指定一个自定义的停止信号,运行时将使用该信号来终止基于此镜像的容器。 停止信号配置最初并不是 Kubernetes Pod API 的一部分。 直到 Kubernetes v1.33,覆盖容器停止信号的唯一方法是通过使用新的自定义停止信号重建容器镜像 (例如,在 ContainerfileDockerfile 中指定 STOPSIGNAL)。

ContainerStopSignals 特性门控是 Kubernetes v1.33 新增的, 它将停止信号添加到了 Kubernetes API。这允许用户在容器规格中指定自定义的停止信号。 停止信号作为新生命周期加入 API,连同现有的 PreStop 和 PostStart 生命周期处理器一起使用。 要使用这个特性,Pod 需要用 spec.os.name 指定操作系统。这是为了能对操作系统进行停止信号的交叉验证, 确保 Pod 中的容器是以适合其调度操作系统的有效停止信号创建的。对于调度到 Windows 节点上的 Pod, 仅允许 SIGTERMSIGKILL 作为有效的停止信号。 这里可以找到 Linux 节点支持的完整信号列表。

默认行为

如果容器在其生命周期中定义了自定义停止信号,那么只要容器运行时也支持自定义停止信号, 容器运行时就会使用生命周期中定义的信号来终止容器。如果容器生命周期中没有定义自定义停止信号, 运行时将回退到容器镜像中定义的停止信号。如果在容器镜像中也没有定义停止信号, 将会使用运行时的默认停止信号。对于 containerd 和 CRI-O,默认信号都是 SIGTERM

版本偏差

为了使该特性按预期工作,Kubernetes 和容器运行时的版本都应支持容器停止信号。 对 Kubernetes API 和 kubelet 的更改从 v1.33 开始进入 Alpha 阶段, 可以通过启用 ContainerStopSignals 特性门控来使用。 containerd 和 CRI-O 的容器运行时实现仍在进行中,不久将会发布。

使用容器停止信号

要启用此特性,你需要在 kube-apiserver 和 kubelet 中打开 ContainerStopSignals 特性门控。 一旦你在节点上启用了特性门控,就可以创建带有 StopSignal 生命周期和有效操作系统名称的 Pod,如下所示:

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  os:
    name: linux
  containers:
    - name: nginx
      image: nginx:latest
      lifecycle:
        stopSignal: SIGUSR1

请注意,此示例中的 SIGUSR1 信号仅在容器的 Pod 被调度到 Linux 节点时才能使用。 因此,我们需要指定 spec.os.namelinux 才能使用该信号。 如果 Pod 被调度到 Windows 节点,则你只能配置 SIGTERMSIGKILL 信号。 此外,如果 spec.os.name 字段为 nil 或未设置,你也不能指定 containers[*].lifecycle.stopSignal

我如何参与?

此特性由 SIG Node 推动。如果你有兴趣帮助开发此特性、分享反馈或参与任何其他正在进行的 SIG Node 项目,请联系我们!

你可以通过几种方式联系 SIG Node:

你也可以直接联系我:

  • GitHub:@sreeram-venkitesh
  • Slack:@sreeram.venkitesh