默认HPA只支持基于CPU和内存的自动伸缩,并不能满足日常的运维需求。阿里云Prometheus监控全面对接开源Prometheus生态,支持类型丰富的组件监控,提供多种开箱即用的预置监控大盘,且提供全面托管的Prometheus服务。本文介绍如何将阿里云Prometheus指标转换成HPA可用的指标,从而为应用提供更加便捷的扩缩机制。
前提条件
在将阿里云Prometheus指标转换成HPA可用的指标前,您需要部署相关组件。
- 部署阿里云Prometheus监控组件。具体操作,请参见开启阿里云Prometheus监控。
- 部署alibaba-cloud-metrics-adapter组件。具体操作,请参见部署alibaba-cloud-metrics-adapter组件。
示例
本文举例如何配置alibaba-cloud-metrics-adapter,实现将阿里云Prometheus指标转换为HPA可用指标,并实现该指标自动伸缩。
- 部署工作负载。
- 添加ServiceMonitor。
- 确认监控状态。在服务发现页面,单击Targets,如果看到default/sample-app/0(1/1 up),则说明您成功在阿里云Prometheus监控到了部署的应用。
- 修改alibaba-cloud-metrics-adapter配置。
- 部署HPA。
当前版本已支持Prometheus Metrics同时透出Custom Metrics与External Metrics,您可以根据需求选择两种不同方式通过HPA进行容器伸缩。
- 方式一:通过Custom Metrics进行容器伸缩
- 执行以下命令,通过Custom Metrics指标查询方式,查看HPA可用指标详情。
kubectl get --raw "/apis/custom.metrics.k8s.io/v1beta1/namespaces/default/pods/*/http_requests_per_second" | jq .
以下为指标查询结果,请展开查看。{ "kind": "MetricValueList", "apiVersion": "custom.metrics.k8s.io/v1beta1", "metadata": { "selfLink": "/apis/custom.metrics.k8s.io/v1beta1/namespaces/default/pods/%2A/http_requests_per_second" }, "items": [ { "describedObject": { "kind": "Pod", "namespace": "default", "name": "sample-app-579bc6774c-rmjfd", "apiVersion": "/v1" }, "metricName": "http_requests_per_second", "timestamp": "2022-01-28T08:42:58Z", "value": "33m", "selector": null } ] }
- 使用以下YAML文件部署HPA,然后执行
kubectl apply -f hpa.yaml
创建HPA应用。以下为YAML文件内容,请展开查看。kind: HorizontalPodAutoscaler apiVersion: autoscaling/v2beta1 metadata: name: sample-app spec: #HPA的伸缩对象描述,HPA会动态修改该对象的Pod数量。 scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: sample-app #HPA的最小Pod数量和最大Pod数量。 minReplicas: 1 maxReplicas: 10 #监控的指标数组,支持多种类型的指标共存。 metrics: - type: Pods pods: #使用指标:pods/http_requests。 metricName: http_requests_per_second # AverageValue类型的目标值,Pods指标类型下只支持AverageValue类型的目标值。 targetAverageValue: 500m #当出现了小数点,K8s又需要高精度时,会使用单位m或k。例如1001m=1.001,1k=1000。
- 在Service中开启负载均衡后,执行压测验证。
- 执行以下命令进行压测实验。
ab -c 50 -n 2000 LoadBalancer(sample-app):8080/
- 执行以下命令查看HPA详情。
kubectl get hpa sample-app
预期输出:NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE sample-app Deployment/sample-app 33m/500m 1 10 1 7m
- 执行以下命令进行压测实验。
- 执行以下命令,通过Custom Metrics指标查询方式,查看HPA可用指标详情。
- 方式二:通过External Metrics进行容器伸缩
- 执行以下命令,通过External Metrics指标查询方式,查看HPA可用指标详情。
kubectl get --raw "/apis/external.metrics.k8s.io/v1beta1/namespaces/default/http_requests_per_second" | jq .
以下为指标查询结果,请展开查看。{ "kind": "ExternalMetricValueList", "apiVersion": "external.metrics.k8s.io/v1beta1", "metadata": {}, "items": [ { "metricName": "http_requests_per_second", "metricLabels": {}, "timestamp": "2022-01-28T08:40:20Z", "value": "33m" } ] }
- 使用以下YAML文件部署HPA,然后执行
kubectl apply -f hpa.yaml
创建HPA应用。以下为YAML文件内容,请展开查看。apiVersion: autoscaling/v2beta2 kind: HorizontalPodAutoscaler metadata: name: sample-app spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: sample-app minReplicas: 1 maxReplicas: 10 metrics: - type: External external: metric: name: http_requests_per_second selector: matchLabels: job: "sample-app" #External指标类型下只支持Value和AverageValue类型的目标值。 target: type: AverageValue averageValue: 500m
- 在Service中开启负载均衡后,执行压测验证。
- 执行以下命令进行压测实验。
ab -c 50 -n 2000 LoadBalancer(sample-app):8080/
- 执行以下命令查看HPA详情。
kubectl get hpa sample-app
预期输出:NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE sample-app Deployment/sample-app 33m/500m 1 10 1 7m
- 执行以下命令进行压测实验。
- 执行以下命令,通过External Metrics指标查询方式,查看HPA可用指标详情。
- 方式一:通过Custom Metrics进行容器伸缩
ack-alibaba-cloud-adapter配置文件详解
ack-alibaba-cloud-adapter通过以下步骤将Prometheus中的指标转换成HPA可用的指标:
- Discovery:ack-alibaba-cloud-adapter会从Prometheus发现可用的指标。
- Association:将指标与Kubernetes资源(Pod、Node、Namespace)相关联。
- Naming:定义转换后的HPA可用指标名称。
- Querying:定义查询Prometheus语句。
以上文中sample-app容器中暴露出来的
http_requests_total
指标转换成HPA中的http_requests_per_second
为例,完整的ack-alibaba-cloud-adapter配置文件如下。- seriesQuery: http_requests_total{namespace!="",pod!=""}
resources:
overrides:
namespace: {resource: "namespace"}
pod: {resource: "pod"}
name:
matches: ^(.*)_total
as: ${1}_per_second
metricsQuery: sum(rate(<<.Series>>{<<.LabelMatchers>>}[2m])) by (<<.GroupBy>>)
说明
seriesQuery
:即PromQL请求数据。metricsQuery
:对seriesQuery
中PromQL请求的数据做聚合操作。resources
:是PromQL里的数据Label,与resource进行匹配,这里的resouce是指集群内的api-resource,比如Pod、Namespace和Node。可通过kubectl api-resources -o wide
查看。此处Key
对应Prometheus数据中的LabelName
,请确认Prometheus指标数据中有此LabelName。name
:是指根据正则匹配把Prometheus指标名转为比较可读的指标名,这里是把http_request_total
转为http_request_per_second
。
- Discovery指定待转换的Prometheus指标,您可以通过seriesFilters精确过滤指标。seriesQuery可以根据标签进行查找(示例代码如下)。
seriesQuery: http_requests_total{namespace!="",pod!=""} seriesFilters: - isNot: "^container_.*_seconds_total"
说明 seriesFilters为非必填项,用来过滤指标:- is:<regex>,匹配包含该正则表达式的指标。
- isNot:<regex>,匹配不包含该正则表达式的指标。
- Association设置Prometheus指标标签与Kubernetes中的资源映射关系。
http_requests_total
指标的标签包括namespace!=""
和pod!=""
。- seriesQuery: http_requests_total{namespace!="",pod!=""} resources: overrides: namespace: {resource: "namespace"} pod: {resource: "pod"}
- Naming用于将Prometheus指标名称转换成HPA的指标名称,但不会改变Prometheus本身的指标名称。如果使用Prometheus原来的指标,可以不设置。说明 您可以通过执行命令
kubectl get --raw "/apis/custom.metrics.k8s.io/v1beta1"
查看HPA可用的所有指标。- seriesQuery: http_requests_total{namespace!="",pod!=""} resources: overrides: namespace: {resource: "namespace"} pod: {resource: "pod"} name: matches: "^(.*)_total" as: "${1}_per_second"
- Querying查询Prometheus API的模板。ack-alibaba-cloud-adapter会根据HPA中的参数,填充参数到此模板中,然后发送给Prometheus API请求,并将获得的值最终提供给HPA进行弹性扩缩。
- seriesQuery: http_requests_total{namespace!="",pod!=""} resources: overrides: namespace: {resource: "namespace"} pod: {resource: "pod"} name: matches: ^(.*)_total as: ${1}_per_second metricsQuery: sum(rate(<<.Series>>{<<.LabelMatchers>>}[2m])) by (<<.GroupBy>>)
如何获取Prometheus数据请求URL
阿里云Prometheus监控场景
- 登录ARMS控制台。
- 在左侧导航栏选择 。
- 在Prometheus监控页面左上角选择容器服务K8s集群所在的地域,然后单击目标实例名称进入对应实例页面。
- 在左侧导航栏单击设置,然后单击设置页签。
- 在设置页签下获取HTTP API地址(Grafana读取地址)。推荐使用内网,如无法使用内网时,可使用公网。
开源Prometheus监控场景
- 部署Prometheus监控方案。
- 查看Labels中对应的service和namespce。以ServiceName是ack-prometheus-operator-prometheus,ServiceNamespace是monitoring为例说明该开源Prometheus数据请求的URL:
http://ack-prometheus-operator-prometheus.monitoring.svc.cluster.local:9090