将 Azure 现成节点池添加到 Azure Kubernetes 服务 (AKS) 群集

本文介绍如何将辅助 Spot 节点池添加到现有的 Azure Kubernetes 服务 (AKS) 群集中。

现成节点池是由 Azure 现成虚拟机规模集支持的节点池。 借助 AKS 群集中的现成 VM,可以充分利用未使用的 Azure 容量,并大幅节省成本。 可用的未用容量因多个因素而异,如节点大小、区域、时间等。

部署现成节点池时,如果存在可用容量,Azure 会分配现成节点,并在单个默认域中部署支持现成节点池的现成规模集。 现成节点没有 SLA。 不提供高可用性保证。 如果 Azure 需要恢复容量,Azure 基础结构会逐出现场节点。

现成节点非常适用于可处理中断、提前终止或逐出的工作负载。 例如,批处理作业、开发和测试环境以及大型计算工作负载等,可能都很适合安排在 Spot 节点池上运行。

开始之前

  • 本文假设读者基本了解 Kubernetes 和 Azure 负载均衡器的概念。 有关详细信息,请参阅 Azure Kubernetes 服务 (AKS) 的 Kubernetes 核心概念
  • 如果没有 Azure 订阅,请在开始前创建一个试用版订阅
  • 当创建群集以使用现成节点池时,该群集还必须将虚拟机规模集用于节点池和标准 SKU 负载均衡器。 创建群集后,还必须添加另一个节点池,本教程将介绍具体操作。
  • 本文要求运行 Azure CLI 2.14 或更高版本。 运行 az --version 即可查找版本。 如果需要进行安装或升级,请参阅安装 Azure CLI

限制

创建和管理具有 Spot 节点池的 AKS 群集时,适用以下限制:

  • Spot 节点池不能作为默认节点池,只能用作辅助节点池。
  • 不能同时升级控制平面和节点池。 您必须分别对其进行升级,或者删除 Spot 节点池,以同时升级控制平面和其余节点池。
  • Spot 节点池必须使用虚拟机规模集。
  • ScaleSetPrioritySpotMaxPrice 一经创建便无法更改。
  • 设置 SpotMaxPrice 时,值必须为 -1,或者为小数点后最多五位的正值
  • Spot 节点池具有 kubernetes.azure.com/scalesetpriority:spot 标签和 kubernetes.azure.com/scalesetpriority=spot:NoSchedule 污点,并且系统 Pod 具有反亲和性。
  • 您必须添加相应的容忍度和亲和性,才能将工作负载调度到 Spot 节点池上。

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

将现成节点池添加到现有群集时,它必须是启用了多个节点池的群集。 创建启用多个节点池的 AKS 群集时,默认会创建一个 priorityRegular 的节点池。 若要添加 Spot 节点池,必须将 Spot 设为 priority 的值。 有关创建包含多个节点池的 AKS 群集的更多详细信息,请参阅使用多个节点池

export SPOT_NODEPOOL="spotnodepool"

az aks nodepool add \
    --resource-group $RESOURCE_GROUP \
    --cluster-name $AKS_CLUSTER \
    --name $SPOT_NODEPOOL \
    --priority Spot \
    --eviction-policy Delete \
    --spot-max-price -1 \
    --enable-cluster-autoscaler \
    --min-count 1 \
    --max-count 3 \
    --no-wait

在上一条命令中,Spot 中的 priority 使该节点池成为抢占式节点池。 参数 eviction-policy 设置为 Delete,这是默认值。 将逐出策略设置为 Delete 时,节点池的底层规模集中的节点会在被逐出时删除。

也可以将逐出策略设置为 Deallocate,这意味着底层规模集中的节点会在逐出时设置为 stopped-deallocated 状态。 处于 stopped-deallocated 状态的节点会占用你的计算配额,并可能导致群集扩缩容或升级出现问题。 priorityeviction-policy 值只能在创建节点池时设置。 以后不能更新这些值。

前一条命令还会启用集群自动扩缩容器,我们建议将其与 Spot 节点池配合使用。 根据群集中运行的工作负载,群集自动缩放程序将纵向扩展和缩减节点数。 对于现成节点池,如果仍需要更多节点,则群集自动缩放程序将在逐出之后纵向扩展节点数。 如果更改节点池可以具有的最大节点数,还需要调整与群集自动缩放程序关联的 maxCount 值。 如果不使用集群自动扩缩器,发生驱逐后,Spot 池最终会缩减到 0,并且需要手动操作才能获得任何额外的 Spot 节点。

重要

仅将可容忍中断的工作负载安排到 Spot 节点池上,例如批处理作业和测试环境。 建议在现成节点池上设置排斥和容许,确保仅在现成节点池上计划可处理节点逐出的工作负载。 例如,上述命令会添加一个污点 kubernetes.azure.com/scalesetpriority=spot:NoSchedule,因此只有具有相应容忍的 Pod 才会被调度到该节点上。

验证现成节点池

az aks nodepool show --resource-group $RESOURCE_GROUP --cluster-name $AKS_CLUSTER --name $SPOT_NODEPOOL

结果:

{
  "artifactStreamingProfile": null,
  "availabilityZones": null,
  "capacityReservationGroupId": null,
  "count": 3,
  "creationData": null,
  "currentOrchestratorVersion": "1.30.10",
  "eTag": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "enableAutoScaling": true,
  "enableCustomCaTrust": false,
  "enableEncryptionAtHost": false,
  "enableFips": false,
  "enableNodePublicIp": false,
  "enableUltraSsd": false,
  "gatewayProfile": null,
  "gpuInstanceProfile": null,
  "gpuProfile": null,
  "hostGroupId": null,
  "id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourcegroups/xxxxxxxxxxxxxxxx/providers/Microsoft.ContainerService/managedClusters/xxxxxxxxxxxxxxxx/agentPools/xxxxxxxxxxxx",
  "kubeletConfig": null,
  "kubeletDiskType": "OS",
  "linuxOsConfig": null,
  "maxCount": 3,
  "maxPods": 30,
  "messageOfTheDay": null,
  "minCount": 1,
  "mode": "User",
  "name": "xxxxxxxxxxxx",
  "networkProfile": {
    "allowedHostPorts": null,
    "applicationSecurityGroups": null,
    "nodePublicIpTags": null
  },
  "nodeImageVersion": "AKSUbuntu-2204gen2containerd-xxxxxxxx.xx.x",
  "nodeInitializationTaints": null,
  "nodeLabels": {
    "kubernetes.azure.com/scalesetpriority": "spot"
  },
  "nodePublicIpPrefixId": null,
  "nodeTaints": [
    "kubernetes.azure.com/scalesetpriority=spot:NoSchedule"
  ],
  "orchestratorVersion": "x.xx.xx",
  "osDiskSizeGb": 128,
  "osDiskType": "Managed",
  "osSku": "Ubuntu",
  "osType": "Linux",
  "podIpAllocationMode": null,
  "podSubnetId": null,
  "powerState": {
    "code": "Running"
  },
  "provisioningState": "Creating",
  "proximityPlacementGroupId": null,
  "resourceGroup": "xxxxxxxxxxxxxxxx",
  "scaleDownMode": "Delete",
  "scaleSetEvictionPolicy": "Delete",
  "scaleSetPriority": "Spot",
  "securityProfile": {
    "enableSecureBoot": false,
    "enableVtpm": false,
    "sshAccess": "LocalUser"
  },
  "spotMaxPrice": -1.0,
  "status": null,
  "tags": null,
  "type": "Microsoft.ContainerService/managedClusters/agentPools",
  "typePropertiesType": "VirtualMachineScaleSets",
  "upgradeSettings": {
    "drainTimeoutInMinutes": null,
    "maxSurge": null,
    "maxUnavailable": null,
    "nodeSoakDurationInMinutes": null,
    "undrainableNodeBehavior": null
  },
  "virtualMachineNodesStatus": null,
  "virtualMachinesProfile": null,
  "vmSize": "Standard_DS2_v2",
  "vnetSubnetId": null,
  "windowsProfile": null,
  "workloadRuntime": "OCIContainer"
}

计划 Pod 在现成节点上运行

若要将 Pod 调度到 Spot 节点上运行,您可以添加与应用于 Spot 节点的污点相对应的容忍和节点亲和性。

以下示例显示了 YAML 文件的一部分,该文件定义了与kubernetes.azure.com/scalesetpriority=spot:NoSchedule排斥相对应的容忍度以及与kubernetes.azure.com/scalesetpriority=spot标签相对应的节点亲和性(通过requiredDuringSchedulingIgnoredDuringExecutionpreferredDuringSchedulingIgnoredDuringExecution节点相关性规则在上一步中使用):

spec:
  containers:
  - name: spot-example
  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"
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 1
        preference:
          matchExpressions:
          - key: another-node-label-key
            operator: In
            values:
            - another-node-label-value

当你部署带有此容忍和节点亲和性的 Pod 时,Kubernetes 会成功地将该 Pod 调度到已应用该污点和标签的节点上。 在此示例中,以下规则适用:

  • 节点必须具有包含键kubernetes.azure.com/scalesetpriority的标签,并且该标签的值必须spot
  • 节点最好具有包含键another-node-label-key的标签,并且该标签的值必须another-node-label-value

如需了解更多信息,请参阅将 Pod 分配给节点

升级现成节点池

升级现成节点池时,AKS 会在内部发出隔离和逐出通知,但不应用清空。 没有激增节点可用于现成节点池升级。 除这些变更外,升级 Spot 节点池时的行为与其他节点池类型的行为一致。

有关升级的详细信息,请参阅升级 AKS 群集

后续步骤

在本文中,你已了解如何将 Spot 节点池添加到 AKS 群集。 有关如何在节点池之间管理 Pod 的详细信息,请参阅AKS 中高级调度器功能的最佳做法