在 Azure Kubernetes 服务 (AKS) 中管理群集的节点池

在 Azure Kubernetes 服务 (AKS) 中,采用相同配置的节点分组成节点池。 这些节点池包含运行应用程序的底层 VM。 创建 AKS 群集时,需要定义初始节点数及其大小 (SKU)。 随着应用程序需求的变化,可能需要更改节点池上的设置。 例如,可能需要缩放节点池中的节点数,或者升级节点池的 Kubernetes 版本。

本文介绍如何在 AKS 群集中管理一个或多个节点池。

开始之前

限制

创建和管理支持多个节点池的 AKS 群集时存在以下限制:

  • 请参阅 Azure Kubernetes 服务 (AKS) 中可用的配额、虚拟机大小限制和区域
  • 系统池必须至少包含一个节点,而用户节点池则可能包含零个或零个以上的节点。
  • 创建节点池后,无法更改其 VM 大小。
  • 在创建群集的过程中创建多个节点池时,节点池使用的所有 Kubernetes 版本都必须与已为控制平面设置的版本相匹配。 可在使用按节点池操作预配群集后进行更新。
  • 不能在群集或节点池上同时运行升级和缩放操作。 如果尝试同时运行它们,会收到错误。 必须先在目标资源上完成一个操作类型,然后再在同一资源上执行下一个请求。 有关详细信息,请参阅故障排除指南

升级单个节点池

注意

节点池的 OS 映像版本与群集的 Kubernetes 版本相关联。 只能在群集升级后进行 OS 映像升级。

在此示例中,我们将升级 mynodepool 节点池。 由于有两个节点池,因此必须使用 az aks nodepool upgrade 命令进行升级。

  1. 使用 az aks get-upgrades 命令检查是否有任何升级可用。

    az aks get-upgrades --resource-group myResourceGroup --name myAKSCluster
    
  2. 使用 az aks nodepool upgrade 命令升级 mynodepool 节点池。

    az aks nodepool upgrade \
        --resource-group myResourceGroup \
        --cluster-name myAKSCluster \
        --name mynodepool \
        --kubernetes-version KUBERNETES_VERSION \
        --no-wait
    
  3. 使用 az aks nodepool list 命令列出节点池的状态。

    az aks nodepool list -g myResourceGroup --cluster-name myAKSCluster
    

    以下示例输出显示 mynodepool 的状态为“正在升级”:

    [
      {
        ...
        "count": 3,
        ...
        "name": "mynodepool",
        "orchestratorVersion": "KUBERNETES_VERSION",
        ...
        "provisioningState": "Upgrading",
        ...
        "vmSize": "Standard_DS2_v2",
        ...
      },
      {
        ...
        "count": 2,
        ...
        "name": "nodepool1",
        "orchestratorVersion": "1.15.7",
        ...
        "provisioningState": "Succeeded",
        ...
        "vmSize": "Standard_DS2_v2",
        ...
      }
    ]
    

    将节点升级到指定的版本需要花费几分钟时间。

最佳做法是将 AKS 群集中的所有节点池升级到相同的 Kubernetes 版本。 az aks upgrade 的默认行为是将所有节点池连同控制平面一起升级,以实现这种一致性。 升级单个节点池的功能可让你执行滚动升级,并在节点池之间计划 pod,使应用程序的正常运行时间保持在上述约束范围内。

升级包含多个节点池的群集控制平面

注意

Kubernetes 使用标准的语义化版本控制方案。 版本号以 x.y.z 表示,其中,x 是主要版本,y 是次要版本,z 是修补程序版本。 例如,版本 1.12.6 中的 1 是主要版本,12 是次要版本,6 是修补程序版本。 控制平面和初始节点池的 Kubernetes 版本是在群集创建过程中设置的。 将其他节点池附加到群集后,可以设置其 Kubernetes 版本。 不同节点池的 Kubernetes 版本可能不同,节点池与控制平面的 Kubernetes 版本也可能不同。

AKS 群集包含两个具有关联 Kubernetes 版本的群集资源对象:

  1. 群集控制平面 Kubernetes 版本,以及
  2. 具有 Kubernetes 版本的节点池。

控制平面映射到一个或多个节点池。 升级操作的行为由你使用的 Azure CLI 命令来决定。

  • az aks upgrade 将群集中的控制平面和所有节点池升级到同一个 Kubernetes 版本。
  • 使用 --control-plane-only 标志的 az aks upgrade 仅升级群集控制平面,并使所有节点池保持不变。
  • az aks nodepool upgrade 仅升级具有指定 Kubernetes 版本的目标节点池。

升级验证规则

使用以下规则集对群集控制平面和节点池的 Kubernetes 升级进行验证:

  • 验证用于升级节点池的版本是否有效的规则

    • 节点池版本的主要版本必须与控制平面相同。
    • 节点池的次要版本必须在控制平面版本的两个次要版本范围内。
    • 节点池版本不能大于控制平面的 major.minor.patch 版本。
  • 验证升级操作提交情况的规则

    • 无法降级控制平面或节点池的 Kubernetes 版本。
    • 如果未指定节点池的 Kubernetes 版本,则行为由客户端决定。 在资源管理器模板中,声明回退到为节点池定义的现有版本。 如果未设置任何内容,它将使用要回退到的控制平面版本。
    • 不能在单个控制平面或节点池资源上同时提交多个操作。 可在给定时间升级或缩放控制平面或节点池。

手动缩放节点池

当应用程序工作负荷需求发生变化时,你可能需要缩放节点池中的节点数。 可以增加或减少节点数。

  1. 使用 az aks node pool scale 命令缩放节点池中的节点数。

    az aks nodepool scale \
        --resource-group myResourceGroup \
        --cluster-name myAKSCluster \
        --name mynodepool \
        --node-count 5 \
        --no-wait
    
  2. 使用 az aks node pool list 命令列出节点池的状态。

    az aks nodepool list -g myResourceGroup --cluster-name myAKSCluster
    

    以下示例输出显示 mynodepool 的状态为“正在缩放”,并显示新节点计数为 5:

    [
      {
        ...
        "count": 5,
        ...
        "name": "mynodepool",
        "orchestratorVersion": "1.15.7",
        ...
        "provisioningState": "Scaling",
        ...
        "vmSize": "Standard_DS2_v2",
        ...
      },
      {
        ...
        "count": 2,
        ...
        "name": "nodepool1",
        "orchestratorVersion": "1.15.7",
        ...
        "provisioningState": "Succeeded",
        ...
        "vmSize": "Standard_DS2_v2",
        ...
      }
    ]
    

    需要花费几分钟时间来完成缩放操作。

使用群集自动缩放程序来自动缩放特定节点池

AKS 提供了一项单独的功能,用于通过一项称为群集自动缩放程序的功能来自动缩放节点池。 对于每个节点池,可在唯一最大和最小缩放计数的情况下启用此功能。

有关详细信息,请参阅使用群集自动缩放程序

将产能预留组关联到节点池

随着工作负载需求的变化,可以将现有容量预留组关联到节点池,以确保为节点池分配的容量。

将产能预留组与 AKS 配合使用的先决条件

  • 使用 CLI 2.56(或更高版本)和 API 2023-10-01(或更高版本)。

  • 产能预留组应该已经存在,并且应包含至少一个产能预留,否则节点池会添加到群集并发出警告,并且不会关联任何产能预留组。 有关详细信息,请参阅 [容量预留组][capacity-reservation-groups]。

  • 需要为包含产能预留组 (CRG) 的资源组创建用户分配的托管标识。 系统分配的托管标识不适用于此功能。 在以下示例中,将环境变量替换为你自己的值。

    IDENTITY_NAME=myID
    RG_NAME=myResourceGroup
    CLUSTER_NAME=myAKSCluster
    VM_SKU=Standard_D4s_v3
    NODE_COUNT=2
    LOCATION=westus2
    az identity create --name $IDENTITY_NAME --resource-group $RG_NAME  
    IDENTITY_ID=$(az identity show --name $IDENTITY_NAME --resource-group $RG_NAME --query identity.id -o tsv)
    
  • 需要将 Contributor 角色分配给上面创建的用户分配的标识。 有关更多详细信息,请参阅分配 Azure 角色的步骤

  • 创建新的群集并分配新创建的标识。

      az aks create --resource-group $RG_NAME --name $CLUSTER_NAME --location $LOCATION \
          --node-vm-size $VM_SKU --node-count $NODE_COUNT \
          --assign-identity $IDENTITY_ID --enable-managed-identity         
    
  • 还可以使用 update 命令在现有托管群集上分配用户托管标识。

      az aks update --resource-group $RG_NAME --name $CLUSTER_NAME --location $LOCATION \
              --node-vm-size $VM_SKU --node-count $NODE_COUNT \
              --assign-identity $IDENTITY_ID --enable-managed-identity         
    

将现有产能预留组与节点池相关联

使用 az aks nodepool add 命令将现有产能预留组与节点池相关联,并使用 --crg-id 标志指定产能预留组。 以下示例假定你有一个名为“myCRG”的 CRG。

RG_NAME=myResourceGroup
CLUSTER_NAME=myAKSCluster
NODEPOOL_NAME=myNodepool
CRG_NAME=myCRG
CRG_ID=$(az capacity reservation group show --capacity-reservation-group $CRG_NAME --resource-group $RG_NAME --query id -o tsv)
az aks nodepool add --resource-group $RG_NAME --cluster-name $CLUSTER_NAME --name $NODEPOOL_NAME --crg-id $CRG_ID

将现有产能预留组与系统节点池相关联

若要将现有的产能预留组与系统节点池相关联,请在创建群集期间将群集与 CRG 上带参与者角色的用户分配的标识以及 CRG 本身相关联。 将 az aks create 命令与 --assign-identity--crg-id 标志配合使用。

IDENTITY_NAME=myID
RG_NAME=myResourceGroup
CLUSTER_NAME=myAKSCluster
NODEPOOL_NAME=myNodepool
CRG_NAME=myCRG
CRG_ID=$(az capacity reservation group show --capacity-reservation-group $CRG_NAME --resource-group $RG_NAME --query id -o tsv)
IDENTITY_ID=$(az identity show --name $IDENTITY_NAME --resource-group $RG_NAME --query identity.id -o tsv)
az aks create --resource-group $RG_NAME --cluster-name $CLUSTER_NAME --crg-id $CRG_ID --assign-identity $IDENTITY_ID --enable-managed-identity

注意

删除节点池会隐式取消节点池与任何关联的容量预留组的关联,然后再删除该节点池。 删除群集会隐式取消该群集中的所有节点池与其相关容量预留组的关联。

注意

无法更新具有产能预留组的现有节点组。 建议的方法是在创建节点池期间关联产能预留组。

指定节点池的 VM 大小

可能需要创建具有不同 VM 大小和容量的节点池。 例如,可以创建一个包含具有大量 CPU/内存的节点的节点池,或者创建一个提供 GPU 支持的节点池。 在下一部分中,使用排斥和容许来告知 Kubernetes 计划程序如何仅限可在这些节点上运行的 Pod 进行访问。

在以下示例中,将创建使用 Standard_NC6s_v3 VM 大小的基于 GPU 的节点池。 这些 VM 采用 NVIDIA Tesla K80 卡。 相关信息,请参阅 Azure 中的 Linux 虚拟机的可用大小

  1. 使用 az aks node pool add 命令创建节点池。 指定名称 gpunodepool,并使用 --node-vm-size 参数指定 Standard_NC6 大小。

    az aks nodepool add \
        --resource-group myResourceGroup \
        --cluster-name myAKSCluster \
        --name gpunodepool \
        --node-count 1 \
        --node-vm-size Standard_NC6s_v3 \
        --no-wait
    
  2. 使用 az aks nodepool list 命令检查节点池的状态。

    az aks nodepool list -g myResourceGroup --cluster-name myAKSCluster
    

    以下示例输出显示 gpunodepool 节点池正在创建具有指定 VmSize 的节点:

    [
      {
        ...
        "count": 1,
        ...
        "name": "gpunodepool",
        "orchestratorVersion": "1.15.7",
        ...
        "provisioningState": "Creating",
        ...
        "vmSize": "Standard_NC6s_v3",
        ...
      },
      {
        ...
        "count": 2,
        ...
        "name": "nodepool1",
        "orchestratorVersion": "1.15.7",
        ...
        "provisioningState": "Succeeded",
        ...
        "vmSize": "Standard_DS2_v2",
        ...
      }
    ]
    

    成功创建 gpunodepool 需要花费几分钟时间。

指定节点池的排斥、标签或标记

创建节点池时,可向它添加排斥、标签或标记。 添加排斥、标签或标记时,该节点池中的所有节点也会获取该排斥、标签或标记。

重要

应该使用 az aks nodepool 为整个节点池向节点添加排斥、标签或标记。 建议不要使用 kubectl 将排斥、标签或标记应用于节点池中的单个节点。

设置节点池排斥

  1. 使用 az aks nodepool add 命令创建具有排斥的节点池。 指定名称 taintnp,并使用 --node-taints 参数为排斥指定 sku=gpu:NoSchedule。

    az aks nodepool add \
        --resource-group myResourceGroup \
        --cluster-name myAKSCluster \
        --name taintnp \
        --node-count 1 \
        --node-taints sku=gpu:NoSchedule \
        --no-wait
    
  2. 使用 az aks nodepool list 命令检查节点池的状态。

    az aks nodepool list -g myResourceGroup --cluster-name myAKSCluster
    

    以下示例输出显示 taintnp 节点池正在创建具有指定 nodeTaints 的节点:

    [
      {
        ...
        "count": 1,
        ...
        "name": "taintnp",
        "orchestratorVersion": "1.15.7",
        ...
        "provisioningState": "Creating",
        ...
        "nodeTaints":  [
          "sku=gpu:NoSchedule"
        ],
        ...
      },
     ...
    ]
    

排斥信息将显示在 Kubernetes 中,以便于处理节点的计划规则。 Kubernetes 计划程序能够使用排斥和容许来限制可在节点上运行的工作负荷。

  • 排斥应用到指明了只能计划特定 pod 的节点。
  • 然后,将容许应用到可以容许节点排斥的 pod。

有关如何使用 Kubernetes 高级计划功能的详细信息,请参阅有关 AKS 中的高级计划程序功能的最佳做法

设置节点池容许

在上一步中,你在创建节点池时应用了 sku=gpu:NoSchedule 排斥。 以下示例 YAML 清单使用容许来允许 Kubernetes 计划程序在该节点池中的节点上运行 NGINX Pod。

  1. 创建名为 nginx-toleration.yaml 的文件,并将其复制到以下示例 YAML 中。

    apiVersion: v1
    kind: Pod
    metadata:
      name: mypod
    spec:
      containers:
     - image: mcr.azk8s.cn/oss/nginx/nginx:1.15.9-alpine
        name: mypod
        resources:
          requests:
            cpu: 100m
            memory: 128Mi
          limits:
            cpu: 1
            memory: 2G
      tolerations:
     - key: "sku"
        operator: "Equal"
        value: "gpu"
        effect: "NoSchedule"
    
  2. 使用 kubectl apply 命令计划 Pod。

    kubectl apply -f nginx-toleration.yaml
    

    只需花费几秒钟时间即可计划 pod 并提取 NGINX 映像。

  3. 使用 kubectl describe pod 命令验证状态。

    kubectl describe pod mypod
    

    以下精简示例输出显示已应用 sku=gpu:NoSchedule 容许。 在“事件”部分中,计划程序已将 Pod 分配到 aks-taintnp-28993262-vmss000000 节点:

    [...]
    Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                     node.kubernetes.io/unreachable:NoExecute for 300s
                     sku=gpu:NoSchedule
    Events:
      Type    Reason     Age    From                Message
      ----    ------     ----   ----                -------
      Normal  Scheduled  4m48s  default-scheduler   Successfully assigned default/mypod to aks-taintnp-28993262-vmss000000
      Normal  Pulling    4m47s  kubelet             pulling image "mcr.azk8s.cn/oss/nginx/nginx:1.15.9-alpine"
      Normal  Pulled     4m43s  kubelet             Successfully pulled image "mcr.azk8s.cn/oss/nginx/nginx:1.15.9-alpine"
      Normal  Created    4m40s  kubelet             Created container
      Normal  Started    4m40s  kubelet             Started container
    

    只能在 taintnp 中的节点上计划已应用此容许的 Pod。 任何其他 Pod 将在 nodepool1 节点池中计划。 如果创建更多节点池,可以使用污点和容忍来限制可在这些节点资源上计划的 pod。

设置节点池标签

有关详细信息,请参阅在 Azure Kubernetes 服务 (AKS) 群集中使用标签

设置节点池 Azure 标记

有关详细信息,请参阅在 Azure Kubernetes 服务 (AKS) 中使用 Azure 标记

使用资源管理器模板管理节点池

使用 Azure 资源管理器模板创建和管理资源时,可更改模板中的设置,然后重新部署它来更新资源。 对于 AKS 节点池,一旦创建 AKS 群集,就无法更新初始节点池配置文件。 此行为意味着无法更新现有的资源管理器模板、更改节点池,然后重新部署模板。 而是必须创建单独的资源管理器模板来更新现有 AKS 群集的节点池。

  1. 创建一个模板(例如 aks-agentpools.json),并粘贴到以下示例清单中。 请确保根据需要编辑值。 此示例模板配置以下设置:

    • 将名为 myagentpoolLinux 节点池更新为运行三个节点。
    • 将节点池中的节点设置为运行 Kubernetes 版本 1.15.7。
    • 将节点大小定义为 Standard_DS2_v2
    {
        "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
        "contentVersion": "1.0.0.0",
        "parameters": {
            "clusterName": {
                "type": "string",
                "metadata": {
                    "description": "The name of your existing AKS cluster."
                }
            },
            "location": {
                "type": "string",
                "metadata": {
                    "description": "The location of your existing AKS cluster."
                }
            },
            "agentPoolName": {
                "type": "string",
                "defaultValue": "myagentpool",
                "metadata": {
                    "description": "The name of the agent pool to create or update."
                }
            },
            "vnetSubnetId": {
                "type": "string",
                "defaultValue": "",
                "metadata": {
                    "description": "The Vnet subnet resource ID for your existing AKS cluster."
                }
            }
        },
        "variables": {
            "apiVersion": {
                "aks": "2020-01-01"
            },
            "agentPoolProfiles": {
                "maxPods": 30,
                "osDiskSizeGB": 0,
                "agentCount": 3,
                "agentVmSize": "Standard_DS2_v2",
                "osType": "Linux",
                "vnetSubnetId": "[parameters('vnetSubnetId')]"
            }
        },
        "resources": [
            {
                "apiVersion": "2020-01-01",
                "type": "Microsoft.ContainerService/managedClusters/agentPools",
                "name": "[concat(parameters('clusterName'),'/', parameters('agentPoolName'))]",
                "location": "[parameters('location')]",
                "properties": {
                    "maxPods": "[variables('agentPoolProfiles').maxPods]",
                    "osDiskSizeGB": "[variables('agentPoolProfiles').osDiskSizeGB]",
                    "count": "[variables('agentPoolProfiles').agentCount]",
                    "vmSize": "[variables('agentPoolProfiles').agentVmSize]",
                    "osType": "[variables('agentPoolProfiles').osType]",
                    "type": "VirtualMachineScaleSets",
                    "vnetSubnetID": "[variables('agentPoolProfiles').vnetSubnetId]",
                    "orchestratorVersion": "1.15.7"
                }
            }
        ]
    }
    
  2. 使用 az deployment group create 命令部署模板。

    az deployment group create \
        --resource-group myResourceGroup \
        --template-file aks-agentpools.json
    

    提示

    可以通过在模板中添加 tag 属性,将标记添加到节点池,如以下示例所示:

    ...
    "resources": [
    {
      ...
      "properties": {
        ...
        "tags": {
          "name1": "val1"
        },
        ...
      }
    }
    ...
    

    更新 AKS 群集可能需要花费几分钟时间,具体取决于资源管理器模板中定义的节点池设置和操作。

后续步骤