使用 VPA 调整 HPA 工作负载的大小

本文档介绍了如何将 HPA 合理调整功能与 Pod 纵向自动伸缩器 (VPA) 和 Pod 横向自动伸缩器 (HPA) 搭配使用,以便在 Google Kubernetes Engine (GKE) 中伸缩工作负载副本时自动优化容器 CPU 请求和限制。

传统上,在同一指标(例如 CPU)上同时使用 Pod 横向自动伸缩器 (HPA) 和 Pod 纵向自动伸缩器 (VPA) 会产生伸缩冲突。之所以会发生这种冲突,是因为当 VPA 设置 Pod CPU 请求时,会更改 HPA 设置的使用率基准,这可能会导致意外的伸缩行为和过度预配。

通过 VPA 进行 HPA 调整,可让两个自动扩缩器在同一工作负载上协同运行。HPA 会继续通过伸缩 Pod 副本的数量来处理短期流量高峰。同时,VPA 会使用合理调整大小逻辑来考虑工作负载在一段时间内的汇总历史资源需求。它会考虑您的 HPA 配置(例如最小副本数、最大副本数和目标 CPU 利用率),以调整容器 CPU 请求,从而使工作负载在低流量期间保持经济实惠,并在高需求期间保持弹性。

资源处理和规模限制

配置 HPA 规模调整时,请考虑以下要求和限制:

  • 容量优化计算仅适用于 CPU。如果您在 VPA 配置中包含内存,VPA 会使用标准 VPA 逻辑调整内存请求和限制的大小。
  • HPA 规模调整功能支持具有一个主容器的 Pod。如果 Pod 还运行边车,则与主容器相比,边车的 CPU 使用率必须可以忽略不计,并且您必须通过在其容器政策中设置 mode: "Off" 来让边车停用 VPA。HPA 必须对 CPU 使用 Resource 指标类型;ContainerResource 指标类型仅支持具有单个容器的 Pod。
  • 您最多可以为单个集群中所有工作负载的 60,000 个容器配置 HPA 优化。
  • 单个 VerticalPodAutoscaler 最多可以定位 1,000 个容器。
  • VPA 仅针对容器级资源请求和限制 (spec.containers[].resources) 生成建议并应用更新。Pod 纵向自动扩缩不支持 Pod 级资源规范 (spec.resources)。

准备工作

  1. 登录您的 Google Cloud 账号。如果您是 Google Cloud新手,请 创建一个账号来评估我们的产品在实际场景中的表现。新客户还可获享 $300 赠金,用于运行、测试和部署工作负载。
  2. 安装 Google Cloud CLI。

  3. 如果您使用的是外部身份提供方 (IdP),则必须先 使用联合身份登录 gcloud CLI。

  4. 如需初始化 gcloud CLI,请运行以下命令:

    gcloud init
  5. 创建或选择 Google Cloud 项目。

    选择或创建项目所需的角色

    • 选择项目:选择项目不需要特定的 IAM 角色,您可以选择已获授角色的任何项目。
    • 创建项目:如需创建项目,您需要拥有 Project Creator 角色 (roles/resourcemanager.projectCreator),该角色包含 resourcemanager.projects.create 权限。了解如何授予角色。
    • 创建 Google Cloud 项目:

      gcloud projects create PROJECT_ID

      将 PROJECT_ID 替换为您要创建的 Google Cloud 项目的名称。

    • 选择您创建的 Google Cloud 项目:

      gcloud config set project PROJECT_ID

      将 PROJECT_ID 替换为您的 Google Cloud 项目名称。

  6. 验证是否已为您的 Google Cloud 项目启用结算功能。

  7. 启用 Google Kubernetes Engine API(如果尚未启用):

    启用 API 所需的角色

    如需启用 API,您需要拥有 serviceusage.services.enable 权限。如果您创建了项目,则可能已经通过 Owner 角色 (roles/owner) 拥有此权限。否则,您可以通过 Service Usage Admin 角色 (roles/serviceusage.serviceUsageAdmin) 获得此权限。了解如何授予角色。

    gcloud services enable container.googleapis.com
  8. 安装 Google Cloud CLI。

  9. 如果您使用的是外部身份提供方 (IdP),则必须先 使用联合身份登录 gcloud CLI。

  10. 如需初始化 gcloud CLI,请运行以下命令:

    gcloud init
  11. 创建或选择 Google Cloud 项目。

    选择或创建项目所需的角色

    • 选择项目:选择项目不需要特定的 IAM 角色,您可以选择已获授角色的任何项目。
    • 创建项目:如需创建项目,您需要拥有 Project Creator 角色 (roles/resourcemanager.projectCreator),该角色包含 resourcemanager.projects.create 权限。了解如何授予角色。
    • 创建 Google Cloud 项目:

      gcloud projects create PROJECT_ID

      将 PROJECT_ID 替换为您要创建的 Google Cloud 项目的名称。

    • 选择您创建的 Google Cloud 项目:

      gcloud config set project PROJECT_ID

      将 PROJECT_ID 替换为您的 Google Cloud 项目名称。

  12. 验证是否已为您的 Google Cloud 项目启用结算功能。

  13. 启用 Google Kubernetes Engine API(如果尚未启用):

    启用 API 所需的角色

    如需启用 API,您需要拥有 serviceusage.services.enable 权限。如果您创建了项目,则可能已经通过 Owner 角色 (roles/owner) 拥有此权限。否则,您可以通过 Service Usage Admin 角色 (roles/serviceusage.serviceUsageAdmin) 获得此权限。了解如何授予角色。

    gcloud services enable container.googleapis.com
  14. 向您的用户账号授予角色。对以下每个 IAM 角色运行以下命令一次: roles/container.admin, roles/container.developer

    gcloud projects add-iam-policy-binding PROJECT_ID --member="user:USER_IDENTIFIER" --role=ROLE

    替换以下内容:

    • PROJECT_ID:您的项目 ID。
    • USER_IDENTIFIER:您的用户账号的标识符。 例如 myemail@example.com。
    • ROLE:您向用户账号授予的 IAM 角色。
  15. 验证您的集群是否运行 GKE 1.36.3-gke.1630000 版或更高版本。
  16. 验证您的集群是否已启用 Pod 纵向自动扩缩。在 Autopilot 集群中,Pod 纵向自动扩缩默认处于启用状态。如需创建新的 Autopilot 集群,请参阅创建 Autopilot 集群。

    如果您使用的是 Standard 集群,请运行以下命令之一来启用 Pod 纵向自动扩缩:

    • 如需创建启用了 Pod 纵向自动扩缩的新 Standard 集群,请运行以下命令:
          gcloud container clusters create CLUSTER_NAME \
              --enable-vertical-pod-autoscaling \
              --location=LOCATION
          
    • 如需在现有 Standard 集群上启用 Pod 纵向自动扩缩,请运行以下命令:
          gcloud container clusters update CLUSTER_NAME \
              --enable-vertical-pod-autoscaling \
              --location=LOCATION
          

    替换以下内容:

    • CLUSTER_NAME:您的集群的名称。
    • LOCATION:集群的 Compute Engine 区域或可用区,例如 us-central1-a。

使用 HPA 和 VPA 规模调整功能部署工作负载

如需使用 VPA 配置 HPA 规模优化,您需要部署工作负载,创建以 CPU 利用率为目标的 HorizontalPodAutoscaler,并使用规模优化政策注解配置 VerticalPodAutoscaler。

为了让 Pod 纵向自动扩缩器有时间收集用量数据并生成准确的建议,同时不修改正在运行的 Pod,请使用分阶段部署方法:

  1. 部署工作负载并配置 HPA。
  2. 部署 VerticalPodAutoscaler,并将 updateMode 字段设置为 "Off",以观察建议。对于新工作负载或非生产关键型工作负载,您可以跳过此步骤。
  3. 经过几天的观察后,将 updateMode 字段更新为 "InPlaceOrRecreate" 或 "Recreate",以启用自动调整大小。VPA 会在几分钟内生成初始建议,但观察至少 24 小时到几天的时间可以让 VPA 捕获完整的流量周期。

部署示例工作负载和 HPA

  1. 将以下示例 Deployment 清单保存为 sample-app.yaml:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: sample-app
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: sample-app
      template:
        metadata:
          labels:
            app: sample-app
        spec:
          containers:
          - name: sample-app
            image: nginx
            resources:
              requests:
                cpu: 250m
                memory: 256Mi
    
  2. 运行以下命令,将清单应用于您的集群:

    kubectl apply -f sample-app.yaml
    
  3. 将以下 HorizontalPodAutoscaler 清单保存为 sample-app-hpa.yaml:

    apiVersion: autoscaling/v2
    kind: HorizontalPodAutoscaler
    metadata:
      name: sample-app-hpa
    spec:
      scaleTargetRef:
        apiVersion: apps/v1
        kind: Deployment
        name: sample-app
      minReplicas: 2
      maxReplicas: 10
      metrics:
      - type: Resource
        resource:
          name: cpu
          target:
            type: Utilization
            averageUtilization: 70
    
  4. 运行以下命令,将 HPA 清单应用于您的集群:

    kubectl apply -f sample-app-hpa.yaml
    

在“关闭”模式下观察建议

如需让 VerticalPodAutoscaler 对象分析历史资源需求并生成建议,而不调整 Pod 大小,请在 Off 模式下部署该对象。对于新工作负载或非生产关键型工作负载,您可以跳过本部分,改为部署 VerticalPodAutoscaler,并将 updateMode 字段设置为 "InPlaceOrRecreate" 或 "Recreate"。

  1. 将以下清单保存为 sample-app-vpa.yaml:

    apiVersion: autoscaling.k8s.io/v1
    kind: VerticalPodAutoscaler
    metadata:
      name: sample-app-vpa
      annotations:
        gke.io/autoscaling-hpa-rightsizing-mode: "gke-hpa-rightsizing-mode-policy"
    spec:
      targetRef:
        apiVersion: apps/v1
        kind: Deployment
        name: sample-app
      updatePolicy:
        updateMode: "Off"
      resourcePolicy:
        containerPolicies:
        - containerName: sample-app
          controlledResources: ["cpu", "memory"]
          minAllowed:
            cpu: 100m
            memory: 200Mi
          maxAllowed:
            cpu: 1000m
            memory: 1024Mi
    

    此清单会配置以下关键设置:

    • metadata.annotations 字段:包含 gke.io/autoscaling-hpa-rightsizing-mode: "gke-hpa-rightsizing-mode-policy",用于启用 HPA 规模优化。
    • spec.updatePolicy.updateMode 字段:设置为 "Off",以生成建议,而不更新容器资源请求。
    • spec.resourcePolicy.containerPolicies[].controlledResources 字段:指定 "cpu"(以及可选的 "memory")。
    • spec.resourcePolicy.containerPolicies[].minAllowed 和 maxAllowed 字段:定义边界限制,以防止 VPA 在您选择的资源限制之外调整容器大小。
  2. 运行以下命令,应用 VPA 清单:

    kubectl apply -f sample-app-vpa.yaml
    
  3. 让工作负载在典型流量模式下运行几天,以便 VPA 能够收集足够的指标来生成高可信度的建议。VPA 会在部署 VerticalPodAutoscaler 后的几分钟内生成初始建议,并在收集工作负载流量周期中的指标时对其进行优化。

启用自动调整大小

在观察建议并确认其符合您的应用要求后,启用自动调整大小。

  1. 在 sample-app-vpa.yaml 中,将 spec.updatePolicy.updateMode 字段更新为 "InPlaceOrRecreate":

    # ...other fields omitted for clarity...
    spec:
      updatePolicy:
        updateMode: "InPlaceOrRecreate"
    

    "InPlaceOrRecreate" 模式会以无中断方式更新 CPU 请求,而无需重启 Pod。如果您的工作负载还管理内存,并且您的应用运行时需要重启才能应用内存更改,请将 resizePolicy 添加到容器规范(restartPolicy: RestartContainer 表示内存)。或者,将 updateMode: "Recreate" 设置为在每次资源更新时重新创建 Pod。

  2. 运行以下命令,应用更新后的清单:

    kubectl apply -f sample-app-vpa.yaml
    

VPA 会根据工作负载需求自动将容器的 CPU 请求调整到最佳水平,而 HPA 会继续动态扩缩副本数量。

调整多容器工作负载的大小

如果您的工作负载在每个 Pod 中运行多个容器(例如一个主应用容器和一个或多个边车),则 HPA 会评估整个 Pod 的 CPU 利用率,而 VPA 仅调整主容器的大小。为了使 HPA 优化大小功能正常运行,HPA 测量的 Pod CPU 利用率必须与 VPA 调整大小的主容器的 CPU 利用率相匹配。为满足此要求,请按如下方式配置工作负载:

  • 与主容器相比,边车 CPU 使用率可以忽略不计,因此边车不会影响 HPA 测量的 Pod 利用率。仅当边车的 CPU 使用率可以忽略不计时,HPA 适配才支持边车。
  • 在 HPA 中使用 Resource 指标类型来表示 CPU,如部署示例工作负载和 HPA 中所示。对于具有多个容器的 Pod,HPA 规模优化不支持 ContainerResource 指标类型。如果 HPA 使用 ContainerResource 且 Pod 具有多个容器,则 VPA 不会为工作负载生成 CPU 建议。
  • 将 VPA 限制为主容器。为防止 VPA 评估边车,请在 spec.resourcePolicy.containerPolicies 中将每个边车的 mode 字段设置为 "Off":

    resourcePolicy:
      containerPolicies:
      - containerName: PRIMARY_CONTAINER_NAME
        controlledResources: ["cpu"]
      - containerName: SIDECAR_CONTAINER_NAME
        mode: "Off"
    

    替换以下内容:

    • PRIMARY_CONTAINER_NAME:主应用容器的名称。
    • SIDECAR_CONTAINER_NAME:要从规模调整中排除的边车容器的名称。为每个边车添加一个条目。

验证建议

如需检查 VPA 生成的建议,请运行以下命令:

kubectl describe vpa VPA_NAME

将 VPA_NAME 替换为 VerticalPodAutoscaler 的名称,例如 sample-app-vpa。

输出包含一个类似于以下内容的“Recommendation”部分:

Recommendation:
  Container Recommendations:
    Container Name:  sample-app
    Lower Bound:
      Cpu:     100m
      Memory:  200Mi
    Target:
      Cpu:     350m
      Memory:  256Mi
    Uncapped Target:
      Cpu:     350m
      Memory:  256Mi
    Upper Bound:
      Cpu:     1
      Memory:  1024Mi

在此输出中,查找以下字段:

  • Target:启用自动更新后,VPA 应用的建议 CPU 和内存请求。
  • Lower Bound:VPA 计算的资源请求建议下限。
  • Upper Bound:VPA 计算出的资源请求建议上限。
  • Uncapped Target:在应用 minAllowed 或 maxAllowed 限制条件之前由 VPA 计算的原始建议。

如需查看更详细的诊断日志,您可以在 Cloud Logging 中查看 VPA 决策日志。如需查看相关说明,请参阅查看 Pod 纵向自动扩缩事件和决策日志。

最佳做法和注意事项

将 HPA 规模调整与 VPA 搭配使用时,请考虑以下最佳实践:

  • 如果您使用 Argo CD 等持续交付工具,该工具可能会尝试将 VPA 所做的资源更改还原为清单值。某些工具支持配置忽略这些类型更改的设置,例如 Argo CD 具有 ignoreDifferences 属性。
  • 对于在初始启动期间出现 CPU 峰值的工作负载(例如 Java 应用),您可以将容量调整与 VPA CPU 启动加速相结合,在启动期间临时分配额外的 CPU,而不会影响稳态容量调整计算。
  • 对于具有边车的 Pod,请在 HPA 上使用 Resource 指标类型,并确保边车 CPU 使用率可以忽略不计。如需了解详情,请参阅调整多容器工作负载的大小。
  • 如需对工作负载停用 HPA 优化,请删除 VerticalPodAutoscaler 或将 spec.updatePolicy.updateMode 字段设置为 "Off"。请勿仅移除 gke.io/autoscaling-hpa-rightsizing-mode 注解,而将 updateMode 字段设置为 "InPlaceOrRecreate" 或 "Recreate"。如果仅移除注解,VPA 会还原为标准 VPA 行为,这可能会导致 HPA 和 VPA 发生冲突,从而造成伸缩不稳定。

后续步骤