在 Azure Kubernetes 服务 (AKS) 中配置 pod 逐出以冻结事件(预览版)

Important

AKS 预览功能可在自助服务和自愿选择的基础上启用。 预览版按“现状”和“视供应情况”提供,它们不包括在服务级别协议和有限保证范围内。 AKS 预览功能是由客户支持尽最大努力部分覆盖。 因此,这些功能并不适合用于生产。 有关详细信息,请参阅以下支持文章:

节点自动清空 有助于保护工作负荷免受节点池中基础虚拟机(VM)上的 计划事件 中断的影响。 默认情况下,冻结事件不会触发封锁和清空,因为它们通常只短暂暂停节点。 如果您的工作负载无法容忍短暂中断,您可以选择在冻结开始之前启用逐出带有标签的 Pod。

冻结驱逐有两个配置级别:

  • 群集级配置:指示 ConfigMap AKS 在计划冻结事件时封锁受影响的节点。 将节点设为不可调度可防止新的 Pod 被调度到该节点上,但其本身不会驱逐任何现有 Pod。
  • Pod 级别配置:单个 Pod 上的标签会使其被纳入驱逐范围。 当节点被封锁时,AKS 仅逐出携带此标签的 Pod。 未标记的 Pod 保留在节点上,不会中断。

仅使用 ConfigMap 只会封锁该节点,而仅有该标签如果没有 ConfigMap 则不会产生任何影响。 如果两者都已配置好,任何接收到带有 VMEventScheduled 消息的 Freeze 状况的节点都会被标记为不可调度,并且带有相应标签的 Pod 会被逐出。 逐出会遵循 Pod 干扰预算(PDB),因此,只有在 PDB 允许时,才能逐出 Pod。

先决条件

  • 现有的 AKS 集群。 如果还没有,请创建 AKS 群集
  • 已配置为连接到您的集群的 kubectl 命令行工具。
  • 为要逐出的工作负荷正确配置 了 Pod 中断预算

为冻结事件启用节点封锁

ConfigMap命名空间中发布一个kube-system命令,告知 AKS 在计划冻结事件时封锁节点。 封锁将节点标记为不可计划,因此没有新 Pod 登陆该节点,但不会删除任何现有 Pod。 若要在冻结期间逐出特定 Pod,还必须为其添加逐出标签

  1. 创建包含以下内容的名为 remediator-config.yaml 的文件:

    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: remediator-config
      namespace: kube-system
    data:
      appConfig: |
        {
          "Cluster": {
            "OnFreeze": {
              "Enabled": true
            }
          }
        }
    
  2. 使用ConfigMapkubectl apply应用到您的集群:

    kubectl apply -f remediator-config.yaml
    

注释

配置每 30 分钟读取一次,因此可能不会立即将更改应用到群集。

为冻结事件期间的驱逐标记 Pod

启用群集级配置后,通过添加 remediator.kubernetes.azure.com/onFreeze 标签将各个 Pod 标记为待逐出。 在排水阶段,仅逐出具有此标签的 Pod。

您可以将该标签添加到工作负载清单中,或将其应用到运行中的 Pod。

在部署清单中添加标签

对于永久性工作负荷,请将标签添加到部署清单中的 Pod 模板,以便 Kubernetes 在重新创建 Pod 时保留设置:

apiVersion: v1
kind: Pod
metadata:
  name: some-pod-safe-to-evict
  labels:
    remediator.kubernetes.azure.com/onFreeze: ""
spec:
  containers:
    - name: my-container
      image: mcr.azk8s.cn/mcr/hello-world:latest

向现有 Pod 添加标签

使用 kubectl label 向正在运行的 Pod 添加标签:

kubectl label pod <pod-name> remediator.kubernetes.azure.com/onFreeze=""

此方法可用于快速验证,但如果 Kubernetes 重新创建 Pod,则会删除标签。

ConfigMap 和 Pod 标签均已配置时,AKS 会将该节点设为不可调度,并仅在计划冻结事件发生前约五分钟驱逐带有相应标签的 Pod。 未标记的 Pod 将继续在已封锁的节点上运行。

Important

确保 Pod 中断预算 已正确配置。 如果 PDB 不允许在预定事件发生时发生中断,则驱逐将失败。

排查冻结事件中的驱逐问题

如果您发现存在冻结事件,但后续没有出现封锁或驱逐清空事件,或者 Pod 没有按预期被驱逐,请按照以下步骤进行排查。

检查 Kubernetes 事件

可以使用 Kubernetes 事件日志或 Container Insights 监视冻结事件的封锁、清空和逐出进度。 有关详细信息,请参阅 使用 Kubernetes 事件进行故障排除

以下事件会在排空和逐出过程中出现:

Event Description
VMEventScheduled 标记节点的计划 VM 事件生命周期的开始。
FreezeScheduled 指示已计划冻结事件,包括计划的时间。
NodeCordonStart 节点警戒线在计划事件之前大约五分钟开始。
NodeCordonEnd 节点警戒线完成。
NodeDrainStart 排空操作开始,带标签的 Pod 开始被逐出。
Evicted 显示被逐出的特定 Pod 的 Pod 事件。
FailedToEvict 表示 Pod 由于任何原因而未能被驱逐的 Pod 事件。
NodeDrainEnd 当带标签的 Pod 被驱逐后,排空操作即告完成。
NoVMEventScheduled 当未找到节点的计划事件时。
NodeUncordonStart 冻结事件结束后,将开始解除节点封锁。
NodeUncordonEnd 节点解除封锁完成后,该节点将再次可调度。

如果在任何步骤中发生故障,则会记录单独的错误事件。 例如,事件消息中会显示一个 NodeDrainError 事件,其中包含详细信息。

如果看到 FreezeScheduled 事件但没有 NodeCordonStart 事件,则可能无法正确应用群集级别 ConfigMap 。 如果您看到封锁事件,但带有相应标签的 Pod 并未被驱逐,请确认这些 Pod 带有 remediator.kubernetes.azure.com/onFreeze 标签,并且 PDB 在事件发生时允许驱逐。

验证 ConfigMap

通过运行以下命令,确认集群级别的 ConfigMap 是否已正确应用:

kubectl describe configmap remediator-config -n kube-system

将输出与 “启用节点封锁”中所述的配置进行比较,用于冻结事件

验证 Pod 标签

运行以下命令,确认要逐出的 Pod 具有正确的标签:

kubectl get pods --show-labels -o wide

验证 remediator.kubernetes.azure.com/onFreeze 标签是否已出现在预期的 Pod 上,并确认这些 Pod 是否正在目标节点上运行。 没有此标签的 Pod 不会在排水阶段被逐出。

验证 Pod 中断预算

确认你的 PDB 在计划事件发生时允许驱逐:

kubectl get pdb

如果 PDB 不允许干扰,即使 Pod 已正确标记,驱逐也会失败。

局限性

  • 无法直接触发或模拟冻结事件。 但是,金丝雀环境中经常会出现冻结情况。 若要评估此功能,请在 chinanorth3chinaeast2 区域中创建群集。
  • ConfigMap 每 30 分钟读取一次,因此配置更改可能不会立即生效。
  • 逐出取决于 Pod 中断预算。 如果 PDB 不允许干扰,则无法逐出。