https://github.com/wentjiang/prometheus-HPA-test
在开发微服务时,我们会有一些请求量突增的场景,举个例子,快上下班的时候,大家都需要签到签退,那么签到考勤,那么对于考勤服务,在上下班的时候,会出现流量激增的情况,一种解决方法是,我们将服务的数量启动到能满足峰值的情况,这种情况会产生不必要的资源浪费,那么,怎么样才能解决该问题呢?作为云原生时代最重要的基础设施,k8s为我们提供了HPA(Horizontal Pod Autoscaler)自动扩缩容机制,这样我们就能够应对类似的流量突增的情况,按照配置好的扩缩容机制,进行自动的扩缩容;
k8s原生的HPA使用方式为:
1.使用类似Deployment的方式部署微服务
2.为微服务添加HPA定义
完成以上配置之后,Metrics Server会根据从pod采集到的信息,使用HPA中定义的判断条件,对当前Deployment的副本数进行调整,以达到期望数值
k8s原生的自动扩缩容,支持的指标只有cpu和内存,但我们业务的场景可能使用的不仅限于cpu和内存,或者,cpu和内存不能满足业务扩缩容的需求,这样的话,就需要使用自定义指标的HPA来进行实现,例如,客户端提交的计算任务,服务端使用生产者消费者模式,将客户端的计算任务放在队列中,这个时候,监听队列的积压,从而进行扩缩容是一个相对于cpu,内存来说更优的方案
通过上述的介绍,想必大家已经明白了HPA的原理,和为什么使用自定义指标扩缩容,这里列出几种HPA指标:
HPA需要从metrics API获取到所需要进行HPA的值,默认使用的是metrics server提供的数据,只有cpu,内存的信息,如果要使用service相关的数据,如http get请求数之类的信息,需要查阅外部指标相关的API,k8s也同样支持,这里只关注custom metrics api指标,接下来,我们将详细的了解如何一步一步搭建自定义指标HPA,这里选取主流的prometheus作为采集指标的收集器,将数据上报给HPA
k8s集群,helm可用
使用helm安装prometheus
将prometheus保存到本地,可根据需要修改prometheus配置
helm show values prometheus-community/kube-prometheus-stack > prometheus-config.yaml
这里使用默认的配置进行安装,安装时需要注意,如果之前集群通过helm安装过prometheus,需要将所有之前安装的信息删除掉(包括无状态,有状态,配置,自定义对象等),否则会导致安装失败
使用helm命令安装prometheus,完成之后会有以下输出
$ helm install ops-prometheus prometheus-community/kube-prometheus-stack -n ops
NAME: ops-prometheus
LAST DEPLOYED: Tue Nov 3 16:26:10 2020
NAMESPACE: monitoring
STATUS: deployed
REVISION: 1
NOTES:
kube-prometheus-stack has been installed. Check its status by running:
kubectl --namespace monitoring get pods -l "release=ops-prometheus"
Visit https://github.com/prometheus-operator/kube-prometheus for instructions on how to create & configure Alertmanager and Prometheus instances using the Operator.
prometheus相关文档(https://github.com/prometheus-operator/kube-prometheus)
验证prometheus是否部署成功
$ kubectl --namespace ops get pods -l "release=ops-prometheus"
NAME READY STATUS RESTARTS AGE
ops-prometheus-kube-promet-operator-6d44cfccfb-72xv2 2/2 Running 0 52d
ops-prometheus-prometheus-node-exporter-n6fg4 1/1 Running 0 52d
# wentao.jiang @ wentjiang in ~/Downloads/temp on git:master x [23:23:03]
$ kubectl get pods -n ops
NAME READY STATUS RESTARTS AGE
alertmanager-ops-prometheus-kube-promet-alertmanager-0 2/2 Running 0 52d
ops-prometheus-adapter-8ff46679d-c52ch 1/1 Running 0 51d
ops-prometheus-grafana-f4875b756-zvn6m 2/2 Running 0 52d
ops-prometheus-kube-promet-operator-6d44cfccfb-72xv2 2/2 Running 0 52d
ops-prometheus-kube-state-metrics-7bdbdb4559-z4dlf 1/1 Running 0 52d
ops-prometheus-prometheus-node-exporter-n6fg4 1/1 Running 0 52d
prometheus-ops-prometheus-kube-promet-prometheus-0 3/3 Running 1 52d
如果所有node中的exporter 都为running状态,并包含以下组件:
- alertmanager-ops-prometheus-kube-promet-alertmanager
- ops-prometheus-grafana
- ops-prometheus-kube-promet-operator
- ops-prometheus-kube-state-metrics
- ops-prometheus-prometheus-node-exporter
- prometheus-ops-prometheus-kube-promet-prometheus
则部署成功
部署demo service
将我们已经写好的demo程序部署到k8s集群中
将代码clone到本地,保证本地环境中有gradle,docker,执行./build.sh 会自动构建出prometheus-test:1.1的镜像,也可以直接使用上传好的docker hub的镜像
docker pull wentjiang/prometheus-test:1.1
启动service,
在项目目录下执行
kubectl create -f ./k8s/service.yaml -n local
分别查看pod 和 service状态
请求以下接口,验证服务启动成功
$ curl http://localhost:8080/prometheus-test/1.0/test
ok%
配置prometheus serviceMonitor
配置serviceMonitor的目的是让prometheus能够采集到服务的监控指标
按照代码中的serviceMonitor.yaml的配置,启动serviceMonitor
使用kubectl create -f ./k8s/serviceMonitor.yaml -n local启动
查看serviceMonitor创建成功
部署prometheus adapter
prometheus adapter的作用是让k8s的custome api能够采集到prometheus的监控数据
安装过程中使用该文档 prometheus-adapter参考链接
a.添加adapter仓库
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
b.查找prometheus对应的ip,记录下来,adapter配置中需要使用
c.修改adapter的配置项
helm show values prometheus-community/prometheus-adapter > prometheus-adapter.yaml
修改prometheus.url为上边查到的url
prometheus:
url: http://10.106.240.218
port: 9090
path: ""
d.安装prometheus adapter chart
helm repo update
helm install [RELEASE_NAME] prometheus-community/prometheus-adapter --values prometheus-adapter.yaml --namespace ops
NAME: prometheus-adapter
LAST DEPLOYED: Wed Nov 4 09:22:09 2020
NAMESPACE: ops
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
prometheus-adapter has been deployed.
In a few minutes you should be able to list metrics using the following command(s):
kubectl get --raw /apis/custom.metrics.k8s.io/v1beta1
e.验证是否部署成功
等待几分钟adapter相关配置安装完成
$ kubectl_local get --raw "/apis/custom.metrics.k8s.io/v1beta1/namespaces/local/pods/*/custom_value"
{"kind":"MetricValueList","apiVersion":"custom.metrics.k8s.io/v1beta1","metadata":{"selfLink":"/apis/custom.metrics.k8s.io/v1beta1/namespaces/local/pods/%2A/custom_value"},"items":[{"describedObject":{"kind":"Pod","namespace":"local","name":"prometheus-test-796fcd758d-5c7fc","apiVersion":"/v1"},"metricName":"custom_value","timestamp":"2020-12-25T13:46:59Z","value":"0","selector":null}]}
看到服务的custom_value已经成功的注册到了k8s的api server上,至此,已经成功的将微服务的自定义指标注册到了k8s集群的api Server上
配置prometheus的采集规则rule
这里的rule是添加adapter采集prometheus数据的规则,需要修改adapter对应的配置
a.找到adapter对应的configmap
$ kubectl_local get configmap -n ops |grep prometheus-adapter
ops-prometheus-adapter 1 52d
执行命令进行修改
kubectl edit configmap ops-prometheus-adapter -n ops
在rule的数组中添加以下规则
- metricsQuery: avg(rate(<<.Series>>{<<.LabelMatchers>>}[10s])) by (<<.GroupBy>>)
name:
as: ""
matches: custom_value
resources:
overrides:
namespace:
resource: namespace
pod_name:
resource: pod
seriesQuery: custom_value{namespace!="",pod_name!=""}
保存之后 adapter会热更新该配置项
为service添加HPA配置
kubectl create ./k8s/hpa.yaml -n local
可以看到配置已经成功提交
验证HPA是否生效
kubectl describe hpa prometheus-test-hpa -n local 可以查看当前hpa的状态
可以看到,当前hpa的状态一切良好, 最小副本数为1,最大副本数为3,当前custom_value的值为 0,目标平均值为10
现在我们修改custom_value的值,使其大于hpa中设置的值,就会看到副本数根据规则增加
调用服务的修改custom_value的接口
持续观察hpa的状态,可以发现,下图中,hpa已经开始工作了,拉起新的节点
已经成功的创建出了第二个节点,图中的5500m实际含义为5500/1000的数值,即为5.5,当前custom_value 11/2=5.5
至此,我们所有的操作都已经完成了
k8s官网对于自定义指标支持的文档
https://kubernetes.io/zh/docs/tasks/run-application/horizontal-pod-autoscale/#support-for-custom-metrics
支持自定义指标的适配器
https://github.com/kubernetes/metrics/blob/master/IMPLEMENTATIONS.md#custom-metrics-api
https://www.padok.fr/en/blog/scaling-prometheus-rabbitmq
https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack
https://artifacthub.io/packages/helm/prometheus-community/prometheus-adapter