根據指標最佳化 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. 確認專案已啟用計費功能 Google Cloud

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

如要使用 Cloud Shell:

  1. 前往Google Cloud 控制台
  2. 按一下主控台視窗頂端的「啟用 Cloud Shell」「Activate 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

    如要建立啟用 Workload Identity Federation for 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 的程序會因叢集是否啟用 Workload Identity Federation for 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 服務帳戶。指派「Monitoring 檢視者」角色,允許這個服務帳戶讀取 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 的程序會因叢集是否啟用 Workload Identity Federation for 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 服務帳戶。指派「Monitoring 檢視者」角色,允許這個服務帳戶讀取 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

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

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

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

  2. 在「指標」元素中,展開「選取指標」選單,然後選取資源類型和指標類型。舉例來說,如要繪製虛擬機器的 CPU 使用率圖表,請執行下列操作:
    1. (選用) 如要減少選單選項,請在「篩選列」中輸入部分指標名稱。在本範例中,請輸入 utilization
    2. 在「Active resources」(有效資源) 選單中,選取「VM instance」(VM 執行個體)
    3. 在「使用中的指標類別」選單中,選取「執行個體」
    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 擴充

您可以執行下列指令,檢查 Deployment 目前的副本數:

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

後續步驟