本文說明如何為 Google Cloud Managed Service for Prometheus 啟用水平 Pod 自動調度資源 (HPA)。如要啟用 HPA,請執行下列其中一項操作:
- 使用 KEDA (Kubernetes 事件導向自動調度資源),這是從 Cloud Native Computing Foundation 畢業的開放原始碼解決方案。
- 使用 Google Cloud開發及支援的自訂指標 Stackdriver 轉接器程式庫。
- 使用第三方 Prometheus Adapter 程式庫。
您無法在同一個叢集中同時使用 Stackdriver 和 Prometheus 轉接器,因為兩者的資源定義會重疊,如「疑難排解」一文所述。建議您只為 HPA 選擇一個解決方案。
使用 KEDA
KEDA (Kubernetes Event-driven Autoscaling) 是最新發布的自動調度程式,使用 Prometheus 指標,並逐漸成為 Prometheus 社群偏好的解決方案。
如要開始使用,請參閱 KEDA 說明文件,瞭解如何與 Google Cloud Managed Service for Prometheus 整合。
使用自訂指標 Stackdriver 轉接器
自訂指標 Stackdriver 轉接器支援從 Managed Service for Prometheus 查詢指標,但須使用轉接器 v0.13.1 以上版本。
如要使用自訂指標 Stackdriver 轉接器設定 HPA 設定範例,請執行下列操作:
- 在叢集中設定代管集合。
在叢集中安裝自訂指標 Stackdriver 轉接器。
kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/k8s-stackdriver/master/custom-metrics-stackdriver-adapter/deploy/production/adapter_new_resource_model.yaml
部署範例 Prometheus 指標匯出工具和 HPA 資源:
kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/k8s-stackdriver/master/custom-metrics-stackdriver-adapter/examples/prometheus-to-sd/custom-metrics-prometheus-sd.yaml
這項指令會部署匯出工具應用程式,發出指標
foo
和 HPA 資源。HPA 會將這個應用程式擴充至 5 個副本,以達到指標foo
的目標值。如果您使用 Workload Identity Federation for GKE,也必須將 Monitoring 檢視者角色授予介面卡執行的服務帳戶。如果 Kubernetes 叢集未啟用 Workload Identity Federation for GKE,請略過這個步驟。
export PROJECT_NUMBER=$(gcloud projects describe PROJECT_ID --format 'get(projectNumber)') 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
在名為
podmonitoring.yaml
的檔案中加入下列設定,定義 PodMonitoring 資源。apiVersion: monitoring.googleapis.com/v1 kind: PodMonitoring metadata: name: prom-example spec: selector: matchLabels: run: custom-metric-prometheus-sd endpoints: - port: 8080 interval: 30s
部署新的 PodMonitoring 資源:
kubectl -n default apply -f podmonitoring.yaml
在幾分鐘內,Managed Service for Prometheus 會處理從匯出工具擷取的指標,並使用長格式名稱將指標儲存在 Cloud Monitoring 中。Prometheus 指標的儲存慣例如下:
- 前置字串
prometheus.googleapis.com
。 - 這個後置字元通常是
gauge
、counter
、summary
或histogram
,但未輸入類型的指標可能會有unknown
或unknown:counter
後置字元。如要驗證後置字元,請使用 Metrics Explorer 在 Cloud Monitoring 中查詢指標。
- 前置字串
更新已部署的 HPA,從 Cloud Monitoring 查詢指標。指標
foo
會以prometheus.googleapis.com/foo/gauge
的形式擷取。如要讓已部署的 HorizontalPodAutoscaler 資源可查詢指標,請在已部署的 HPA 中使用長格式名稱,但必須將所有斜線 (/
) 替換為管道字元 (|
):prometheus.googleapis.com|foo|gauge
。詳情請參閱 Custom Metrics Stackdriver Adapter 存放區的「Metrics available from Stackdriver」一節。執行下列指令,更新已部署的 HPA:
kubectl edit hpa custom-metric-prometheus-sd
將
pods.metric.name
欄位的值從foo
變更為prometheus.googleapis.com|foo|gauge
。spec
區段應如下所示:spec: maxReplicas: 5 metrics: - pods: metric: name: prometheus.googleapis.com|foo|gauge target: averageValue: "20" type: AverageValue type: Pods minReplicas: 1
在本範例中,HPA 設定會尋找指標
prometheus.googleapis.com/foo/gauge
的平均值是否為20
。由於 Deployment 會將指標值設為40
,因此 HPA 控制器會將 Pod 數量增加至maxReplicas
(5
) 欄位的值,盡量將所有 Pod 的平均指標值降至20
。水平 Pod 自動配置器查詢的範圍僅限於安裝水平 Pod 自動配置器資源的命名空間和叢集,因此其他叢集和命名空間中的相同指標不會影響自動調度。
如要觀察工作負載調度資源,請執行下列指令:
kubectl get hpa custom-metric-prometheus-sd --watch
「
REPLICAS
」欄位的值從「1
」變更為「5
」。NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE custom-metric-prometheus-sd Deployment/custom-metric-prometheus-sd 40/20 1 5 5 *
如要縮減部署作業,請將目標指標值更新為高於匯出指標值。在本範例中,Deployment 會將
prometheus.googleapis.com/foo/gauge
指標的值設為40
。如果將目標值設為大於40
的數字,部署作業就會縮減。舉例來說,使用
kubectl edit
將 HPA 設定中pods.target.averageValue
欄位的值從20
變更為100
。kubectl edit hpa custom-metric-prometheus-sd
修改規格部分,使其符合下列內容:
spec: maxReplicas: 5 metrics: - pods: metric: name: prometheus.googleapis.com|foo|gauge target: averageValue: "100" type: AverageValue type: Pods minReplicas: 1
如要觀察工作負載縮減,請執行下列指令:
kubectl get hpa custom-metric-prometheus-sd --watch
「
REPLICAS
」欄位的值從「5
」變更為「1
」。根據設計,這項作業的速度會比向上擴充 pod 數量慢:NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE custom-metric-prometheus-sd Deployment/custom-metric-prometheus-sd 40/100 1 5 1 *
如要清除已部署的範例,請執行下列指令:
kubectl delete -f https://raw.githubusercontent.com/GoogleCloudPlatform/k8s-stackdriver/master/custom-metrics-stackdriver-adapter/deploy/production/adapter_new_resource_model.yaml kubectl delete -f https://raw.githubusercontent.com/GoogleCloudPlatform/k8s-stackdriver/master/custom-metrics-stackdriver-adapter/examples/prometheus-to-sd/custom-metrics-prometheus-sd.yaml kubectl delete podmonitoring/prom-example
詳情請參閱 Custom Metrics Stackdriver Adapter 存放區中的 Prometheus 範例,或參閱調度應用程式資源。
使用 Prometheus 介面卡
您只需稍做變更,即可使用現有的 prometheus-adapter 設定來自動調度資源。與使用上游 Prometheus 進行資源調度相比,使用 Managed Service for Prometheus 進行資源調度時,設定 prometheus-adapter 有兩項額外限制:
查詢必須透過 Prometheus 前端 UI Proxy 傳送,就像使用 Prometheus API 或 UI 查詢 Managed Service for Prometheus 時一樣。 如果是 prometheus-adapter,您需要編輯
prometheus-adapter
Deployment,將prometheus-url
值變更如下:--prometheus-url=http://frontend.NAMESPACE_NAME.svc:9090/
其中 NAMESPACE_NAME 是部署前端的命名空間。
您無法在規則設定的
.seriesQuery
欄位中,對指標名稱使用規則運算式比對器 (=~
或!~
)。您必須完整指定指標名稱。如需一些解決方法,請參閱「PromQL 相容性」。
與上游 Prometheus 相比,資料可能需要稍長的時間才能在 Managed Service for Prometheus 中提供,因此設定過於急切的自動調整大小邏輯可能會導致非預期的行為。雖然無法保證資料的新鮮度,但資料傳送至 Managed Service for Prometheus 後,通常會在 3 到 7 秒內可供查詢 (不含任何網路延遲)。
prometheus-adapter 發出的所有查詢都屬於全域範圍。也就是說,如果兩個命名空間中的應用程式發出名稱相同的指標,使用該指標的 HPA 設定會根據這兩個應用程式的資料進行調整。建議您一律在 PromQL 中使用 namespace
或 cluster
篩選器,避免使用錯誤資料進行調整。
如要使用 prometheus-adapter 和受管理集合設定 HPA 設定範例,請按照下列步驟操作:
- 在叢集中設定代管集合。
- 在叢集中部署 Prometheus 前端 UI Proxy。如果您使用 Workload Identity Federation for GKE,也必須設定服務帳戶並授權。
- 在 prometheus-engine 存放區的
examples/hpa/
目錄中部署資訊清單:example-app.yaml
:可發出指標的部署和服務範例。pod-monitoring.yaml
:用於設定擷取範例指標的資源。hpa.yaml
:設定工作負載資源調度的 HPA 資源。
確認叢集已安裝
prometheus-adapter
。方法是將範例安裝資訊清單部署至叢集。這份資訊清單已設定為:- 查詢部署在
default
命名空間中的前端 Proxy。 - 發出 PromQL,計算並從範例部署作業傳回
http_requests_per_second
指標。
- 查詢部署在
在不同的終端機工作階段中,分別執行下列指令:
- 針對
prometheus-example-app
服務產生 HTTP 負載:kubectl run -i --tty load-generator --rm --image=busybox:1.28 --restart=Never -- /bin/sh -c "while sleep 0.01; do wget -q -O- http://prometheus-example-app; done"
- 監控水平 Pod 自動調度器:
kubectl get hpa prometheus-example-app --watch
- 監控工作負載的資源調度情況:
kubectl get po -lapp.kubernetes.io/name=prometheus-example-app --watch
- 針對
使用 Ctrl+C 停止產生 HTTP 負載,並觀察工作負載縮減。
疑難排解
自訂指標 Stackdriver 轉接器使用的資源定義與 Prometheus 轉接器 (prometheus-adapter) 中的資源定義名稱相同。名稱重疊表示在同一個叢集中執行多個轉接程式會導致錯誤。
如果叢集先前已安裝自訂指標 Stackdriver 轉接器,在該叢集中安裝 Prometheus 轉接器可能會因名稱衝突而擲回錯誤,例如 FailedGetObjectMetric
。如要解決這個問題,您可能必須刪除先前由自訂指標介面卡註冊的 v1beta1.external.metrics.k8s.io
、v1beta1.custom.metrics.k8s.io
和 v1beta2.custom.metrics.k8s.io
apiservices。
疑難排解提示:
部分 Cloud Monitoring 系統指標 (例如 Pub/Sub 指標) 會延遲 60 秒以上。由於 Prometheus Adapter 會使用目前的時間戳記執行查詢,因此使用 Prometheus Adapter 查詢這些指標時,可能會錯誤地導致沒有資料。如要查詢延遲指標,請在 PromQL 中使用
offset
修飾符,將查詢的時間偏移量變更為必要值。如要確認前端 UI Proxy 正常運作,且權限沒有問題,請在終端機中執行下列指令:
kubectl -n NAMESPACE_NAME port-forward svc/frontend 9090
接著,開啟另一個終端機並執行下列指令:
curl --silent 'localhost:9090/api/v1/series?match%5B%5D=up'
如果前端 UI 代理伺服器運作正常,第二個終端機中的回應會類似如下:
curl --silent 'localhost:9090/api/v1/series?match%5B%5D=up' | jq . { "status": "success", "data": [ ... ] }
如果收到 403 錯誤,表示前端 UI Proxy 設定有誤。如要瞭解如何解決 403 錯誤,請參閱設定及授權服務帳戶指南。
如要確認自訂指標 apiserver 是否可用,請執行下列指令:
kubectl get apiservices.apiregistration.k8s.io v1beta1.custom.metrics.k8s.io
如果 apiserver 可用,回應會類似以下內容:
$ kubectl get apiservices.apiregistration.k8s.io v1beta1.custom.metrics.k8s.io NAME SERVICE AVAILABLE AGE v1beta1.custom.metrics.k8s.io monitoring/prometheus-adapter True 33m
如要確認水平 Pod 自動配置器是否正常運作,請執行下列指令:
$ kubectl describe hpa prometheus-example-app Name: prometheus-example-app Namespace: default Labels:
Annotations: Reference: Deployment/prometheus-example-app Metrics: ( current / target ) "http_requests_per_second" on pods: 11500m / 10 Min replicas: 1 Max replicas: 10 Deployment pods: 2 current / 2 desired Conditions: Type Status Reason Message ---- ------ ------ ------- AbleToScale True ReadyForNewScale recommended size matches current size ScalingActive True ValidMetricFound the HPA was able to successfully calculate a replica count from pods metric http_requests_per_second ScalingLimited False DesiredWithinRange the desired count is within the acceptable range Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal SuccessfulRescale 47s horizontal-pod-autoscaler New size: 2; reason: pods metric http_requests_per_second above target 如果回覆包含
FailedGetPodsMetric
等陳述,則 HPA 會失敗。以下說明 HPA 失敗時,對describe
呼叫的回應:$ kubectl describe hpa prometheus-example-app Name: prometheus-example-app Namespace: default Reference: Deployment/prometheus-example-app Metrics: ( current / target ) "http_requests_per_second" on pods:
/ 10 Min replicas: 1 Max replicas: 10 Deployment pods: 1 current / 1 desired Conditions: Type Status Reason Message ---- ------ ------ ------- AbleToScale True ReadyForNewScale recommended size matches current size ScalingActive False FailedGetPodsMetric the HPA was unable to compute the replica count: unable to get metric http_requests_per_second: unable to fetch metrics from custom metrics API: the server could not find the metric http_requests_per_second for pods ScalingLimited False DesiredWithinRange the desired count is within the acceptable range Events: Type Reason Age From Message ---- ------ ---- ---- ------- Warning FailedGetPodsMetric 104s (x11 over 16m) horizontal-pod-autoscaler unable to get metric http_requests_per_second: unable to fetch metrics from custom metrics API: the server could not find the metric http_requests_per_second for pods 如果 HPA 失敗,請確認您是否使用
load-generator
產生指標。您可以使用以下指令直接檢查自訂指標 API:kubectl get --raw "/apis/custom.metrics.k8s.io/v1beta1/" | jq .
成功輸出結果會與下列內容相似:
$ kubectl get --raw "/apis/custom.metrics.k8s.io/v1beta1/" | jq . { "kind": "APIResourceList", "apiVersion": "v1", "groupVersion": "custom.metrics.k8s.io/v1beta1", "resources": [ { "name": "namespaces/http_requests_per_second", "singularName": "", "namespaced": false, "kind": "MetricValueList", "verbs": [ "get" ] }, { "name": "pods/http_requests_per_second", "singularName": "", "namespaced": true, "kind": "MetricValueList", "verbs": [ "get" ] } ] }
如果沒有任何指標,輸出內容的
"resources"
下方就不會有任何資料,例如:kubectl get --raw "/apis/custom.metrics.k8s.io/v1beta1/" | jq . { "kind": "APIResourceList", "apiVersion": "v1", "groupVersion": "custom.metrics.k8s.io/v1beta1", "resources": [] }