自动伸缩工作负载的Pod实例个数,早期仅支持基于CPU和Memory的自动伸缩方式,随着应用越来越多搬迁到k8s上以及Prometheus的发展,开发者已经不满足于CPU和Memory,开发者需要应用自身的业务指标,或者是一些接入层的监控信息,例如:Load Balancer的QPS、网站的实时在线人数等。社区经过思考之后,定义了一套标准的Metrics API,通过聚合API对外提供服务。
基础知识
Metrics API
Kubernetest提供了三类Metrics API,如下。
API类别 | 说明 | API实现方 | 解释 |
---|---|---|---|
metrics.k8s.io | 核心指标API,主要包括CPU和内存指标 | Metrics Server、Prometheus Adapter | |
custom.metrics.k8s.io | 自定义指标 | Prometheus Adapter | |
external.metrics.k8s.io | 外部指标,指非K8s集群内的指标数据 | Prometheus Adapter |
API实现方实现K8s提供的标准API接口,并通过聚合API注册到Api-Server,统一对外提供服务。可以看到Prometheus Adapter已经实现了所有类型的Metrics API。
聚合 API
API聚合机制是Kubernetes 1.7版本引入的特性,能够将用户扩展的API注册到kube-apiserver上,然后可以通过kube-apiserver对注册的API进行统一访问和操作。API聚合机制的目标是提供集中的API发现机制和安全的代理功能,将开发人员的新API动态地、无缝地注册到Kubernetes API Server中进行测试和使用。例子如下:
# 一个样例,往api-server中注册自定义指标的API # 注册完成后即可通过api-server的地址调用改API:kubectl get --raw "/apis/custom.metrics.k8s.io/v1beta1" apiVersion: apiregistration.k8s.io/v1beta1 kind: APIService metadata: name: v1beta1.custom.metrics.k8s.io spec: service: name: custom-metrics-server namespace: custom-metrics group: custom.metrics.k8s.io # API的分组名称 version: v1beta1 # API的版本号 insecureSkipTLSVerify: true groupPriorityMinimum: 100 versionPriority: 100
HPA的版本和能力
HPA版本号 | 功能范围 |
---|---|
autoscaling/v1 | 仅支持基于CPU指标的HPA |
autoscaling/v2beta1 | 可支持基于核心指标、自定义指标的HPA |
autoscaling/v2beta2 | 可支持基于核心指标、自定义指标、外部指标的HPA |
自定义指标HPA的工作原理
整体框架
HPA控制器通过List&Watch机制遍历所有的HPA配置文件
HPA控制器调用Api-Server获取指标数据,Api-Server通过聚合API将请求分发给Prometheus Adapter
Prometheus Adapter收到请求后,调用Prometheus的API获取指标数据返回
HPA控制器根据获取到的指标值以及HPA配置文件中指定的目标指标值来动态伸缩副本数量
HPA控制器调整副本数量的算法为: 副本数 = ceil[当前副本数 * ( 当前指标值 / 指定指标值 )]
自定义指标HPA的使用
K8s集群部署Prometheus Adapter
# 1. 部署完成后,可以看到Prometheus Adapter往Api-Server中注册了这两个API [docker@ccse-0001 ~]$ kubectl get apiservices | grep metrics v1beta1.custom.metrics.k8s.io kube-system/prometheus-adapter True 8d v1beta1.metrics.k8s.io kube-system/prometheus-adapter True 8d # 2. 然后可以通过Api-Server查到指标数据,如Node的CPU和内存数据 [docker@ccse-0001 ~]$ kubectl get --raw "/apis/metrics.k8s.io/v1beta1/nodes/172.16.200.24" { "kind":"NodeMetrics", "apiVersion":"metrics.k8s.io/v1beta1", "metadata":{ "name":"172.16.200.24", "selfLink":"/apis/metrics.k8s.io/v1beta1/nodes/172.16.200.24", "creationTimestamp":"2021-10-26T11:07:09Z" }, "timestamp":"2021-10-26T11:07:09Z", "window":"1m0s", "usage":{ "cpu":"856m", "memory":"25707556Ki" } } # 3. 再如Pod的CPU和内存数据 [docker@ccse-0001 ~]$ kubectl get --raw "/apis/metrics.k8s.io/v1beta1/namespaces/default/pods/curl-d7f94d689-x2hvz" { "kind":"PodMetrics", "apiVersion":"metrics.k8s.io/v1beta1", "metadata":{ "name":"curl-d7f94d689-x2hvz", "namespace":"default", "selfLink":"/apis/metrics.k8s.io/v1beta1/namespaces/default/pods/curl-d7f94d689-x2hvz", "creationTimestamp":"2021-10-26T11:10:40Z" }, "timestamp":"2021-10-26T11:10:40Z", "window":"3m0s", "containers":[ { "name":"POD", "usage":{ "cpu":"0", "memory":"800Ki" } }, { "name":"container1", "usage":{ "cpu":"0", "memory":"2780Ki" } }, { "name":"", "usage":{ "cpu":"0", "memory":"3580Ki" } } ] }
创建HPA配置文件
apiVersion: autoscaling/v2beta1 kind: HorizontalPodAutoscaler metadata: name: php-apache spec: # 指定目标工作负载,这里将自动调节php-apache这个Deployment的Pod数量 scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: php-apache # 指定自动调节Pod数量的范围 minReplicas: 1 maxReplicas: 10 # 指定自动调节Pod数量的依据,这里指定了三条依据 # HPA控制器将会依次评估每一条依据所需要调节的Pod数量,最后选择最大值来调整Pod数量 metrics: # 第一条规则指定HPA控制器要调用`metrics.k8s.io`组下的API查询目标Pod的当前CPU使用量 # 计算这条规则的期望副本数: 副本数 = ceil[当前副本数 * ( 当前CPU利用率 / 指定CPU利用率 )] - type: Resource resource: name: cpu target: type: AverageUtilization averageUtilization: 50 # 第二条规则指定HPA控制器要调用`custom.metrics.k8s.io`组下的API查询`packets-per-second`指标值 # 计算这条规则的期望副本数: 副本数 = ceil[当前副本数 * ( 当前指标值 / 指定指标值 )] - type: Pods pods: metric: name: packets-per-second target: type: AverageValue averageValue: 1k # 第三条规则指定HPA控制器要调用`custom.metrics.k8s.io`组下的API查询`requests-per-second`指标值 # 计算这条规则的期望副本数: 副本数 = ceil[当前副本数 * ( 当前指标值 / 指定指标值 )] - type: Object object: metric: name: requests-per-second describedObject: apiVersion: networking.k8s.io/v1beta1 kind: Ingress name: main-route target: kind: Value value: 10k