你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

Azure Kubernetes 服务 (AKS) 中的垂直 Pod 自动缩放

本文概述 Azure Kubernetes 服务 (AKS) 中基于开源 Kubernetes 版本的垂直 Pod 自动缩放程序 (VPA)。 配置该程序后,它将根据过去的使用量自动设置每个工作负载中容器的资源请求和限制。 VPA 释放其他 Pod 的 CPU 和内存,并帮助有效利用 AKS 群集。

垂直 Pod 自动缩放提供一段时间内的资源使用情况建议。 若要管理资源使用量的突然增加,请使用水平 Pod 自动缩放程序,它可以根据需要缩放 Pod 副本数。

好处

垂直 Pod 自动缩放程序提供以下优势:

  • 分析应用程序所需的处理器和内存资源并将其调整为合适的大小。 VPA 不仅会根据一段时间内的资源使用量负责纵向扩展,而且还负责纵向缩减。

  • 如果某个 Pod 的缩放模式设置为“自动”或“重新创建”,当它需要更改其资源请求时,将逐出该 Pod。

  • 通过指定资源策略为单个容器设置 CPU 和内存限制

  • 确保节点中有适当的资源用于 Pod 调度

  • 对处理器或内存资源所做调整的日志记录可配置

  • 提高群集资源利用率并为其他 Pod 释放 CPU 和内存。

限制

  • 垂直 Pod 自动缩放支持每个群集上的最多 1,000 个关联的 VerticalPodAutoscaler 对象。

  • VPA 建议的资源可能多于群集中可用的资源。 因此,这会阻止 Pod 分配给节点并运行,因为节点没有足够的资源。 可以通过将 LimitRange 设置为每个命名空间的最大可用资源来克服此限制,这可确保 Pod 请求的资源不会超过指定。 此外,还可以设置 VerticalPodAutoscaler 对象中每个 Pod 允许的最大资源建议数。 请注意,VPA 无法完全克服节点资源不足的问题。 限制范围是固定的,但节点资源使用情况会动态更改。

  • 不建议将垂直 Pod 自动缩放程序与水平 Pod 自动缩放程序配合使用,后者根据相同的 CPU 和内存使用情况指标进行缩放。

  • VPA 推荐器最多只存储 8 天的历史数据。

  • VPA 不支持基于 JVM 的工作负载,因为对工作负载的实际内存使用情况的可见性有限。

  • 不建议或不支持将自己的 VPA 实现与 VPA 的此托管实现一起运行。 支持使用额外的或自定义的推荐器。

  • 不支持 AKS Windows 容器。

开始之前

  • AKS 群集正在运行 Kubernetes 版本 1.24 和更高版本。

  • 已安装并配置 Azure CLI 2.52.0 或更高版本。 运行 az --version 即可查找版本。 如果需要进行安装或升级,请参阅安装 Azure CLI

  • kubectl 应连接到要安装 VPA 的群集。

VPA 概述

API 对象

垂直 Pod 自动缩放程序是 Kubernetes 自动缩放 API 组中的一个 API 资源。 支持的版本是 0.11 或更高版本,可在 Kubernetes 自动缩放程序存储库中找到。

VPA 对象由三个组件组成:

  • 推荐器 - 它监视当前和过去的资源消耗,并基于它为容器的 CPU 和内存请求/限制提供建议值。 推荐器监视指标历史记录、内存不足 (OOM) 事件和 VPA 部署规范,并建议公平请求。 通过提供适当的资源请求和限制配置,可以提高和降低限制。

  • 更新程序 - 它会检查哪些托管 Pod 设置了正确的资源,如果未设置,则会将其终止,以便控制器可以使用更新的请求重新创建它们。

  • VPA 许可控制器 - 它为新 Pod 设置正确的资源请求(由其控制器创建或重新创建,因为更新程序的活动)。

VPA 许可控制器

VPA 许可控制器是一个二进制文件,用于将自身注册为可变许可 Webhook。 创建每个 Pod 后,它会从 apiserver 获取请求,并评估是否存在匹配的 VPA 配置,或者查找相应的配置,并使用当前建议在 Pod 中设置资源请求。

独立作业在 VPA 允许控制器外运行,称为 overlay-vpa-cert-webhook-checkoverlay-vpa-cert-webhook-check 用于创建和续订证书,并将 VPA 许可控制器注册为 MutatingWebhookConfiguration

为了获得高可用性,AKS 支持两个准入控制器副本。

VPA 对象操作模式

将为希望自动计算资源要求的每个控制器插入垂直 Pod 自动缩放程序资源。 这通常是部署。 有四种运行 VVA 的模式:

  • Auto - VPA 在 Pod 创建期间分配资源请求,并使用首选更新机制更新现有 Pod。 目前,Auto 等效于 Recreate,也是默认模式。 免费重启(“就地”)更新 Pod 请求可用后,Auto 模式可以将它用作首选更新机制。 使用 Recreate 模式时,如果 Pod 需要更改其资源请求,VPA 会逐出 Pod。 这可能会导致 Pod 一次性重启,从而导致应用程序不一致。 在这种情况下,可以使用 PodDisruptionBudget 限制重启并保持一致性。
  • Recreate - VPA 在 Pod 创建期间分配资源请求,并通过在请求的资源与遵循 Pod 中断预算的新建议(如果定义)明显不同时逐出现有 Pod 来更新这些请求。 仅当需要确保每当资源请求更改时重启 Pod 时,才应少量使用此模式。 否则,Auto 为首选模式,该模式在可用后可能会利用免重启更新。
  • Initial - VPA 仅在 Pod 创建期间分配资源请求,之后永远不会更改。
  • Off - VPA 不会自动更改 Pod 的资源要求。 建议经过计算,可以在 VPA 对象中检查。

应用程序开发期间的部署模式

如果不熟悉 VPA,建议使用一种常见部署模式,即在应用程序开发期间执行以下步骤,以确定其独特的资源利用率特征,测试 VPA 以验证它是否正常运行,并与其他 Kubernetes 组件一起测试以优化群集的资源利用率。

  1. 在生产群集中设置 UpdateMode = "Off",并在建议模式下运行 VPA,以便测试并熟悉 VPA。 UpdateMode = "Off" 可以避免引入可能导致中断的错误配置。

  2. 首先通过收集给定时间段内的实际资源利用率遥测数据来建立可观测性。 这有助于了解受容器和 Pod 资源上运行的工作负载影响的症状或问题的行为和迹象。

  3. 熟悉监视数据以了解性能特征。 根据此见解,相应地设置所需的请求/限制,然后在下一次部署或升级中

  4. 根据你的要求将 updateMode 值设为 AutoRecreateInitial

在群集上部署、升级或禁用 VPA

本部分介绍如何在群集上部署、升级或禁用垂直 Pod 自动缩放程序。

  1. 若要在新群集上启用 VPA,请将 --enable-vpa 参数与 az aks create 命令结合使用。

    az aks create -n myAKSCluster -g myResourceGroup --enable-vpa
    

    片刻之后,该命令将会完成,并返回有关群集的 JSON 格式信息。

  2. (可选)若要在现有群集上启用 VPA,请使用 --enable-vpa [https://learn.microsoft.com/en-us/cli/azure/aks?view=azure-cli-latest#az-aks-update] 命令。

    az aks update -n myAKSCluster -g myResourceGroup --enable-vpa 
    

    片刻之后,该命令将会完成,并返回有关群集的 JSON 格式信息。

  3. (可选)若要在现有群集上禁用 VPA,请使用 --disable-vpa [https://learn.microsoft.com/en-us/cli/azure/aks?view=azure-cli-latest#az-aks-update] 命令。

    az aks update -n myAKSCluster -g myResourceGroup --disable-vpa
    

    片刻之后,该命令将会完成,并返回有关群集的 JSON 格式信息。

  4. 若要验证垂直 Pod 自动缩放程序 Pod 是否已成功创建,请使用 kubectl get 命令。

kubectl get pods -n kube-system

该命令的输出包括以下特定于 VPA Pod 的结果。 Pod 应显示 running 状态。

NAME                                        READY   STATUS    RESTARTS   AGE
vpa-admission-controller-7867874bc5-vjfxk   1/1     Running   0          41m
vpa-recommender-5fd94767fb-ggjr2            1/1     Running   0          41m
vpa-updater-56f9bfc96f-jgq2g                1/1     Running   0          41m

测试垂直 Pod 自动缩放程序安装

以下步骤将创建包含两个 Pod 的部署,其中每个 Pod 运行单个容器,该容器请求 100 个毫核,并尝试利用数量略高于 500 的毫核。 这些步骤还会创建一个指向部署的 VPA 配置。 VPA 将观察 Pod 的行为,大约五分钟后,将通过更高的 CPU 请求更新 Pod。

  1. 创建名为 hamster.yaml 的文件,并将 kubernetes/autoscaler GitHub 存储库中垂直 Pod 自动缩放程序示例的以下清单复制到该文件中。

  2. 使用 kubectl apply 命令部署 hamster.yaml 垂直 Pod 自动缩放程序示例,并指定 YAML 清单的名称:

    kubectl apply -f hamster.yaml
    

    片刻之后,该命令将会完成,并返回有关群集的 JSON 格式信息。

  3. 运行以下 kubectl get 命令以从 hamster 示例应用程序中获取 Pod:

    kubectl get pods -l app=hamster
    

    示例输出如下所示:

    hamster-78f9dcdd4c-hf7gk   1/1     Running   0          24s
    hamster-78f9dcdd4c-j9mc7   1/1     Running   0          24s
    
  4. 对其中一个 Pod 使用 kubectl describe 命令以查看其 CPU 和内存预留量。 将“exampleID”替换为上一步骤的输出中返回的 Pod ID 之一。

    kubectl describe pod hamster-exampleID
    

    示例输出是有关群集的信息片段:

     hamster:
        Container ID:  containerd://
        Image:         k8s.gcr.io/ubuntu-slim:0.1
        Image ID:      sha256:
        Port:          <none>
        Host Port:     <none>
        Command:
          /bin/sh
        Args:
          -c
          while true; do timeout 0.5s yes >/dev/null; sleep 0.5s; done
        State:          Running
          Started:      Wed, 28 Sep 2022 15:06:14 -0400
        Ready:          True
        Restart Count:  0
        Requests:
          cpu:        100m
          memory:     50Mi
        Environment:  <none>
    

    在此示例中,Pod 预留了 100 millicpu(毫核 CPU)和 50 MiB 内存。 对于此示例应用程序,Pod 需要低于 100 millicpu 才能运行,因此没有可用的 CPU 容量。 此外,Pod 预留的内存也比需求量少得多。 垂直 Pod 自动缩放程序 vpa-recommender 部署将分析托管 hamster 应用程序的 Pod,以确定 CPU 和内存要求是否适当。 如果需要调整,vpa-updater 将使用更新的值重新启动 Pod。

  5. 等待 vpa-updater 启动新的 hamster Pod,这需要几分钟时间。 可以使用 kubectl get 命令监视 Pod。

    kubectl get --watch pods -l app=hamster
    
  6. 启动新的 hamster Pod 后,描述运行 kubectl describe 命令的 Pod 并查看已更新的 CPU 和内存预留量。

    kubectl describe pod hamster-<exampleID>
    

    示例输出是描述 Pod 的信息片段:

    State:          Running
      Started:      Wed, 28 Sep 2022 15:09:51 -0400
    Ready:          True
    Restart Count:  0
    Requests:
      cpu:        587m
      memory:     262144k
    Environment:  <none>
    

    在上面的输出中,可以看到 CPU 预留量已增加到 587 millicpu,这是原始值的五倍多。 内存已增加到 262,144 KB(大约 250 MiB),即原始值的五倍。 此 Pod 资源不足,而垂直 Pod 自动缩放程序使用一个更合适的值更正了估算值。

  7. 若要查看 VPA 提供的已更新建议,请运行 kubectl describe 命令来描述 hamster-vpa 资源信息。

    kubectl describe vpa/hamster-vpa
    

    示例输出是有关资源利用率的信息片段:

     State:          Running
      Started:      Wed, 28 Sep 2022 15:09:51 -0400
    Ready:          True
    Restart Count:  0
    Requests:
      cpu:        587m
      memory:     262144k
    Environment:  <none>
    

设置 Pod 自动缩放程序请求

当 updateMode 设置为 Auto 时,垂直 Pod 自动缩放使用 VerticalPodAutoscaler 对象在 Pod 上自动设置资源请求。可以根据要求和测试设置不同的值。 在此示例中,updateMode 设置为 Recreate

  1. 运行以下命令为群集启用 VPA。 将群集名称 myAKSCluster 替换为你的 AKS 群集名称,并将 myResourceGroup 替换为群集所在资源组的名称。

    az aks update -n myAKSCluster -g myResourceGroup --enable-vpa
    
  2. 创建名为 azure-autodeploy.yaml 的文件,并将其复制到以下清单中。

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: vpa-auto-deployment
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: vpa-auto-deployment
      template:
        metadata:
          labels:
            app: vpa-auto-deployment
        spec:
          containers:
          - name: mycontainer
            image: mcr.microsoft.com/oss/nginx/nginx:1.15.5-alpine
            resources:
              requests:
                cpu: 100m
                memory: 50Mi
            command: ["/bin/sh"]
            args: ["-c", "while true; do timeout 0.5s yes >/dev/null; sleep 0.5s; done"]
    

    此清单描述了包含两个 Pod 的部署。 每个 Pod 包含一个请求 100 milliCPU 和 50 MiB 内存的容器。

  3. 使用 kubectl create 命令创建 Pod,如以下示例所示:

    kubectl create -f azure-autodeploy.yaml
    

    片刻之后,该命令将会完成,并返回有关群集的 JSON 格式信息。

  4. 运行以下 kubectl get 命令以获取 Pod:

    kubectl get pods
    

    输出如以下示例所示,其中显示了 Pod 的名称和状态:

    NAME                                   READY   STATUS    RESTARTS   AGE
    vpa-auto-deployment-54465fb978-kchc5   1/1     Running   0          52s
    vpa-auto-deployment-54465fb978-nhtmj   1/1     Running   0          52s
    
  5. 创建名为 azure-vpa-auto.yaml 的文件,并将描述 VerticalPodAutoscaler 的以下清单复制到其中:

    apiVersion: autoscaling.k8s.io/v1
    kind: VerticalPodAutoscaler
    metadata:
      name: vpa-auto
    spec:
      targetRef:
        apiVersion: "apps/v1"
        kind:       Deployment
        name:       vpa-auto-deployment
      updatePolicy:
        updateMode: "Recreate"
    

    targetRef.name 值指定由名为 vpa-auto-deployment 的部署所控制的任何 Pod 都属于此 VerticalPodAutoscalerRecreateupdateMode 值表示垂直 Pod 自动缩放程序控制器可以删除 Pod,调整 CPU 和内存请求,然后启动新 Pod。

  6. 使用 kubectl apply 命令将清单应用于群集:

    kubectl create -f azure-vpa-auto.yaml
    
  7. 等待几分钟,然后运行以下 kubectl get 命令再次查看正在运行的 Pod:

    kubectl get pods
    

    输出如以下示例所示,其中显示了 Pod 名称已更改,并显示了 Pod 状态:

    NAME                                   READY   STATUS    RESTARTS   AGE
    vpa-auto-deployment-54465fb978-qbhc4   1/1     Running   0          2m49s
    vpa-auto-deployment-54465fb978-vbj68   1/1     Running   0          109s
    
  8. 使用 Kubectl get 命令获取有关正在运行的 Pod 的详细信息。 将 podName 替换为在上一步骤中检索的某个 Pod 的名称。

    kubectl get pod podName --output yaml
    

    输出如以下示例所示,其中显示了垂直 Pod 自动缩放程序控制器已将内存请求增加到 262144k,并已将 CPU 请求增加到 25 milliCPU。

    apiVersion: v1
    kind: Pod
    metadata:
      annotations:
        vpaObservedContainers: mycontainer
        vpaUpdates: 'Pod resources updated by vpa-auto: container 0: cpu request, memory
          request'
      creationTimestamp: "2022-09-29T16:44:37Z"
      generateName: vpa-auto-deployment-54465fb978-
      labels:
        app: vpa-auto-deployment
    
    spec:
      containers:
      - args:
        - -c
        - while true; do timeout 0.5s yes >/dev/null; sleep 0.5s; done
        command:
        - /bin/sh
        image: mcr.microsoft.com/oss/nginx/nginx:1.15.5-alpine
        imagePullPolicy: IfNotPresent
        name: mycontainer
        resources:
          requests:
            cpu: 25m
            memory: 262144k
    
  9. 若要获取有关垂直 Pod 自动缩放程序及其 CPU 和内存建议的详细信息,请使用 kubectl get 命令:

    kubectl get vpa vpa-auto --output yaml
    

    输出如以下示例所示:

     recommendation:
      containerRecommendations:
      - containerName: mycontainer
        lowerBound:
          cpu: 25m
          memory: 262144k
        target:
          cpu: 25m
          memory: 262144k
        uncappedTarget:
          cpu: 25m
          memory: 262144k
        upperBound:
          cpu: 230m
          memory: 262144k
    

    结果显示,target 属性指定无需更改 CPU 或内存目标即可使容器以最佳方式运行。 如果目标 CPU 和内存建议更高,结果可能有所不同。

    垂直 Pod 自动缩放程序使用 lowerBoundupperBound 属性来确定是否要删除 Pod 并将其替换为新 Pod。 如果 Pod 中的请求低于下限或高于上限,垂直 Pod 自动缩放程序会删除该 Pod,并将它替换为符合目标属性的 Pod。

垂直 Pod 自动缩放程序的额外推荐器

在 VPA 中,其中一个核心组件是推荐器。 它根据实时资源消耗提供资源使用情况建议。 群集启用 VPA 时,AKS 会部署推荐器。 可以使用与默认映像相同的映像部署自定义推荐器或额外推荐器。 使用自定义推荐器的好处是可以自定义建议逻辑。 使用额外的推荐器,如果有多个 VPA 对象,则可以将 VPA 分区为多个推荐器。

以下示例是应用于现有 AKS 群集的额外推荐器。 然后,将 VPA 对象配置为使用额外的推荐器。

  1. 创建名为 extra_recommender.yaml 的文件,并将以下清单复制到其中:

    apiVersion: apps/v1 
    kind: Deployment 
    metadata: 
      name: extra-recommender 
      namespace: kube-system 
    spec: 
      replicas: 1 
      selector: 
        matchLabels: 
          app: extra-recommender 
      template: 
        metadata: 
          labels: 
            app: extra-recommender 
        spec: 
          serviceAccountName: vpa-recommender 
          securityContext: 
            runAsNonRoot: true 
            runAsUser: 65534 # nobody 
          containers: 
          - name: recommender 
            image: registry.k8s.io/autoscaling/vpa-recommender:0.13.0 
            imagePullPolicy: Always 
            args: 
              - --recommender-name=extra-recommender 
            resources: 
              limits: 
                cpu: 200m 
                memory: 1000Mi 
              requests: 
                cpu: 50m 
                memory: 500Mi 
            ports: 
            - name: prometheus 
              containerPort: 8942 
    
  2. 使用 kubectl apply 命令部署 extra-recomender.yaml 垂直 Pod 自动缩放程序示例,并指定 YAML 清单的名称。

    kubectl apply -f extra-recommender.yaml 
    

    片刻之后,该命令将会完成,并返回有关群集的 JSON 格式信息。

  3. 创建名为 hamnster_extra_recommender.yaml 的文件,并将以下清单复制到其中:

    apiVersion: "autoscaling.k8s.io/v1" 
    kind: VerticalPodAutoscaler 
    metadata: 
      name: hamster-vpa 
    spec: 
      recommenders:  
        - name: 'extra-recommender' 
      targetRef: 
        apiVersion: "apps/v1" 
        kind: Deployment 
        name: hamster 
      updatePolicy: 
        updateMode: "Auto" 
      resourcePolicy: 
        containerPolicies: 
          - containerName: '*' 
            minAllowed: 
              cpu: 100m 
              memory: 50Mi 
            maxAllowed: 
              cpu: 1 
              memory: 500Mi 
            controlledResources: ["cpu", "memory"] 
    --- 
    apiVersion: apps/v1 
    kind: Deployment 
    metadata: 
      name: hamster 
    spec: 
      selector: 
        matchLabels: 
          app: hamster 
      replicas: 2 
      template: 
        metadata: 
          labels: 
            app: hamster 
        spec: 
          securityContext: 
            runAsNonRoot: true 
            runAsUser: 65534 # nobody 
          containers: 
            - name: hamster 
              image: k8s.gcr.io/ubuntu-slim:0.1 
              resources: 
                requests: 
                  cpu: 100m 
                  memory: 50Mi 
              command: ["/bin/sh"] 
              args: 
                - "-c" 
                - "while true; do timeout 0.5s yes >/dev/null; sleep 0.5s; done" 
    

    如果 memory 未在 controlledResources 中指定,则推荐器不会响应 OOM 事件。 在这种情况下,仅在 controlledValues 中设置 CPU。 controlledValues 允许选择是按 RequestsOnly 选项更新容器的资源请求,还是使用 RequestsAndLimits 选项同时更新资源请求和限制。 默认值为 RequestsAndLimits。 如果使用 RequestsAndLimits 选项,则会根据实际使用情况计算请求,并根据当前 Pod 的请求和限制比率计算限制。

    例如,如果从请求 2 个 CPU 且限制为 4 个 CPU 的 Pod 开始,则 VPA 始终将限制设置为请求数的两倍。 同一原则也适用于内存。 使用 RequestsAndLimits 模式时,它可以用作初始应用程序资源请求和限制的蓝图。

可以使用 CPU 和内存的自动模式和计算建议来简化 VPA 对象。

  1. 使用 kubectl apply 命令部署 hamster_extra-recomender.yaml 示例,并指定 YAML 清单的名称。

    kubectl apply -f hamster_customized_recommender.yaml
    
  2. 等待 vpa-updater 启动新的 hamster Pod,这需要几分钟时间。 可以使用 kubectl get 命令监视 Pod。

    kubectl get --watch pods -l app=hamster
    
  3. 启动新的 hamster Pod 后,描述运行 kubectl describe 命令的 Pod 并查看已更新的 CPU 和内存预留量。

    kubectl describe pod hamster-<exampleID>
    

    示例输出是描述 Pod 的信息片段:

    State:          Running
      Started:      Wed, 28 Sep 2022 15:09:51 -0400
    Ready:          True
    Restart Count:  0
    Requests:
      cpu:        587m
      memory:     262144k
    Environment:  <none>
    
  4. 若要查看 VPA 提供的已更新建议,请运行 kubectl describe 命令来描述 hamster-vpa 资源信息。

    kubectl describe vpa/hamster-vpa
    

    示例输出是有关资源利用率的信息片段:

    State:          Running
     Started:      Wed, 28 Sep 2022 15:09:51 -0400
    Ready:          True
    Restart Count:  0
    Requests:
      cpu:        587m
      memory:     262144k
    Environment:  <none>
    Spec:
      recommenders:
        Name: customized-recommender
    

疑难解答

若要诊断 VPA 安装问题,请执行以下步骤。

  1. 使用以下命令检查是否所有系统组件都在运行:

    kubectl --namespace=kube-system get pods|grep vpa
    

输出应列出三个 Pod - 推荐器、更新器和允许控制器,状态显示为 Running

  1. 确认系统组件是否记录任何错误。 对于上一个命令返回的每个 Pod,请运行以下命令:

    kubectl --namespace=kube-system logs [pod name] | grep -e '^E[0-9]\{4\}'
    
  2. 通过运行以下命令确认已创建自定义资源定义:

    kubectl get customresourcedefinition | grep verticalpodautoscalers
    

后续步骤

本文介绍了如何自动缩放群集节点的资源利用率(例如 CPU 和内存),以符合应用程序的要求。

  • 还可以使用水平 Pod 自动缩放程序自动调整运行应用程序的 Pod 数。 有关使用水平 Pod 自动缩放程序的步骤,请参阅在 AKS 中缩放应用程序

  • 请参阅垂直 Pod 自动缩放程序 [API 参考],详细了解相关 VPA 对象的定义。