千家信息网

Kubernetes1.16基于Prometheus自定义指标弹性伸缩

发表于:2024-11-24 作者:千家信息网编辑
千家信息网最后更新 2024年11月24日,HPA原理K8S弹性伸缩,指在大业务量情况下,当前容器资源如cpu,内存,自定义指标等,已超出正常设定的范围时进行的自动扩容操作,将业务负载到扩容后的容器上,降低容器压力,直到达到HPA设定的容器数量
千家信息网最后更新 2024年11月24日Kubernetes1.16基于Prometheus自定义指标弹性伸缩

HPA原理

K8S弹性伸缩,指在大业务量情况下,当前容器资源如cpu,内存,自定义指标等,已超出正常设定的范围时进行的自动扩容操作,将业务负载到扩容后的容器上,降低容器压力,直到达到HPA设定的容器数量上限,当业务量降低后,实现自动缩容操作。Kubernetes 中的 Metrics Server 持续采集所有 Pod 副本的指标数据。HPA 控制器通过 Metrics Server 的 API(Heapster 的 API 或聚合 API)获取这些数据,基于用户定义的扩缩容规则进行计算,得到目标 Pod 副本数量。当目标 Pod 副本数量与当前副本数量不同时,HPA 控制器就向 Pod 的副本控制器(Deployment、RC 或 ReplicaSet)发起 scale 操作,调整 Pod 的副本数量,完成扩缩容操作。

HPA的具有扩缩容冷却周期,防止因网络抖动而造成的不必要扩缩容操作

扩容冷却时间默认值:3分钟

缩容冷却时间默认值:5分钟

可以通过调整kube-controller-manager组件启动参数设置冷却时间:

--horizontal-pod-autoscaler-downscale-delay :扩容冷却

--horizontal-pod-autoscaler-upscale-delay :缩容冷却

HPA发展初期只支持内存,cpu的自动扩缩容操作,不支持自定义指标,发展至今,已经可以通过第三方插件与Prometheus等监控服务进行交互,获取到自定义指标,并转换成apiserver能够理解的内容,供HPA进行自动化扩缩容操作。如下图


HPA发展历程

目前 HPA 已经支持了 autoscaling/v1、autoscaling/v2beta1和autoscaling/v2beta2 三个大版本 。

目前大多数人比较熟悉是autoscaling/v1,这个版本只支持CPU一个指标的弹性伸缩。

而autoscaling/v2beta1增加了支持自定义指标,autoscaling/v2beta2又额外增加了外部指标支持。

而产生这些变化不得不提的是Kubernetes社区对监控与监控指标的认识与转变。从早期Heapster到Metrics Server再到将指标边界进行划分,一直在丰富监控生态。


传统HPA,只针对cpu,内存进行扩缩容编写方式也很简单,可以通过yaml,也可以通过kubectl 命令行形式设定阀值。


v1版本:

apiVersion: autoscaling/v1

kind: HorizontalPodAutoscaler

metadata:

name: php-apache

namespace: default

spec:

scaleTargetRef:

apiVersion: apps/v1

kind: Deployment

name: php-apache

minReplicas: 1

maxReplicas: 10

targetCPUUtilizationPercentage: 50


v2beta2版本:

apiVersion: autoscaling/v2beta2

kind: HorizontalPodAutoscaler

metadata:

name: php-apache

namespace: default

spec:

scaleTargetRef:

apiVersion: apps/v1

kind: Deployment

name: php-apache

minReplicas: 1

maxReplicas: 10

metrics:

- type: Resource

resource:

name: cpu

target:

type: Utilization

averageUtilization: 50

- type: Pods

pods:

metric:

name: packets-per-second

target:

type: AverageValue

averageValue: 1k

- type: Object

object:

metric:

name: requests-per-second

describedObject:

apiVersion: networking.k8s.io/v1beta1

kind: Ingress

name: main-route

target:

type: Value

value: 10k

- type: External

external:

metric:

name: queue_messages_ready

selector: "queue=worker_tasks"

target:

type: AverageValue

averageValue: 30


metrics中的type字段有四种类型的值:Object、Pods、Resource、External。

Resource:指的是当前伸缩对象下的pod的cpu和memory指标,只支持Utilization和AverageValue类型的目标值。

Object:指的是指定k8s内部对象的指标,数据需要第三方adapter提供,只支持Value和AverageValue类型的目标值。

Pods:指的是伸缩对象Pods的指标,数据需要第三方的adapter提供,只允许AverageValue类型的目标值。

External:指的是k8s外部的指标,数据同样需要第三方的adapter提供,只支持Value和AverageValue类型的目标值。


基于Prometheus自定义指标缩放

1.部署Prometheus

参考我之前的博客部署即可


2.部署Prometheus Adapter

但是prometheus采集到的metrics并不能直接给k8s用,因为两者数据格式不兼容,还需要另外一个组件(k8s-prometheus-adpater),将prometheus的metrics 数据格式转换成k8s API接口能识别的格式,转换以后,因为是自定义 API,所以还需要用Kubernetes aggregator在主APIServer中注册,以便直接通过/apis/来访问。

直接使用Helm Charts安装

# wget https://get.helm.sh/helm-v3.0.0-linux-amd64.tar.gz

# tar zxvf helm-v3.0.0-linux-amd64.tar.gz

# mv linux-amd64/helm /usr/bin/

# helm repo add stable http://mirror.azure.cn/kubernetes/charts

# helm repo update

# helm repo list

# helm install prometheus-adapter stable/prometheus-adapter --namespace kube-system --set prometheus.url=http://prometheus.kube-system,prometheus.port=9090

# helm list -n kube-system


确保适配器adapter注册到apiserver

# kubectl get apiservices |grep custom

# kubectl get --raw "/apis/custom.metrics.k8s.io/v1beta1"

3.创建metrics deployment

容器需要暴露出让prometheus获取数据的端口,metrics路径,需要和开发商量好,服务暴露在外的需要监控的指标放在/metrics路径下

注意:镜像为私人镜像,需要实验的话,需要进行替换

apiVersion: apps/v1

kind: Deployment

metadata:

labels:

app: metrics-app

name: metrics-app

spec:

replicas: 3

selector:

matchLabels:

app: metrics-app

template:

metadata:

labels:

app: metrics-app

annotations:

prometheus.io/scrape: "true"

prometheus.io/port: "80"

prometheus.io/path: "/metrics"

spec:

containers:

- image: 172.30.0.109/metrics-app

name: metrics-app

ports:

- name: web

containerPort: 80

resources:

requests:

cpu: 200m

memory: 256Mi

readinessProbe:

httpGet:

path: /

port: 80

initialDelaySeconds: 3

periodSeconds: 5

livenessProbe:

httpGet:

path: /

port: 80

initialDelaySeconds: 3

periodSeconds: 5

---

apiVersion: v1

kind: Service

metadata:

name: metrics-app

labels:

app: metrics-app

spec:

ports:

- name: web

port: 80

targetPort: 80

selector:

app: metrics-app


访问容器/metrics路径,得到总共http访问量,经过prometheus指标转换为QPS


4.创建HPA规则

针对容器QPS进行扩缩容操作,Pods类型只支持averageValue,deployment最大扩容数设为10。

HPA yaml:

apiVersion: autoscaling/v2beta2

kind: HorizontalPodAutoscaler

metadata:

name: metrics-app-hpa

namespace: default

spec:

scaleTargetRef:

apiVersion: apps/v1

kind: Deployment

name: metrics-app

minReplicas: 1

maxReplicas: 10

metrics:

- type: Pods

pods:

metric:

name: http_requests_per_second

target:

type: AverageValue

averageValue: 800m # 800m 即0.8个/秒


配置好HPA后,hpa还不能获取到http_requests_per_second的数据,kubetcl get hpa看到的获取指标是unknown,需要在prometheus adapter适配器中配置http_requests_per_second

相当于白名单,去获取prometheus中的指标数据。

修改prometheus adapter configmap

# kubectl edit cm -n kube-system prometheus-adapter

新增:

- seriesQuery: 'http_requests_total{kubernetes_namespace!="",kubernetes_pod_name!=""}'

resources:

overrides:

kubernetes_namespace: {resource: "namespace"}

kubernetes_pod_name: {resource: "pod"}

name:

matches: "^(.*)_total"

as: "${1}_per_second"

metricsQuery: 'sum(rate(<<.Series>>{<<.LabelMatchers>>}[2m])) by (<<.GroupBy>>)'


这里主要是利用promSQL的形式通过将http_requests_total转换成一个区间的平均访问量,如上两分钟,求容器所有的和,即为QPS


注意:将/metrics中的http_requests_total名称替换为http_requests_per_second,HPA根据http_requests_per_second去获取指标数据进行扩缩容操作

prometheus-adapter配置修改后,需要重启容器加载新的配置


到这一步,指标已经获取到了

# kubectl get hpa


5.测试HPA

进行压测

# yum install -y httpd-tools

使用ab命令对metrics-app service进行压力测试


查看HPA,指标数据已经打满,deployment下的容器已经扩容到了10个,等压力测试结束,就会自动缩容



0