为您的应用程序指定中断预算

功能状态: Kubernetes v1.21 [稳定]

此页面展示了如何限制应用程序所经历的并发中断次数,从而在允许集群管理员管理集群节点的同时提高可用性。

开始之前

您的 Kubernetes 服务器必须为 v1.21 或更高版本。要检查版本,请输入 kubectl version
  • 您是运行在 Kubernetes 集群上的应用程序的所有者,该应用程序需要高可用性。
  • 您应该了解如何部署 复制无状态应用程序 和/或 复制有状态应用程序
  • 您应该阅读有关 Pod 中断 的内容。
  • 您应该与您的集群所有者或服务提供商确认他们是否尊重 Pod 中断预算。

使用 PodDisruptionBudget 保护应用程序

  1. 确定您要使用 PodDisruptionBudget (PDB) 保护的应用程序。
  2. 考虑您的应用程序如何应对中断。
  3. 创建一个 PDB 定义作为 YAML 文件。
  4. 从 YAML 文件创建 PDB 对象。

确定要保护的应用程序

当您想要保护由内置 Kubernetes 控制器之一指定的应用程序时,最常见的用例

  • 部署
  • 复制控制器
  • 副本集
  • StatefulSet

在这种情况下,记下控制器的 .spec.selector;相同的选择器将进入 PDB 的 .spec.selector

从版本 1.15 开始,PDB 支持自定义控制器,其中 scale 子资源 已启用。

您还可以将 PDB 与不受上述控制器之一控制的 Pod 或任意 Pod 组一起使用,但存在一些限制,如 任意工作负载和任意选择器 中所述。

考虑您的应用程序如何应对中断

决定由于自愿中断,在短时间内可以同时关闭多少实例。

  • 无状态前端
    • 问题:不要将服务容量降低超过 10%。
      • 解决方案:例如,使用 minAvailable 为 90% 的 PDB。
  • 单实例有状态应用程序
    • 问题:不要在没有与我联系的情况下终止此应用程序。
      • 可能的解决方案 1:不要使用 PDB 并容忍偶尔的停机时间。
      • 可能的解决方案 2:设置 maxUnavailable=0 的 PDB。达成一项协议(在 Kubernetes 之外),即集群操作员需要在终止之前与您协商。当集群操作员与您联系时,准备停机,然后删除 PDB 以指示准备中断。之后重新创建。
  • 多实例有状态应用程序,例如 Consul、ZooKeeper 或 etcd
    • 问题:不要将实例数量减少到低于法定人数,否则写入将失败。
      • 可能的解决方案 1:将 maxUnavailable 设置为 1(适用于应用程序的不同规模)。
      • 可能的解决方案 2:将 minAvailable 设置为法定人数大小(例如,当规模为 5 时为 3)。(允许更多同时中断)。
  • 可重启批处理作业
    • 问题:作业需要在发生自愿中断的情况下完成。
      • 可能的解决方案:不要创建 PDB。作业控制器将创建一个替换 Pod。

指定百分比时的舍入逻辑

minAvailablemaxUnavailable 的值可以表示为整数或百分比。

  • 当您指定一个整数时,它表示 Pod 的数量。例如,如果您将 minAvailable 设置为 10,那么即使在中断期间也必须始终有 10 个 Pod 可用。
  • 当您通过将值设置为百分比的字符串表示形式(例如 "50%")来指定百分比时,它表示总 Pod 的百分比。例如,如果您将 minAvailable 设置为 "50%",那么在中断期间至少有 50% 的 Pod 必须可用。

当您将值指定为百分比时,它可能不会映射到确切的 Pod 数量。例如,如果您有 7 个 Pod,并且您将 minAvailable 设置为 "50%",那么不清楚这意味着必须有 3 个 Pod 还是 4 个 Pod 可用。Kubernetes 将向上舍入到最接近的整数,因此在这种情况下,必须有 4 个 Pod 可用。当您将 maxUnavailable 值指定为百分比时,Kubernetes 会向上舍入可能被中断的 Pod 数量。因此,中断可能会超过您定义的 maxUnavailable 百分比。您可以检查 代码,该代码控制此行为。

指定 PodDisruptionBudget

PodDisruptionBudget 有三个字段

  • 一个标签选择器 .spec.selector,用于指定它适用的 Pod 集。此字段是必需的。
  • .spec.minAvailable,它描述了在驱逐后,即使在没有被驱逐的 Pod 的情况下,该集合中必须仍然可用的 Pod 数量。minAvailable 可以是绝对数量或百分比。
  • .spec.maxUnavailable(在 Kubernetes 1.7 及更高版本中可用),它描述了在驱逐后,该集合中可以不可用的 Pod 数量。它可以是绝对数量或百分比。

您只能在单个 PodDisruptionBudget 中指定 maxUnavailableminAvailable 之一。maxUnavailable 只能用于控制具有关联控制器管理它们的 Pod 的驱逐。在下面的示例中,“所需副本”是管理由 PodDisruptionBudgetselector 选择的 Pod 的控制器的 scale

示例 1:使用 minAvailable 为 5,只要驱逐后留下了 5 个或更多个 健康 的 Pod(在由 PodDisruptionBudget 的 selector 选择的那些 Pod 中),就可以允许驱逐。

示例 2:使用 minAvailable 为 30%,只要至少 30% 的所需副本数量是健康的,就可以允许驱逐。

示例 3:使用 maxUnavailable 为 5,只要在所需副本总数中最多有 5 个不健康的副本,就可以允许驱逐。

示例 4:使用 maxUnavailable 为 30%,只要不健康的副本数量不超过所需副本总数的 30%(向上舍入到最接近的整数),就可以允许驱逐。如果所需副本总数仅为 1,则仍然允许对该单个副本进行中断,从而导致 100% 的有效不可用性。

在典型用法中,单个预算将用于由控制器管理的 Pod 集合,例如,单个 ReplicaSet 或 StatefulSet 中的 Pod。

如果您将 maxUnavailable 设置为 0% 或 0,或者您将 minAvailable 设置为 100% 或副本数量,那么您需要零个自愿驱逐。当您为 ReplicaSet 等工作负载对象设置零个自愿驱逐时,您将无法成功排空运行这些 Pod 之一的节点。如果您尝试排空运行不可驱逐 Pod 的节点,则排空永远不会完成。这是根据 PodDisruptionBudget 的语义允许的。

您可以在下面找到定义的 Pod 中断预算示例。它们匹配具有标签 app: zookeeper 的 Pod。

使用 minAvailable 的示例 PDB

apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: zk-pdb
spec:
  minAvailable: 2
  selector:
    matchLabels:
      app: zookeeper

使用 maxUnavailable 的示例 PDB

apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: zk-pdb
spec:
  maxUnavailable: 1
  selector:
    matchLabels:
      app: zookeeper

例如,如果上面的 zk-pdb 对象选择大小为 3 的 StatefulSet 的 Pod,则这两个规范具有完全相同的含义。建议使用 maxUnavailable,因为它会自动响应相应控制器副本数量的变化。

创建 PDB 对象

您可以使用 kubectl 创建或更新 PDB 对象。

kubectl apply -f mypdb.yaml

检查 PDB 的状态

使用 kubectl 检查您的 PDB 是否已创建。

假设您在命名空间中实际上没有匹配 app: zookeeper 的 Pod,那么您将看到类似以下内容

kubectl get poddisruptionbudgets
NAME     MIN AVAILABLE   MAX UNAVAILABLE   ALLOWED DISRUPTIONS   AGE
zk-pdb   2               N/A               0                     7s

如果存在匹配的 Pod(例如,3 个),那么您将看到类似以下内容

kubectl get poddisruptionbudgets
NAME     MIN AVAILABLE   MAX UNAVAILABLE   ALLOWED DISRUPTIONS   AGE
zk-pdb   2               N/A               1                     7s

ALLOWED DISRUPTIONS 的非零值意味着中断控制器已看到 Pod,计算了匹配的 Pod,并更新了 PDB 的状态。

您可以使用以下命令获取有关 PDB 状态的更多信息

kubectl get poddisruptionbudgets zk-pdb -o yaml
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  annotations:

  creationTimestamp: "2020-03-04T04:22:56Z"
  generation: 1
  name: zk-pdb

status:
  currentHealthy: 3
  desiredHealthy: 2
  disruptionsAllowed: 1
  expectedPods: 3
  observedGeneration: 1

Pod 的健康状况

当前实现将健康 Pod 定义为具有 .status.conditions 项目且 type="Ready"status="True" 的 Pod。这些 Pod 通过 PDB 状态中的 .status.currentHealthy 字段进行跟踪。

不健康 Pod 驱逐策略

功能状态: Kubernetes v1.27 [beta]

保护应用程序的 PodDisruptionBudget 确保 .status.currentHealthy 的 Pod 数量不会低于 .status.desiredHealthy 中指定的数量,方法是禁止驱逐健康 Pod。通过使用 .spec.unhealthyPodEvictionPolicy,您还可以定义不健康 Pod 应被视为驱逐的标准。当未指定策略时,默认行为对应于 IfHealthyBudget 策略。

策略

IfHealthyBudget
正在运行的 Pod (.status.phase="Running"),但尚未处于健康状态,只有在受保护的应用程序未受到干扰 (.status.currentHealthy 至少等于 .status.desiredHealthy) 时才能被驱逐。

此策略确保已受干扰应用程序的正在运行的 Pod 有最大的机会变为健康状态。这对于排空节点有负面影响,因为可能会被行为不端的应用程序阻塞,这些应用程序受 PDB 保护。更具体地说,是指 Pod 处于 CrashLoopBackOff 状态 (由于错误或配置错误) 的应用程序,或者只是无法报告 Ready 状态的 Pod。

AlwaysAllow
正在运行的 Pod (.status.phase="Running"),但尚未处于健康状态,被视为已受干扰,无论 PDB 中的标准是否满足,都可以被驱逐。

这意味着已受干扰应用程序的预期运行的 Pod 可能没有机会变为健康状态。通过使用此策略,集群管理器可以轻松地驱逐受 PDB 保护的行为不端的应用程序。更具体地说,是指 Pod 处于 CrashLoopBackOff 状态 (由于错误或配置错误) 的应用程序,或者只是无法报告 Ready 状态的 Pod。

任意工作负载和任意选择器

如果您只使用具有内置工作负载资源 (Deployment、ReplicaSet、StatefulSet 和 ReplicationController) 或具有 自定义资源 (这些资源实现了 scale 子资源,并且 PDB 选择器与 Pod 所属资源的选择器完全匹配) 的 PDB,则可以跳过此部分。

您可以将 PDB 与由其他资源、"运算符" 或裸 Pod 控制的 Pod 一起使用,但存在以下限制

  • 只能使用 .spec.minAvailable,不能使用 .spec.maxUnavailable
  • 只能对 .spec.minAvailable 使用整数值,不能使用百分比。

无法使用其他可用性配置,因为 Kubernetes 无法在没有支持的所属资源的情况下推导出 Pod 的总数。

您可以使用选择器,该选择器选择属于工作负载资源的 Pod 的子集或超集。驱逐 API 将禁止驱逐被多个 PDB 覆盖的任何 Pod,因此大多数用户会希望避免重叠选择器。重叠 PDB 的一个合理用途是在将 Pod 从一个 PDB 迁移到另一个 PDB 时。

上次修改时间:2024 年 2 月 20 日上午 9:48 PST: 将更多功能状态简码改为数据驱动 (7b6866063f)