使用 HPA 將 GKE 工作負載擴充至零,或從零擴充

本教學課程說明如何在 Google Kubernetes Engine (GKE) 中,將工作負載設定為在閒置時自動縮減至零個副本,並在需求增加時擴充,藉此提高資源使用率。這種做法會將水平 Pod 自動調度器 (HPA)與 GKE 的受管理自動調度基礎架構整合,根據外部指標管理調度作業。

將 minReplicas 欄位的值設為 0,並在 HPA 資訊清單中定義 External 或 Object 類型的指標,即可將部署作業設定為縮減至零。 GKE 會透過 AutoscalingMetric 自訂資源監控這些指標,確保應用程式的資源管理效率。

使用這項設定時,您不需要使用第三方指標介面卡 (例如 KEDA) 調整 GKE 工作負載的資源配置。這項解決方案可直接在 GKE 控制層中管理指標擷取作業和調度建議,減少叢集管理負擔。

在本教學課程中,您將部署範例非同步工作者應用程式,處理 Pub/Sub 佇列中的訊息。您可以設定水平 Pod 自動配置器,使用 AutoscalingMetric 自訂資源監控佇列深度 (pubsub.googleapis.com:num_undelivered_messages):

  • 當訂閱項目收到訊息時:GKE 會擴大 worker Pod,處理佇列。
  • 佇列清空時:GKE 會自動將 worker 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 自動調度資源器中,至少設定一個 External 或 Object 指標 (例如佇列深度)。當工作負載的 Pod 數量為零時,GKE 無法收集 CPU 或記憶體 (Resource) 指標,因此單獨使用資源指標無法從零觸發擴充作業。
  • AutoscalingMetric、HorizontalPodAutoscaler 和目標 Deployment 必須位於相同的 Kubernetes 命名空間。

事前準備

  1. 登入 Google Cloud 帳戶。如果您是 Google Cloud新手,歡迎 建立帳戶,親自評估產品在實際工作環境中的成效。新客戶還能獲得價值 $300 美元的免費抵免額,可用於執行、測試及部署工作負載。
  2. 安裝 Google Cloud CLI。

  3. 若您採用的是外部識別資訊提供者 (IdP),請先 使用聯合身分登入 gcloud CLI。

  4. 執行下列指令,初始化 gcloud CLI:

    gcloud init
  5. 建立或選取 Google Cloud 專案。

    選取或建立專案所需的角色

    • 選取專案:選取專案時,不需要具備特定 IAM 角色,只要您在專案中獲派角色,即可選取該專案。
    • 建立專案:如要建立專案,您需要「專案建立者」角色 (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. 如果尚未啟用,請啟用 GKE 和 Pub/Sub API:

    啟用 API 時所需的角色

    如要啟用 API,您必須具備 serviceusage.services.enable 權限。如果您建立了專案,可能已透過「擁有者」角色 (roles/owner) 取得這項權限。否則,您可以透過「服務使用情形管理員」角色 (roles/serviceusage.serviceUsageAdmin) 取得這項權限。瞭解如何授予角色。

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

  9. 若您採用的是外部識別資訊提供者 (IdP),請先 使用聯合身分登入 gcloud CLI。

  10. 執行下列指令,初始化 gcloud CLI:

    gcloud init
  11. 建立或選取 Google Cloud 專案。

    選取或建立專案所需的角色

    • 選取專案:選取專案時,不需要具備特定 IAM 角色,只要您在專案中獲派角色,即可選取該專案。
    • 建立專案:如要建立專案,您需要「專案建立者」角色 (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. 如果尚未啟用,請啟用 GKE 和 Pub/Sub API:

    啟用 API 時所需的角色

    如要啟用 API,您必須具備 serviceusage.services.enable 權限。如果您建立了專案,可能已透過「擁有者」角色 (roles/owner) 取得這項權限。否則,您可以透過「服務使用情形管理員」角色 (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 叢集,並啟用 Workload Identity Federation for 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。

    標準

    建立 Standard 叢集,並啟用 Workload Identity Federation for GKE:

    gcloud container clusters create scale-to-zero \
        --project=${PROJECT_ID} \
        --location=${LOCATION} \
        --workload-pool=${PROJECT_ID}.svc.id.goog
    
  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

設定 GKE 適用的工作負載身分聯盟,允許工作應用程式向 Google Cloud API 進行驗證,並從 Pub/Sub 接收訊息。

對於同一專案中的 AutoscalingMetric 資源,GKE 會自動處理與 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}.svc.id.goog/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. 驗證指標狀態並擷取指標 ID:

    kubectl describe autoscalingmetric pubsub-queue-depth
    

    在輸出內容的 Status 區段,確認沒有列出任何錯誤,並記下 autoscaling.gke.io|CUSTOM_RESOURCE_NAME|METRIC_NAME 格式的 Hpa Name 值。您將在下一節建立 HorizontalPodAutoscaler 物件時,參照這個外部指標 ID。 如果「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}
    

後續步驟