本文档介绍了如何为 Google Cloud Managed Service for Prometheus 启用横向 Pod 自动扩缩 (HPA)。您可以通过执行以下任一操作来启用 HPA:
- 使用 Google Cloud 开发和支持的自定义指标 Stackdriver 适配器库。
- 使用第三方 Prometheus 适配器库。
您必须选择其中一种方法。您不能同时使用这两者,因为它们的资源定义重叠,如问题排查中所述。
使用自定义指标 Stackdriver 适配器
从适配器的 v0.13.1 版开始,自定义指标 Stackdriver 适配器支持从 Managed Service for Prometheus 查询指标。
如需使用自定义指标 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 Viewer”角色。如果您的 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
。如需了解详情,请参阅自定义指标 Stackdriver 适配器代码库的 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
。HPA 查询的范围限定为安装了 HPA 资源的命名空间和集群,因此其他集群和命名空间中的相同指标不会影响您的自动扩缩。
如需观察工作负载扩容,请运行以下命令:
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
如需了解详情,请参阅自定义指标 Stackdriver 适配器代码库中的 Prometheus 示例,或参阅扩缩应用。
使用 Prometheus 适配器
现有的 prometheus-adapter 配置可用于自动扩缩,只需要进行少量更改即可。与使用上游 Prometheus 进行扩缩相比,将 prometheus-aptapter 配置为使用 Managed Service for Prometheus 进行扩缩还有两个额外的限制:
与使用 Prometheus API 或界面查询 Managed Service for Prometheus 时一样,必须通过 Prometheus 前端界面代理路由查询。对于 prometheus-aptapter,您需要修改
prometheus-adapter
部署以更改prometheus-url
值,如下所示:--prometheus-url=http://frontend.NAMESPACE_NAME.svc:9090/
其中,NAMESPACE_NAME 是部署前端的命名空间。
您不能在规则配置的
.seriesQuery
字段中对指标名称使用正则表达式匹配器。您必须完全指定指标名称。
由于与 Prometheus 上游相比,让数据在 Managed Service for Prometheus 中可供使用的时间略长,因此配置过于激增的自动扩缩逻辑可能会导致不希望的行为。虽然无法保证数据新鲜度,但数据在发送到 Managed Service for Prometheus 后,通常在 3-7 秒内可用于查询,不包括任何网络延迟时间。
prometheus-adapter 发出的所有查询都是全局性的。这意味着,如果两个命名空间中的应用发出具有相同名称的指标,则使用该指标的 HPA 配置会使用这两个应用中的数据进行扩缩。我们建议您始终在 PromQL 中使用 namespace
或 cluster
过滤条件,以避免使用错误的数据进行扩缩。
如需使用 prometheus-adapter 和代管式集合来设置示例 HPA 配置,请按以下步骤操作:
- 在集群中设置代管式收集。
- 在集群中部署 Prometheus 前端界面代理。如果您使用 Workload Identity Federation for GKE,则还必须配置服务账号并向其授权。
- 在 prometheus-engine 代码库内的
examples/hpa/
目录中部署清单:example-app.yaml
:发出指标的部署和服务示例。pod-monitoring.yaml
:用于配置示例指标的资源。hpa.yaml
:配置工作负载的 HPA 资源。
确保您的集群中已安装
prometheus-adapter
。这可以通过将示例安装清单部署到集群来实现。此清单已配置为:- 查询部署在
default
命名空间中的前端代理。 - 发出 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
apiservice。
问题排查提示:
某些 Cloud Monitoring 系统指标(例如 Pub/Sub 指标)会延迟 60 秒或更长时间。当 Prometheus 适配器使用当前时间戳执行查询时,使用 Prometheus 适配器查询这些指标可能会错误地导致无数据。如需查询延迟指标,请使用 PromQL 中的
offset
修饰符将查询的时间偏移值更改为必要的量。如需确认前端界面代理是否按预期工作以及权限没有问题,请在终端运行以下命令:
kubectl -n NAMESPACE_NAME port-forward svc/frontend 9090
接下来,打开另一个终端并运行以下命令:
curl --silent 'localhost:9090/api/v1/series?match%5B%5D=up'
当前端界面代理正常运行时,第二个终端中的响应类似于以下内容:
curl --silent 'localhost:9090/api/v1/series?match%5B%5D=up' | jq . { "status": "success", "data": [ ... ] }
如果您收到 403 错误,则表示前端界面代理未正确配置。如需了解如何解决 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
如需验证 HPA 是否按预期工作,请运行以下命令:
$ 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": [] }