强制删除 StatefulSet Pods

此页面说明如何删除属于 StatefulSet 的 Pod,并解释了执行此操作时需要考虑的事项。

开始之前

  • 这是一项相对高级的任务,有可能违反 StatefulSet 的某些固有属性。
  • 在继续之前,请熟悉以下列出的注意事项。

StatefulSet 注意事项

在 StatefulSet 的正常运行中,绝不需要强制删除 StatefulSet Pod。 StatefulSet 控制器负责创建、扩缩和删除 StatefulSet 的成员。它试图确保从序号 0 到 N-1 的指定数量的 Pod 处于活跃和就绪状态。StatefulSet 确保在任何时候,集群中最多只有一个具有给定身份的 Pod 在运行。这被称为 StatefulSet 提供的**最多一个**(*at most one*)语义。

手动强制删除应谨慎进行,因为它有可能违反 StatefulSet 固有的最多一个语义。StatefulSet 可用于运行需要稳定网络身份和稳定存储的分布式和集群化应用程序。这些应用程序通常具有依赖于固定数量成员组成的固定身份集的配置。拥有具有相同身份的多个成员可能是灾难性的,并可能导致数据丢失(例如,基于法定人数(quorum-based)的系统中的脑裂(split brain)场景)。

删除 Pod

你可以使用以下命令执行优雅的 Pod 删除

kubectl delete pods <pod>

为了使上述操作能够实现优雅终止,Pod 不能指定 pod.Spec.TerminationGracePeriodSeconds 为 0。将 pod.Spec.TerminationGracePeriodSeconds 设置为 0 秒的做法是不安全的,强烈不建议用于 StatefulSet Pod。优雅删除是安全的,并且能够确保 Pod 在 kubelet 从 apiserver 删除名称之前优雅地关闭

当节点无法访问时,Pod 不会自动删除。在无法访问的节点上运行的 Pod 在经过超时后会进入“Terminating”或“Unknown”状态。当用户尝试在无法访问的节点上优雅删除 Pod 时,Pod 也可能进入这些状态。处于此类状态的 Pod 可以从 apiserver 中移除的唯一方式如下

  • 删除 Node 对象(可以是你,也可以是节点控制器)。
  • 无响应节点上的 kubelet 开始响应,杀死 Pod 并从 apiserver 中移除条目。
  • 用户强制删除 Pod。

推荐的最佳实践是使用第一种或第二种方法。如果确定一个节点已死亡(例如,永久与网络断开连接,已断电等),则删除该 Node 对象。如果节点遭受网络分区,则尝试解决此问题或等待其自行解决。当分区恢复时,kubelet 将完成 Pod 的删除,并在 apiserver 中释放其名称。

通常,一旦 Pod 不再在节点上运行,或者管理员删除节点,系统就会完成删除。你也可以通过强制删除 Pod 来覆盖此行为。

强制删除

强制删除等待 kubelet 确认 Pod 已终止。无论强制删除是否成功杀死 Pod,它都会立即从 apiserver 中释放名称。这将允许 StatefulSet 控制器创建一个具有相同身份的替换 Pod;这可能导致仍在运行的 Pod 的重复,并且如果该 Pod 仍然可以与 StatefulSet 的其他成员通信,则会违反 StatefulSet 设计用于保证的最多一个语义。

当你强制删除 StatefulSet Pod 时,你是在断言该 Pod 将永远不会再与 StatefulSet 中的其他 Pod 建立联系,并且可以安全地释放其名称以供创建替换 Pod。

如果你想使用 kubectl 1.5 或更高版本强制删除 Pod,请执行以下操作

kubectl delete pods <pod> --grace-period=0 --force

如果你使用的是 kubectl 1.4 或更低版本,则应省略 --force 选项,使用

kubectl delete pods <pod> --grace-period=0

如果即使执行了这些命令后 Pod 仍然停留在 Unknown 状态,请使用以下命令将 Pod 从集群中移除

kubectl patch pod <pod> -p '{"metadata":{"finalizers":null}}'

始终谨慎地强制删除 StatefulSet Pod,并充分了解所涉及的风险。

接下来

了解更多关于调试 StatefulSet 的信息。

最后修改于太平洋标准时间 2023 年 2 月 19 日 晚上 9:42:清理 tasks/run-application 中的页面 (ba99616c27)