Pod 不会消失,除非有人(用户或控制器)将其销毁,或者出现了不可避免的硬件或软件系统错误。
我们把这些不可避免的情况称为应用的非自愿干预(Involuntary Disruptions)。例如:
称其他情况为自愿干扰(Voluntary Disruptions)。 包括由应用所有者发起的操作和由集群管理员发起的操作。 典型的应用所有者的操作包括:
集群管理员操作包括:
即使你会经常引入自愿性干预,Kubernetes 提供的功能也能够支持你运行高度可用的应用。
作为一个应用的所有者,你可以为每个应用创建一个 PodDisruptionBudget(PDB)。
PDB 将限制在同一时间因自愿干预导致的多副本应用中发生宕机的 Pod 数量。 例如,基于票选机制的应用希望确保运行中的副本数永远不会低于票选所需的数量。 Web 前端可能希望确保提供负载的副本数量永远不会低于总数的某个百分比。
集群管理器和托管提供商应使用遵循 Pod Disruption Budgets 的工具,方法是调用Eviction API而不是直接删除 Pod。例如 kubectl drain 命令和 Kubernetes-on-GCE 集群升级脚本
例如,kubectl drain 命令可以用来标记某个节点即将停止服务。 运行 kubectl drain 命令时,工具会尝试驱逐你所停服的节点上的所有 Pod。 kubectl 代表你所提交的驱逐请求可能会暂时被拒绝, 所以该工具会周期性地重试所有失败的请求, 直到目标节点上的所有的 Pod 都被终止,或者达到配置的超时时间。
PDB 指定应用可以容忍的副本数量(相当于应该有多少副本)。 例如,具有 .spec.replicas: 5 的 Deployment 在任何时间都应该有 5 个 Pod。 如果 PDB 允许其在某一时刻有 4 个副本,那么驱逐 API 将允许同一时刻仅有一个(而不是两个)Pod 自愿干扰。
使用标签选择器来指定应用程序的一组 pod,这与应用程序的控制器(Deployment、StatefulSet 等)使用的相同。
Pod 控制器的 .spec.replicas 计算“预期的” pod 数量。使用对象的 .metadata.ownerReferences 值从控制器获取。
由于应用程序的滚动升级而被删除或不可用的 Pod 确实会计入中断预算,但控制器(如 Deployment 和 StatefulSet)在进行滚动升级时不受 PDB 的限制——在应用程序更新期间的故障处理是在控制器的规格(spec)中配置
使用驱逐 API 驱逐 pod 时,pod 会被优雅地终止
假设集群有3个节点,node-1 到 node-3。集群中运行了一些应用,其中一个应用有3个副本,分别是 pod-a、pod-b 和 pod-c。另外,还有一个与它相关的不具有 PDB 的 pod,我们称为之为 pod-x。最初,所有 Pod 的分布如下
所有的3个 pod 都是 Deployment 中的一部分,并且它们共同拥有一个 PDB,要求至少有3个 pod 中的2个始终处于可用状态。
例如,假设集群管理员想要重启系统,升级内核版本来修复内核中的错误。集群管理员首先使用 kubectl drain 命令尝试排除 node-1。该工具试图驱逐 pod-a 和 pod-x。这立即成功。两个 Pod 同时进入终止状态。这时的集群处于这种状态:
Deployment 注意到其中有一个 pod 处于正在终止,因此会创建了一个 pod-d 来替换。由于 node-1 被封锁(cordon),它落在另一个节点上。同时其它控制器也创建了 pod-y 作为 pod-x 的替代品。
对于 StatefulSet,pod-a 将被称为 pod-1,需要在替换之前完全终止,替代它的也称为 pod-1,但是具有不同的 UID
当前集群的状态如下:
在某一时刻,pod 被终止,集群看起来像下面这样子:
此时,如果一个集群管理员试图排空(drain)node-2 或 node-3,drain 命令将被阻塞,因为对于 Deployment 只有2个可用的 pod,并且其 PDB 至少需要2个。经过一段时间,pod-d 变得可用。
现在,集群管理员尝试排空 node-2。drain 命令将尝试按照某种顺序驱逐两个 pod,假设先是 pod-b,然后再 pod-d。它将成功驱逐 pod-b。但是,当它试图驱逐 pod-d 时,将被拒绝,因为这样对 Deployment 来说将只剩下一个可用的 pod。
Deployment 将创建一个名为 pod-e 的 pod-b 的替代品。但是,集群中没有足够的资源来安排 pod-e。那么,drain 命令就会被阻塞。集群最终可能是这种状态:
您可以看到 Kubernetes 如何改变中断发生的速率,根据:
将集群管理者和应用程序所有者视为彼此知识有限的独立角色通常是很有用的。这种责任分离在这些情况下可能是有意义的:
Pod Disruption Budget 通过在角色之间提供接口来支持这种角色分离。
如果您的组织中没有这样的职责分离,则可能不需要使用 Pod 中断预算。
如果您是集群管理员,要对集群的所有节点执行中断操作,例如节点或系统软件升级,则可以使用以下选择: