通过将 AKS 现成节点池与群集自动缩放程序结合使用来配置多个节点池

已完成

Azure 提供了 Azure 虚拟机实例,它们在降低成本的同时提供可伸缩性,非常适合可中断的工作负载。 不过,这些虚拟机 (VM) 以较低的价格购买未使用的 Azure 计算容量,但仍支持高性能计算方案。

与许多容器化应用程序和服务一样,你公司的无人机跟踪解决方案也部署在 Azure Kubernetes 服务 (AKS) 上。 其中一项服务是调度无人机飞行路线的批处理服务。 随着客户群的突然扩大,批处理服务会收到铺天盖地的请求,并开始积压大量交付。 这种情况会导致延迟并令客户感到失望。

通过自动缩放批处理服务副本的数量,可及时处理订单。 但是,这还需要部署更多节点才能满足计算资源需求。 通过分析 Azure Monitor 中的使用趋势,你注意到这些节点仅在特定时间使用,而且不具成本效益。 批处理服务是无状态服务,不保存客户端会话数据。 你意识到可通过以下方式节省成本:

  • 使用成本较低的节点实例。
  • 自动缩放为批处理配置的节点池中的节点计数。

让我们看看 AKS 中构成此节省成本解决方案的基础结构。

Azure 中的现成虚拟机(现成 VM)是指什么?

现成虚拟机是一种可以超低优惠价购买未使用的 Azure 计算容量的 VM。 现成 VM 可代替 Azure 中现有的低优先级 VM。 可以使用现成 VM 运行工作负载,其中包括:

  • 高性能计算方案、批处理或视觉渲染应用程序。

  • 大规模无状态应用程序。

  • 开发人员/测试环境,包括持续集成 (CI) 和持续交付 (CD) 工作负载。

现成 VM 可用性

现成 VM 的可用性取决于容量、大小、区域和当日时间等因素。 Azure 仅在容量可用时分配 VM。 因此,此类 VM 没有服务级别协议 (SLA),且不能保证高可用性。

现成 VM 逐出策略

现成 VM 的默认逐出策略为“解除分配”。 当某个区域中的容量受限时,Azure 会在提前 30 秒通知后逐出现成 VM。 逐出后,使用 Deallocate 策略设置的 VM 变为“已停止分配”状态。 当现成容量再次可用时,可重新部署已逐出的 VM。 解除分配的 VM 仍计入你的现成虚拟 CPU (vCPU) 配额,且仍对基础分配的磁盘收费。

什么是现成虚拟机规模集?

现成虚拟机规模集是支持 Azure 现成 VM 的虚拟机规模集。 这些 VM 的行为与普通的现成 VM 相同,区别在于:在 Azure 中对现成 VM 使用虚拟机规模集支持时,你可在两种逐出策略之间进行选择:

  • Deallocate:“解除分配”策略的功能与前面所述的完全相同。

  • 删除:“删除”策略使你可避免磁盘成本和达到配额限制。 借助 Delete 逐出策略,逐出的 VM 将连同其基础磁盘一起删除。 规模集的自动缩放功能现可通过创建新的 VM 来自动尝试弥补 VM 逐出。 尽管无法保证 VM 的创建,但逐出的 VM 不计入你的 vCPU 配额,也不会产生基础磁盘的费用。

    最佳做法是仅在将规模集上的逐出策略设置为“删除”时使用自动缩放功能。

什么是 Azure Kubernetes 服务 (AKS) 中的现成节点池?

现成节点池是使用现成虚拟机规模集的用户节点池。 AKS 在下列情况下支持现成 VM:

  • 需要创建用户节点池。
  • 希望拥有虚拟机规模集支持 Azure 现成 VM 所带来的成本优势。

可使用现成节点池执行以下操作:

  • 利用 Azure 中未使用的容量。
  • 将规模集功能与“删除”逐出策略配合使用。
  • 定义每小时愿意支付的最高价格。
  • 使用现成节点池时,启用建议的 AKS Kubernetes 群集自动缩放程序。

例如,若要支持无人机跟踪应用程序的批处理服务,可以创建一个现成的用户节点池,并启用群集自动缩放程序。 然后,将水平 Pod 缩放程序配置为部署更多批处理服务,以匹配资源需求。

随着节点需求的增加,群集自动缩放程序可以在现成节点池中增加和缩减节点数。 如果发生节点逐出,则在仍需要额外节点的情况下,群集自动缩放程序将继续尝试纵向扩展横向计数。

现成节点池的限制

在决定将现成用户节点池添加到 AKS 群集之前,请考虑以下限制:

  • 基础现成规模集仅部署到单个容错域,不保证高可用性。
  • AKS 群集需要启用多个节点池支持。
  • 只能将现成节点池用作用户节点池。
  • 你无法升级现成节点池。
  • 不保证创建现成 VM。 创建现成节点取决于群集的已部署 Azure 区域中的容量和配额可用性。

请记住,现成节点池应仅用于可中断的工作负载。

重要

在某些订阅(如赞助订阅)中,创建现成 VM 和现成节点池的功能将受到限制。 可能无法为群集创建现成节点池。

将现成节点池添加到 AKS 群集

现成节点池不能是 AKS 群集的系统节点池。 首先,你需要创建群集,然后使用 az aks nodepool add 命令添加新的用户节点池。

为新节点池设置多个参数,以将其配置为现成节点池。

优先级

新节点池的 --priority 参数默认设置为 Regular。 将值设置为 Spot,以指示正在创建的新池是一个现成节点池。 创建后不能更改此值。

逐出策略

现成节点池必须使用虚拟机规模集。 回想前面的内容,现成节点池要使用一个现成规模集。 将 --eviction-policy 设置为 Delete,以允许规模集同时移除节点及其使用的基础分配磁盘。 创建后无法再更改此值。

你可以将逐出策略设置为 Deallocate,但当这些节点被逐出时,它们仍将计入计算配额,以缩放或升级群集。

现成节点的最高价格

通过限制你愿意为每小时每个现成节点支付的最大金额,现成节点池可以优化成本。 要设置安全价格,请使用 --spot-max-price 参数。 达到此值后,将逐出新创建的现成节点。

你可以将此值设置为小数位数不超过 5 位的任何正值,或将其设置为 -1。 如果将 --spot-max-price 值设置为 -1,将通过以下方式影响节点池:

  • 不会根据节点的价格逐出节点。
  • 新节点的成本将基于现成节点的当前价格或标准节点的价格,两者以较低者为准。

例如,如果将值设置为 0.98765,则节点的最高价格为每小时 0.98765 美元。 当节点的使用超出此价格时,就会被逐出。

启用群集自动缩放程序

建议使用 --enable-cluster-autoscaler 参数启用群集自动缩放程序。 如果不使用群集自动缩放程序,就会面临节点池中的节点计数降为零的风险,因为节点会由于 Azure 容量限制而被逐出。

最小节点计数

使用 --min-count 参数将最小节点计数设置为 1 到 100 之间的值。 启用群集自动缩放程序时,需要最小节点计数。

最大节点计数

使用 --max-count 参数将最大节点计数设置为 1 到 100 之间的值。 启用群集自动缩放程序时,需要最大节点计数。

示例配置

下面是一个示例 az aks nodepool add 命令,它会添加最大计数为 3 且最小计数为 1 的现成节点池。 请注意如何使用 --enable-cluster-autoscaler 启用现成节点功能。

az aks nodepool add \
    --resource-group resourceGroup \
    --cluster-name aksCluster \
    --name spotpool01 \
    --enable-cluster-autoscaler \
    --max-count 3 \
    --min-count 1 \
    --priority Spot \
    --eviction-policy Delete \
    --spot-max-price -1 \
    --no-wait

将 Pod 部署到现成节点池

在 Kubernetes 中部署工作负载时,可向调度程序提供信息,来指定工作负载可运行或无法运行的节点。 可配置污点、容忍或节点相关性来控制工作负载。 使用特定标签和污点配置现成节点。

什么是污点?

污点可应用于节点,以指示只能对其调度特定的 Pod。 配置现成节点时,将标签设置为 kubernetes.azure.com/scalesetpriority:spot

什么是容忍?

容忍度是应用于 Pod 的规范,允许但不要求在具有相应污点的节点上计划 Pod。 配置现成节点时,将节点污点设置为 kubernetes.azure.com/scalesetpriority=spot:NoSchedule

注意

污点和容忍度不保证 Pod 将放置在特定节点上。 例如,如果某个节点没有污点,则可能将具有容忍度的 Pod 调度到该未污染的节点上。 指定与污点和容忍度的相关性可以解决此问题。

什么是节点相关性?

使用节点相关性来描述在节点上调度的 Pod。 通过使用节点上定义的标签来指定相关性。 例如在 AKS 中,系统 Pod 配置有对现成节点的反相关性,以防止在这些节点上对其进行调度。

定义 Pod 清单文件中的容忍

你可以通过在工作负载清单文件中创建 tolerations 字典项来指定节点污点容忍。 在此字典中,你可以为工作负载在此部分中必须容忍的每个节点污点设置以下属性:

属性 说明
key 标识在节点上指定的节点污点键值对。 例如,在现成节点池上,键值对为 kubernetes.azure.com/scalesetpriority:spot。 键为 kubernetes.azure.com/scalesetpriority
operator 允许容忍与污点匹配。 默认运算符为 Equal。 你还可指定 Exists 与容忍匹配。 但是,在使用 Exists 时,不指定以下属性 (value)。
value 表示节点上指定的节点污点键值对的值部分。 例如,在键值对为 kubernetes.azure.com/scalesetpriority:spot 的现成节点池上,该值为 spot
effect 指示在系统中如何处理 Pod 的调度。 有 3 种选择:NoSchedulePreferNoScheduleNoExecuteNoSchedule 可确保系统无法调度 Pod。 PreferNoSchedule 允许系统尝试不调度 Pod。 NoExecute 要么逐出已在受污染节点上运行的 Pod,要么根本不调度 Pod。

在 Pod 清单文件中定义节点相关性

通过在工作负载清单文件中创建 affinity 条目来指定相关性。 在此条目中,为工作负载必须匹配的每个节点标签设置以下属性:

属性 说明
nodeAffinity 描述 Pod 的节点相关性调度规则。
requiredDuringSchedulingIgnoredDuringExecution 如果在调度时未满足此字段指定的相关性要求,则不会将 Pod 调度到节点上。 如果在 Pod 执行期间的某个时间点不再满足此字段指定的相关性要求(例如由于更新),则系统可以选择尝试将 Pod 从其节点中逐出。
nodeSelectorTerms 节点选择器术语列表。 返回的术语会与任何筛选器匹配,而不是所有筛选器。
matchExpressions 按节点标签排列的节点选择器要求列表。
key 选择器应用到的标签键。 键为 kubernetes.azure.com/scalesetpriority
operator 表示键与一组值之间的关系。 有效的运算符有 InNotInExistsDoesNotExistGtLt
values 表示节点上指定的节点标签键值对的值部分。 在键值对为 kubernetes.azure.com/scalesetpriority:spot 的现成节点池上,该值为 spot

下面是已为现成节点池添加容忍度和相关性的工作负载的示例。

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    env: test
spec:
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent
  tolerations:
  - key: "kubernetes.azure.com/scalesetpriority"
    operator: "Equal"
    value: "spot"
    effect: "NoSchedule"
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: "kubernetes.azure.com/scalesetpriority"
            operator: In
            values:
            - "spot"

知识检查

1.

假设你有一个无状态服务,它负责处理联机订单并在 Azure Kubernetes 服务 (AKS) 群集上运行。 你决定在 AKS 群集上使用现成节点池来优化群集上的计算成本。 如何将现成节点池添加到 AKS 群集?

2.

对于上述问题中描述的服务,哪种逐出策略是用于配置现成节点池的最经济实惠的选项?

3.

对于上述问题中描述的服务,如何确保在现成用户节点池的节点上调度工作负载?