使用 HPA 将 GKE 工作负载扩缩至零或从零扩缩

本教程介绍了如何通过配置工作负载,使其在空闲时自动扩缩到零个副本,并在需求增加时扩缩回来,从而优化 Google Kubernetes Engine (GKE) 中的资源利用率。此方法将 Pod 横向自动伸缩器 (HPA) 与 GKE 的托管自动伸缩基础设施集成,以根据外部指标管理伸缩。

通过将 minReplicas 字段的值设置为 0,并在 HPA 清单中定义 ExternalObject 类型的指标,将部署配置为扩缩到零。 GKE 通过 AutoscalingMetric 自定义资源监控这些指标,这有助于确保为应用高效管理资源。

使用此配置,您无需使用 KEDA 等第三方指标适配器来扩缩 GKE 工作负载。此解决方案直接在 GKE 控制平面中管理指标提取和伸缩建议,从而减少集群管理开销。

在本教程中,您将部署一个示例异步工作器应用,该应用可处理来自 Pub/Sub 队列的消息。您可以使用 AutoscalingMetric 自定义资源配置 Pod 横向自动扩缩器,以监控队列深度 (pubsub.googleapis.com:num_undelivered_messages):

  • 当订阅中收到消息时:GKE 会纵向扩容工作器 Pod 以处理队列。
  • 当队列为空时:GKE 会自动将工作器 Deployment 缩减至零个副本。

本教程适用于希望通过在工作负载处于空闲状态时将其伸缩为零来优化 GKE 中的资源用量的应用开发者、平台管理员和运维人员,以及 DevOps。

注意事项

在配置工作负载以缩放到零之前,请查看以下注意事项:

  • 使用 HPA 将工作负载扩缩到零或从零扩缩需要 GKE 集群控制平面和节点在新的集群和升级的现有集群中运行 1.37 版或更高版本。如果您使用现有集群,请验证其版本,或将集群或其节点升级到 1.37 版或更高版本。
  • 您的 HPA 清单必须使用 apiVersion: autoscaling/v2 配置才能支持 minReplicas: 0 设置和外部指标。
  • 在将节点池降级到 1.37 之前的版本之前,请更新所有配置为从零开始扩缩的 HPA 清单,方法是将 minReplicas 字段设置为 1 或更低值。低于 1.37 的版本不支持 minReplicas: 0 设置,这可能会导致工作负载一直卡在零个副本的状态。
  • 您必须在 Pod 横向自动扩缩器中配置至少一个 ExternalObject 指标(例如队列深度)。当工作负载的 Pod 数量为零时,GKE 无法收集 CPU 或内存 (Resource) 指标,因此仅凭资源指标无法触发从零开始的扩容。
  • AutoscalingMetric、HorizontalPodAutoscaler 和目标 Deployment 必须位于同一 Kubernetes 命名空间中。

准备工作

  1. 安装 Google Cloud CLI。

  2. 配置 gcloud CLI 以使用您的联合身份。

    如需了解详情,请参阅使用联合身份登录 gcloud CLI

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

    gcloud init
  4. 创建或选择 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 项目名称。

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

  6. 启用 GKE 和 Pub/Sub API:

    启用 API 所需的角色

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

    gcloud services enable container.googleapis.com pubsub.googleapis.com

所需的角色

如需获得完成本教程所需的权限,请让您的管理员为您授予项目的以下 IAM 角色:

如需详细了解如何授予角色,请参阅管理对项目、文件夹和组织的访问权限

您也可以通过自定义角色或其他预定义角色来获取所需的权限。

设置环境

为简单起见,本教程中的命令会在单个 Google Cloud 项目 (PROJECT_ID) 中创建所有资源(GKE 集群以及 Pub/Sub 主题和订阅)。

如需设置您的环境,请按以下步骤操作:

  1. 设置环境变量:

    export PROJECT_ID=PROJECT_ID
    export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format 'get(projectNumber)')
    export LOCATION=LOCATION
    

    替换以下内容:

    • PROJECT_ID:您的 Google Cloud项目 ID
    • LOCATION:您要在其中创建 GKE 集群的区域或可用区,例如 us-central1。对于 Autopilot 集群,请指定一个区域。
  2. 创建一个运行 1.37 或更高版本的 GKE 集群,并启用适用于 GKE 的工作负载身份联合。 我们建议您使用 Autopilot 集群获得全代管式 Kubernetes 体验,并在工作负载扩缩为零时最大限度地节省费用。如需选择最适合您的工作负载的操作模式,请参阅选择 GKE 操作模式

    Autopilot

    创建 Autopilot 集群:

    gcloud container clusters create-auto scale-to-zero \
        --project=${PROJECT_ID} \
        --location=${LOCATION}
    

    Autopilot 集群默认启用 Workload Identity Federation for GKE。

    标准

    创建一个启用了 Workload Identity Federation for GKE 的 Standard 集群:

    gcloud container clusters create scale-to-zero \
        --project=${PROJECT_ID} \
        --location=${LOCATION} \
        --workload-pool=${PROJECT_ID}.
    
  3. 配置 kubectl 以与您的集群通信:

    gcloud container clusters get-credentials scale-to-zero \
        --project=${PROJECT_ID} \
        --location=${LOCATION}
    

创建 Pub/Sub 资源

本教程以 Pub/Sub 队列深度为例,说明如何使用外部指标源。

如需创建 Pub/Sub 主题和订阅,请按以下步骤操作:

  1. 创建 Pub/Sub 主题:

    gcloud pubsub topics create my-worker-topic \
        --project=${PROJECT_ID}
    
  2. 创建附加到主题的订阅:

    gcloud pubsub subscriptions create my-worker-subscription \
        --topic=my-worker-topic \
        --project=${PROJECT_ID}
    

设置 Workload Identity Federation for GKE

配置 Workload Identity Federation for GKE,以允许工作器应用通过 Google Cloud API 进行身份验证并使用来自 Pub/Sub 的消息。

GKE 会自动处理同一项目中 AutoscalingMetric 资源的 Cloud Monitoring 身份验证。如需详细了解如何定义用于自动扩缩的指标,请参阅从 Cloud Monitoring 中提取自定义指标或外部指标

如需为工作器工作负载配置 Workload Identity Federation for GKE,请按以下步骤操作:

  1. default 命名空间中为工作器应用创建 Kubernetes 服务账号:

    kubectl create serviceaccount async-worker-sa \
        --namespace default
    
  2. roles/pubsub.subscriber 角色授予 Kubernetes 服务账号,以便应用可以从您的 Pub/Sub 订阅接收消息:

    gcloud projects add-iam-policy-binding projects/${PROJECT_ID} \
        --role=roles/pubsub.subscriber \
        --member=principal://iam.googleapis.com/projects/${PROJECT_NUMBER}/locations/global/workloadIdentityPools/${PROJECT_ID}./subject/ns/default/sa/async-worker-sa
    

如需了解详情,请参阅将应用配置为使用 Workload Identity Federation for GKE

创建示例 Deployment

在创建 HPA 对象之前,您必须先创建其要监控的工作负载。

如需创建示例 Deployment,请按照以下步骤操作:

  1. 将以下清单保存为 async-worker.yaml

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: async-worker
      namespace: default
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: async-worker
      template:
        metadata:
          labels:
            app: async-worker
        spec:
          containers:
          - name: async-worker
            image: nginx:latest
            ports:
            - containerPort: 80
            resources:
              limits:
                memory: 100Mi
              requests:
                cpu: 50m
                memory: 100Mi
    
  2. 应用 async-worker.yaml Deployment:

    kubectl apply -f async-worker.yaml
    

配置工作负载以实现从零开始扩缩和缩减至零

在本部分中,您将配置 async-worker Deployment,以便在 Pub/Sub 队列为空时将其缩容为零,并在有新消息到达时将其重新扩大。

创建 AutoscalingMetric 资源

如需定义 GKE 监控的外部信号,请创建 AutoscalingMetric 自定义资源。在以下示例清单中,指标会查询 Cloud Monitoring,以获取 my-worker-subscription 订阅中未传送的 Pub/Sub 消息的数量。

如需创建 AutoscalingMetric 资源,请按以下步骤操作:

  1. 将以下清单保存为 pubsub-metric.yaml 文件:

    apiVersion: autoscaling.gke.io/v1beta1
    kind: AutoscalingMetric
    metadata:
      name: pubsub-queue-depth
      namespace: default
    spec:
      metrics:
      - promql:
          name: pubsub-undelivered
          query: >
              {
                "pubsub.googleapis.com/subscription/num_undelivered_messages",
                subscription_id="my-worker-subscription"
              }
    
  2. 应用 pubsub-metric.yaml 清单:

    kubectl apply -f pubsub-metric.yaml
    
  3. 验证指标状态并检索指标标识符:

    kubectl describe autoscalingmetric pubsub-queue-depth
    

    在输出的 Status 部分,验证是否未列出任何错误,并记下 autoscaling.gke.io|CUSTOM_RESOURCE_NAME|METRIC_NAME 格式的 Hpa Name 值。您将在下一部分中创建 HorizontalPodAutoscaler 对象时引用此外部指标标识符。 如果 Status 部分报告配置错误,或者未按预期检索到指标,请参阅排查为自动扩缩功能提取的指标

配置 Pod 横向自动扩缩器

如需配置自动扩缩行为,请创建一个以 Deployment 为目标的 HorizontalPodAutoscaler 资源。

如需配置 Pod 横向自动扩缩器,请按以下步骤操作:

  1. 将以下清单保存为 worker-hpa.yaml 文件:

    apiVersion: autoscaling/v2
    kind: HorizontalPodAutoscaler
    metadata:
      name: async-worker-hpa
      namespace: default
    spec:
      scaleTargetRef:
        apiVersion: apps/v1
        kind: Deployment
        name: async-worker
      minReplicas: 0
      maxReplicas: 20
      metrics:
      - type: External
        external:
          metric:
            name: autoscaling.gke.io|pubsub-queue-depth|pubsub-undelivered
          target:
            type: AverageValue
            averageValue: "10"
    

    此清单配置了以下关键字段:

    • minReplicas: 0:启用缩减至零,允许控制器在需求降至零时将 Deployment 缩减到 0 个副本。
    • type: External:配置外部指标源,以便 HPA 可以在工作负载没有 Pod 时触发扩容。
    • name: autoscaling.gke.io|pubsub-queue-depth|pubsub-undelivered:通过使用 autoscaling.gke.io|CUSTOM_RESOURCE_NAME|METRIC_NAME 标识符格式,将 HPA 直接映射到上一步中创建的 AutoscalingMetric 资源。
  2. 应用 worker-hpa.yaml 清单:

    kubectl apply -f worker-hpa.yaml
    

验证零规模行为和条件

当 Pub/Sub 订阅中的所有消息都处理完毕后,Pod 横向自动扩缩器会评估零需求,并将 Deployment 缩减为 0 个副本。

如需验证水平 Pod 自动扩缩器是否已启动零状态,请运行以下命令来检查 async-worker-hpa 资源的状态条件:

kubectl describe hpa async-worker-hpa

输出类似于以下内容:

Name:             async-worker-hpa
Namespace:        default
Reference:        Deployment/async-worker
Metrics:          ( current / target )
  "autoscaling.gke.io|pubsub-queue-depth|pubsub-undelivered" (external metric):  0 / 10
Min replicas:     0
Max replicas:     20
Deployment pods:  0 current / 0 desired
Conditions:
  Type            Status  Reason               Message
  ----            ------  ------               -------
  AbleToScale     True    SucceededGetScale    the HPA controller was able to get the target's current scale
  ScalingActive   True    ValidMetricFound     the HPA was able to successfully calculate a replica count from external metric
  ScaledToZero    True    ScaledToZero         the HPA has scaled the target resource to 0 replicas due to zero metric demand

了解 ScaledToZero 条件

ScaledToZero 条件表示 Pod 横向自动扩缩器是否已将工作负载缩减至零个副本:

  • ScaledToZero: True (Reason: ScaledToZero):表示 HPA 控制器已成功将工作负载扩缩到 0 个副本,因为外部指标需求降至零。HPA 保持活跃状态 (ScalingActive: True),并持续轮询 GKE 以检测工作负载需求何时增加。
  • ScaledToZero: False:表示工作负载已扩缩为一个或多个副本。

如果您手动将 Deployment 扩缩为零个副本(例如,使用 kubectl scale --replicas=0 命令),HPA 会暂停自动扩缩 (ScalingActive: False),以防止发生冲突的更改。如需恢复自动扩缩,请将部署扩缩回一个或多个副本 (kubectl scale deployment async-worker --replicas=1)。

如需了解工作负载无法缩减至零或无法从零向上扩容的故障排除方案,请参阅使用 HPA 排查 GKE 工作负载伸缩至零和从零伸缩的问题。如果 Pod 横向自动扩缩器报告外部指标缺失或无效,请参阅排查为自动扩缩提取的指标

清理

为避免因本教程中使用的资源导致您的 Google Cloud 账号产生费用,请按照以下步骤操作:

  1. 删除 GKE 集群:

    gcloud container clusters delete scale-to-zero \
        --project=${PROJECT_ID} \
        --location=${LOCATION}
    
  2. 删除 Pub/Sub 订阅和主题:

    gcloud pubsub subscriptions delete my-worker-subscription \
        --project=${PROJECT_ID}
    gcloud pubsub topics delete my-worker-topic \
        --project=${PROJECT_ID}
    

后续步骤