根據指標最佳化 Pod 自動調度資源


本教學課程示範如何依據 Cloud Monitoring 提供的指標,自動調整 Google Kubernetes Engine (GKE) 工作負載的資源配置。

在本教學課程中,您可以根據下列其中一項指標設定自動調度:

Pub/Sub

Pub/Sub 待處理項目

根據外部指標調整規模,該指標會回報 Pub/Sub 訂閱項目中剩餘的未確認訊息數。這項功能可有效減少延遲,避免問題發生,但與根據 CPU 使用率自動調度資源相比,可能會使用相對較多的資源。

自訂指標

自訂 Prometheus 指標

根據自訂使用者定義指標進行擴縮,並透過 Google 代管的 Prometheus 以 Prometheus 格式匯出。Prometheus 指標必須為「Gauge」類型。

自動調度資源的根本目標,是在成本和延遲時間之間取得可接受的平衡。建議您嘗試結合這些指標和其他指標,找出適合自己的政策。

目標

本教學課程涵蓋下列工作:

  1. 如何部署自訂指標轉接器
  2. 如何從應用程式程式碼匯出指標。
  3. 如何在 Cloud Monitoring 介面中查看指標。
  4. 如何部署 HorizontalPodAutoscaler (HPA) 資源,以依據 Cloud Monitoring 指標調整應用程式的資源配置。

費用

在本文件中,您會使用 Google Cloud的下列計費元件:

如要根據預測用量估算費用,請使用 Pricing Calculator

初次使用 Google Cloud 的使用者可能符合免費試用資格。

完成本文所述工作後,您可以刪除已建立的資源,避免繼續計費。詳情請參閱清除所用資源一節。

事前準備

請依照下列步驟啟用 Kubernetes Engine API:
  1. 前往 Google Cloud 控制台的 Kubernetes Engine 頁面
  2. 建立或選取專案。
  3. 等待 API 和相關服務完成啟用。 這可能需要幾分鐘的時間。
  4. Make sure that billing is enabled for your Google Cloud project.

在進行本教學課程時,您可以使用 Cloud Shell,其中已預先安裝本教學課程所使用的 gcloudkubectl 指令列工具。如果使用的是 Cloud Shell,則不需要在工作站上安裝這些指令列工具。

如要使用 Cloud Shell:

  1. 前往Google Cloud 控制台
  2. 按一下主控台視窗頂端的「啟用 Cloud Shell」啟動 Shell 按鈕 Google Cloud 按鈕。

    系統會在 Google Cloud 控制台底部的新頁框中開啟 Cloud Shell 工作階段,並顯示指令列提示。

    Cloud Shell 工作階段

正在設定環境

  1. 設定 Google Cloud CLI 的預設可用區:

    gcloud config set compute/zone zone
    

    更改下列內容:

    • zone:選擇距離您最近的區域。 詳情請參閱地區和區域一文。
  2. PROJECT_IDPROJECT_NUMBER 環境變數設為您的Google Cloud 專案 ID 和專案編號

    export PROJECT_ID=project-id
    export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format 'get(projectNumber)')
    
  3. 設定 Google Cloud CLI 的預設可用區:

    gcloud config set project $PROJECT_ID
    
  4. 建立 GKE 叢集

    最佳做法

    如要在存取 Google Cloud 服務時提升安全性,請在叢集上啟用 Workload Identity Federation for GKE。雖然本頁面包含使用舊版方法的範例 (已停用 Workload Identity Federation for GKE),但啟用這項功能可提升防護力。

    Workload Identity

    如要建立啟用 GKE 適用的工作負載身分聯盟的叢集,請執行下列指令:

    gcloud container clusters create metrics-autoscaling --workload-pool=$PROJECT_ID.svc.id.goog
    

    舊版驗證

    如要建立停用 Workload Identity Federation for GKE 的叢集,請執行下列指令:

    gcloud container clusters create metrics-autoscaling
    

部署自訂指標轉接器

自訂指標介面卡可讓叢集與 Cloud Monitoring 傳送及接收指標。

Pub/Sub

安裝 Custom Metrics Adapter 的程序會因叢集是否啟用 GKE 適用的工作負載身分聯盟而異。選取與建立叢集時所選設定相符的選項。

Workload Identity

授予使用者權限,使其能夠建立必要的授權角色:

kubectl create clusterrolebinding cluster-admin-binding \
    --clusterrole cluster-admin --user "$(gcloud config get-value account)"

在叢集上部署自訂指標轉接器:

kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/k8s-stackdriver/master/custom-metrics-stackdriver-adapter/deploy/production/adapter_new_resource_model.yaml

轉接器會使用 custom-metrics 命名空間中的 custom-metrics-stackdriver-adapter Kubernetes 服務帳戶。指派「監控檢視者」角色,允許這個服務帳戶讀取 Cloud Monitoring 指標:

gcloud projects add-iam-policy-binding projects/$PROJECT_ID \
  --role roles/monitoring.viewer \
  --member=principal://iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/$PROJECT_ID.svc.id.goog/subject/ns/custom-metrics/sa/custom-metrics-stackdriver-adapter

舊版驗證

授予使用者權限,使其能夠建立必要的授權角色:

kubectl create clusterrolebinding cluster-admin-binding \
    --clusterrole cluster-admin --user "$(gcloud config get-value account)"

在叢集上部署自訂指標轉接器:

kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/k8s-stackdriver/master/custom-metrics-stackdriver-adapter/deploy/production/adapter_new_resource_model.yaml

自訂指標

安裝 Custom Metrics Adapter 的程序會因叢集是否啟用 GKE 適用的工作負載身分聯盟而異。選取與建立叢集時所選設定相符的選項。

Workload Identity

授予使用者權限,使其能夠建立必要的授權角色:

kubectl create clusterrolebinding cluster-admin-binding \
    --clusterrole cluster-admin --user "$(gcloud config get-value account)"

在叢集上部署自訂指標轉接器:

kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/k8s-stackdriver/master/custom-metrics-stackdriver-adapter/deploy/production/adapter_new_resource_model.yaml

轉接器會使用 custom-metrics 命名空間中的 custom-metrics-stackdriver-adapter Kubernetes 服務帳戶。指派「監控檢視者」角色,允許這個服務帳戶讀取 Cloud Monitoring 指標:

gcloud projects add-iam-policy-binding projects/$PROJECT_ID \
  --role roles/monitoring.viewer \
  --member=principal://iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/$PROJECT_ID.svc.id.goog/subject/ns/custom-metrics/sa/custom-metrics-stackdriver-adapter

舊版驗證

授予使用者權限,使其能夠建立必要的授權角色:

kubectl create clusterrolebinding cluster-admin-binding \
    --clusterrole cluster-admin --user "$(gcloud config get-value account)"

在叢集上部署自訂指標轉接器:

kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/k8s-stackdriver/master/custom-metrics-stackdriver-adapter/deploy/production/adapter_new_resource_model.yaml

部署含有指標的應用程式

下載內含本教學課程應用程式程式碼的存放區:

Pub/Sub

git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples.git
cd kubernetes-engine-samples/databases/cloud-pubsub

自訂指標

git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples.git
cd kubernetes-engine-samples/observability/custom-metrics-autoscaling/google-managed-prometheus

存放區包含將指標匯出至 Cloud Monitoring 的程式碼:

Pub/Sub

這個應用程式會輪詢 Pub/Sub 訂閱項目的新訊息,並在收到訊息時確認。Cloud Monitoring 會自動收集 Pub/Sub 訂閱指標。

from google import auth
from google.cloud import pubsub_v1


def main():
    """Continuously pull messages from subsciption"""

    # read default project ID
    _, project_id = auth.default()
    subscription_id = 'echo-read'

    subscriber = pubsub_v1.SubscriberClient()
    subscription_path = subscriber.subscription_path(
        project_id, subscription_id)

    def callback(message: pubsub_v1.subscriber.message.Message) -> None:
        """Process received message"""
        print(f"Received message: ID={message.message_id} Data={message.data}")
        print(f"[{datetime.datetime.now()}] Processing: {message.message_id}")
        time.sleep(3)
        print(f"[{datetime.datetime.now()}] Processed: {message.message_id}")
        message.ack()

    streaming_pull_future = subscriber.subscribe(
        subscription_path, callback=callback)
    print(f"Pulling messages from {subscription_path}...")

    with subscriber:
        try:
            streaming_pull_future.result()
        except Exception as e:
            print(e)

自訂指標

這個應用程式會使用 Prometheus 格式,透過常數值指標回應 /metrics 路徑的任何網頁要求。

metric := prometheus.NewGauge(
	prometheus.GaugeOpts{
		Name: *metricName,
		Help: "Custom metric",
	},
)
prometheus.MustRegister(metric)
metric.Set(float64(*metricValue))

http.Handle("/metrics", promhttp.Handler())
log.Printf("Starting to listen on :%d", *port)
err := http.ListenAndServe(fmt.Sprintf(":%d", *port), nil)

存放區也包含 Kubernetes 資訊清單,可將應用程式部署到叢集。Deployment 是 Kubernetes API 物件,可讓您執行多個 Pod 副本,並將這些副本分散到叢集中的節點:

Pub/Sub

如果叢集啟用 Workload Identity Federation for GKE,資訊清單會有所不同。選取與建立叢集時所選設定相符的選項。

Workload Identity

apiVersion: apps/v1
kind: Deployment
metadata:
  name: pubsub
spec:
  selector:
    matchLabels:
      app: pubsub
  template:
    metadata:
      labels:
        app: pubsub
    spec:
      serviceAccountName: pubsub-sa
      containers:
      - name: subscriber
        image: us-docker.pkg.dev/google-samples/containers/gke/pubsub-sample:v2

舊版驗證

apiVersion: apps/v1
kind: Deployment
metadata:
  name: pubsub
spec:
  selector:
    matchLabels:
      app: pubsub
  template:
    metadata:
      labels:
        app: pubsub
    spec:
      volumes:
      - name: google-cloud-key
        secret:
          secretName: pubsub-key
      containers:
      - name: subscriber
        image: us-docker.pkg.dev/google-samples/containers/gke/pubsub-sample:v2
        volumeMounts:
        - name: google-cloud-key
          mountPath: /var/secrets/google
        env:
        - name: GOOGLE_APPLICATION_CREDENTIALS
          value: /var/secrets/google/key.json

自訂指標

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    run: custom-metrics-gmp
  name: custom-metrics-gmp
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      run: custom-metrics-gmp
  template:
    metadata:
      labels:
        run: custom-metrics-gmp
    spec:
      containers:
      # sample container generating custom metrics
      - name: prometheus-dummy-exporter
        image: us-docker.pkg.dev/google-samples/containers/gke/prometheus-dummy-exporter:v0.2.0
        command: ["./prometheus-dummy-exporter"]
        args:
        - --metric-name=custom_prometheus
        - --metric-value=40
        - --port=8080

透過 PodMonitoring 資源,Google Cloud Managed Service for Prometheus 會將 Prometheus 指標匯出至 Cloud Monitoring:

apiVersion: monitoring.googleapis.com/v1
kind: PodMonitoring
metadata:
  name: "custom-metrics-exporter"
spec:
  selector:
    matchLabels:
      run: custom-metrics-gmp
  endpoints:
  - port: 8080
    path: /metrics
    interval: 15s

從 GKE Standard 1.27 版或 GKE Autopilot 1.25 版開始,Google Cloud Managed Service for Prometheus 會啟用。如要在舊版叢集中啟用 Google Cloud Managed Service for Prometheus,請參閱「啟用代管收集作業」。

將應用程式部署至叢集:

Pub/Sub

如果叢集已啟用 Workload Identity Federation for GKE,應用程式部署程序會有所不同。選取與建立叢集時所選設定相符的選項。

Workload Identity

  1. 在專案中啟用 Pub/Sub API:

    gcloud services enable cloudresourcemanager.googleapis.com pubsub.googleapis.com
    
  2. 建立 Pub/Sub 主題和訂閱項目:

    gcloud pubsub topics create echo
    gcloud pubsub subscriptions create echo-read --topic=echo
    
  3. 將應用程式部署至叢集:

    kubectl apply -f deployment/pubsub-with-workload-identity.yaml
    
  4. 這個應用程式定義了 pubsub-sa Kubernetes 服務帳戶。指派「Pub/Sub 訂閱者」角色給該服務帳戶,讓應用程式可以將訊息發布至 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/pubsub-sa
    

    上述指令會使用主體 ID,讓 IAM 直接參照 Kubernetes 服務帳戶。

    最佳做法

    使用主體 ID,但請注意替代方法說明中的限制。

舊版驗證

  1. 在專案中啟用 Pub/Sub API:

    gcloud services enable cloudresourcemanager.googleapis.com pubsub.googleapis.com
    
  2. 建立 Pub/Sub 主題和訂閱項目:

    gcloud pubsub topics create echo
    gcloud pubsub subscriptions create echo-read --topic=echo
    
  3. 建立可存取 Pub/Sub 的服務帳戶:

    gcloud iam service-accounts create autoscaling-pubsub-sa
    gcloud projects add-iam-policy-binding $PROJECT_ID \
      --member "serviceAccount:autoscaling-pubsub-sa@$PROJECT_ID.iam.gserviceaccount.com" \
      --role "roles/pubsub.subscriber"
    
  4. 下載服務帳戶金鑰檔案:

    gcloud iam service-accounts keys create key.json \
      --iam-account autoscaling-pubsub-sa@$PROJECT_ID.iam.gserviceaccount.com
    
  5. 將服務帳戶金鑰匯入叢集做為 Secret

    kubectl create secret generic pubsub-key --from-file=key.json=./key.json
    
  6. 將應用程式部署至叢集:

    kubectl apply -f deployment/pubsub-with-secret.yaml
    

自訂指標

kubectl apply -f custom-metrics-gmp.yaml

稍待片刻,應用程式部署完成後,所有 Pod 都會達到 Ready 狀態:

Pub/Sub

kubectl get pods

輸出:

NAME                     READY   STATUS    RESTARTS   AGE
pubsub-8cd995d7c-bdhqz   1/1     Running   0          58s

自訂指標

kubectl get pods

輸出:

NAME                                  READY   STATUS    RESTARTS   AGE
custom-metrics-gmp-865dffdff9-x2cg9   1/1     Running   0          49s

在 Cloud Monitoring 中查看指標

應用程式執行時,會將指標寫入 Cloud Monitoring。

如要使用 Metrics Explorer 查看受監控資源的指標,請按照下列步驟操作:

  1. 前往 Google Cloud 控制台的 「Metrics Explorer」頁面:

    前往 Metrics Explorer

    如果您是使用搜尋列尋找這個頁面,請選取子標題為「Monitoring」的結果

  2. 在「指標」元素中,展開「選取指標」選單,然後選取資源類型和指標類型。舉例來說,如要繪製虛擬機器的 CPU 使用率圖表,請按照下列步驟操作:
    1. (選用) 如要減少選單選項,請在「篩選器」列中輸入部分指標名稱。在本例中,請輸入 utilization
    2. 在「Active resources」(有效資源) 選單中,選取「VM instance」(VM 執行個體)
    3. 在「Active metric categories」(使用中的指標類別) 選單中,選取「Instance」(執行個體)
    4. 在「有效指標」選單中,選取「CPU 使用率」,然後按一下「套用」
  3. 如要篩選顯示的時間序列,請使用篩選元素

  4. 如要合併時間序列,請使用「Aggregation」元素上的選單。 舉例來說,如要依據 VM 所在區域顯示 CPU 使用率,請將第一個選單設為「平均值」,第二個選單設為「區域」

    如果將「Aggregation」(匯總) 元素的第一個選單設為「Unaggregated」(未匯總),系統就會顯示所有時間序列。「匯總」元素的預設設定取決於您選取的指標類型。

資源類型和指標如下:

Pub/Sub

Metrics Explorer

資源類型:pubsub_subscription

指標:pubsub.googleapis.com/subscription/num_undelivered_messages

自訂指標

Metrics Explorer

資源類型:prometheus_target

指標:prometheus.googleapis.com/custom_prometheus/gauge

視指標而定,您可能還不會在 Cloud Monitoring Metrics Explorer 中看到太多活動。如果指標沒有更新,請別感到意外。

建立 HorizontalPodAutoscaler 物件

在 Cloud Monitoring 中看到指標後,您可以部署 HorizontalPodAutoscaler,根據指標調整部署大小。

Pub/Sub

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: pubsub
spec:
  minReplicas: 1
  maxReplicas: 5
  metrics:
  - external:
      metric:
       name: pubsub.googleapis.com|subscription|num_undelivered_messages
       selector:
         matchLabels:
           resource.labels.subscription_id: echo-read
      target:
        type: AverageValue
        averageValue: 2
    type: External
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: pubsub

自訂指標

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: custom-metrics-gmp-hpa
  namespace: default
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: custom-metrics-gmp
  minReplicas: 1
  maxReplicas: 5
  metrics:
  - type: Pods
    pods:
      metric:
        name: prometheus.googleapis.com|custom_prometheus|gauge
      target:
        type: AverageValue
        averageValue: 20

HorizontalPodAutoscaler 部署至叢集:

Pub/Sub

kubectl apply -f deployment/pubsub-hpa.yaml

自訂指標

kubectl apply -f custom-metrics-gmp-hpa.yaml

產生負載

對於某些指標,您可能需要產生負載,才能觀察自動調度資源功能:

Pub/Sub

將 200 則訊息發布至 Pub/Sub 主題:

for i in {1..200}; do gcloud pubsub topics publish echo --message="Autoscaling #${i}"; done

自訂指標

不適用:本範例使用的程式碼會為自訂指標匯出 40 的常數值。HorizontalPodAutoscaler 設定的目標值為 20,因此會嘗試自動調度部署資源。

您可能需要稍候幾分鐘,HorizontalPodAutoscaler 才會回應指標變更。

觀察 HorizontalPodAutoscaler 擴充

您可以執行下列指令,檢查部署目前的備用資源數:

kubectl get deployments

指標傳播一段時間後,Deployment 會建立五個 Pod 來處理待處理事項。

您也可以執行下列指令,檢查 HorizontalPodAutoscaler 的狀態和最近的活動:

kubectl describe hpa

清除所用資源

如要避免系統向您的 Google Cloud 帳戶收取本教學課程中所用資源的相關費用,請刪除含有該項資源的專案,或者保留專案但刪除個別資源。

Pub/Sub

  1. 清除 Pub/Sub 訂閱與主題:

    gcloud pubsub subscriptions delete echo-read
    gcloud pubsub topics delete echo
    
  2. 刪除您的 GKE 叢集:

    gcloud container clusters delete metrics-autoscaling
    

自訂指標

刪除您的 GKE 叢集:

 gcloud container clusters delete metrics-autoscaling

後續步驟