- Java锁的逻辑(结合对象头和ObjectMonitor)
- 还在用饼状图?来瞧瞧这些炫酷的百分比可视化新图形(附代码实现)⛵
- 自动注册实体类到EntityFrameworkCore上下文,并适配ABP及ABPVNext
- 基于Sklearn机器学习代码实战
大家好,我是蓝胖子,都知道,k8s拥有自动扩缩容机制HPA,我们能够通过配置针对不同的扩缩容场景进行自动扩缩容,往往初学者在面对其中繁多配置的时候会学了又忘记,今天我将会以一种不同的视角,结合api server 请求 来探索这部分的配置,看完本篇,应该会对扩缩容这部分配置会有更深的理解.
我们先来看一下自动扩缩容的原理,在k8s中HPA这个模块的逻辑会定时请求api server 获取相应的pod或者CRD或者其他资源的指标信息,这些指标信息是用户创建HPA的yaml配置文件时指定的.
api server收到请求后,根据请求的api group,api version 转发给内部的api service服务进行处理,当我们想让k8s借用prometheus的相关指标进行扩缩容时,就需要在集群里用api service的方式安装prometheus adapter,它会将发往api server的请求经过包装,转发到prometheus服务器获取对应指标信息,然后将结果经过封装返回给客户端即HPA模块。HPA模块收到指标后,在根据自身配置文件中的target值判断是否需要进行自动扩缩容.
既然提到了prometheus adapter是以api service 方式安装到k8s集群中的,我再对api server的架构已经处理请求的方式再阐述下.
api server 处理请求的方式是链式的,你可以简单的理解为api server里有多个http server ,当某个请求的路径不属于某个http server处理范畴内的话,会将这个请求委托给下一个http server进行处理。同时,k8s允许用户自定义api service作为http server,prometheus adapter 就是一个自定义的api service.
向api server发送http请求,请求格式是按一定规则进行组装的,我主要查看了HPA模块源码,所以拿这块去举例,hpa发往api server的请求是将api version和api group 以及要请求资源的命名空间,资源名拼接到一起组成的路径。如下
不同的HPA指标类型这个路径的拼接会有所不同(下面会详细讲到),但是整体的api风格是和这个一致的.
当HPA在向api server发送请求的时候则是根据不同的扩缩容指标类型选择了不同的api group 去发送请求.
❗️❗️📢 注意,这里HPA选择的api group是k8s这部分代码已经固定好了的,所以prometheus adapter在以api service安装时指定的api group 需要和这里吻合。目前针对指标类型,HPA会从metrics.k8s.io, customer.metrics.k8s.io, external.metrics.k8s.io这3个api group种选取对应的group.
接下来,我们来详细看下,HPA扩缩容的4种指标类型.
先看第一种pods类型,它表示的是由pod产生的指标, 其在HPA声明的配置yaml文件里写法如下, 。
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: sample-app
namespace: default
spec:
maxReplicas: 10
minReplicas: 2
metrics:
- pods:
metric:
name: http_requests
selector:
matchLabels:
<label-key>: <label-value>
target:
averageValue: 500m
type: AverageValue
type: Pods
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: sample-app
可以看到spec.metrics.type 值为pods类型,HPA的pods 指标类型 是指pod这个资源对象产生的指标,其中定义了指标名为http_requests,最终发往api server的url path如下所示, 。
/apis/custom.metrics.k8s.io/v1beta1/namespaces/default/pods/*/http_requests?labelSelector=<label-key>=<label-value>
api server 收到这个请求后会将请求转发给prometheus adapter,那么prometheus adapter 又是如何将http_requests 与具体的prometheus中的指标对应起来的呢?
prometheus adapter在启动的时候我们会配置一个规则配置文件,在这个文件定义了这个映射关系,下面是这针这种类型的指标配置规则部分, 。
rules:
- seriesQuery: 'http_requests_total{}'
resources:
overrides:
kubernetes_namespace: {resource: "namespace"}
kubernetes_pod_name: {resource: "pods"}
name:
matches: "http_requests_total"
as: "http_requests"
metricsQuery: 'sum(rate(<<.Series>>{<<.LabelMatchers>>}[2m])) by (<<.GroupBy>>)'
我们将hpa配置文件和发往api server的请求以及prometheus adapter的规则文件结合起来,看看prometheus adapter 规则文件里那些模板变量的含义.
首先是hpa的配置文件中指定了metric.name是http_requests,http_requests在prometheus adapter的配置文件里是将prometheus的http_requests_total与之对应了起来,并且从规则配置文件的resources.overrides 配置中可以发现namespace和pods资源在指标http_requests_total中会有kubernetes_namespace和kubernetes_pod_name标签与之对应,这层关系其实主要是为了metricsQuery 中模板变量的替换.
metricsQuery 中 <<.Series>> 其实就是seriesQuery这部分.
<<.LabelMatchers>> 是筛选指标时的标签,在hpa里面我们指定了metric.selector,发往api server的请求里的参数labelSelector就会替代<<.LabelMatchers>>模板变量,同时发往api server请求中的namespace的值也会写到<<.LabelMatchers>>中,并且namespace的对应标签名就是resources.overrides中定义的kubernetes_namespace.
<<.GroupBy>> 变量在这里会将k8s的resource资源类型作为分组的维度,并且在这个场景下,在发往api server的请求中,k8s的资源是pods类型,而pods类型在指标中的标签名是kubernetes_pod_name.
所以最终,在prometheus 中进行查询时执行的promql语句为.
sum(rate(http_requests_total{"kubernetes_namespace":"default","<label-key>":"<label-value>"}[2m])) by (kubernetes_pod_name)
在看了pods类型的hpa指标后,我们再来看看Object类型的指标是如何配置的,因为在k8s里资源类型除了pod类型,还有其他类型,所以如果由其他资源类型产生的指标,则由Object来表示.
先看下hpa的yaml配置文件是如何写的.
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: sample-app
namespace: default
spec:
maxReplicas: 10
minReplicas: 2
metrics:
- object:
metric:
name: requests-per-second
describedObject:
apiVersion: extensions/v1beta1
kind: Ingress
name: main-route
target:
type: Value
value: 2k
type: Object
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: sample-app
发往api server的请求格式如下 。
/apis/custom.metrics.k8s.io/v1beta1/namespaces/default/ingress/main-route/requests-per-second
prometheus adapter配置此类规则和Pods类型类似,模板变量解析方式也是类似,唯一有点不一样的是此时的<<.GroupBy>> 模板变量会被ingress/main-route 也就是资源名加上资源示例名替代.
接着看一下hpa中的Resource类型的指标配置,它表示对pod的cpu或者内存值来进行扩缩容,本质上可以用Pods 类型的配置来代替这部分配置,那为什么还有Resource类型呢?因为Resource出来的时候还没有Pods 类型.
Kubernetes 1.20 在 HorizontalPodAutoscaler (HPA) 中引入了 ContainerResource 类型指标,不论是Resource还是ContainerResource都只能对cpu和内存这两个维度进行监控,它们的区别如下, 。
Resource 计算pod的资源使用率是 。
sum{每个容器的资源使用量} / sum{每个容器的资源请求}
但是一个pod有多个容器,可能会出现单个容器资源使用率高,但是平均下来每个容器资源使用率低的情况,而ContainerResource 则能够指定以pod中的哪个容器拿来计算扩容指标,能够提供更准确的扩容机制.
ContainerResource在hpa的yaml配置文件中配置如下,其中container标签指明了容器名称.
type: ContainerResource
containerResource:
name: cpu
container: application
target:
type: Utilization
averageUtilization: 60
而Resource类型的扩容指标则是针对pod中所有容器计算指标, 。
type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 60
它们发往api server 的请求格式如下 。
/apis/metrics.k8s.io/v1beta1/namespaces/default/pods
注意,这里的配置文件没有加上selector,实际上我们平时写配置文件的时候肯定是有selector的,所以发往api server的请求也会有selector的参数 。
prometheus adapter 在收到这个请求后,会将对应的pod的cpu和内存信息全部返回,然后k8s的hpa模块筛选其需要用到的部分,像ContainerResource就会筛选返回结果中和container标签值代表的容器名称一样的指标进行计算.
prometheus adapter针对此类型的指标规则配置如下, 其中的containerLabel 表明了指标中容器名称是用哪个标签表示的,此时的<<.GroupBy>>模板变量 会由pod资源名称和容器名标签两个维度替代.
以下是prometheus adapter官方给出的配置模版,自己配置的时候需要改掉实际查询的指标名已经标签名等.
"resourceRules":
"cpu":
"containerLabel": "container"
"containerQuery": |
sum by (<<.GroupBy>>) (
irate (
container_cpu_usage_seconds_total{<<.LabelMatchers>>,container!="",pod!=""}[4m]
)
)
"nodeQuery": |
sum by (<<.GroupBy>>) (
irate(
node_cpu_usage_seconds_total{<<.LabelMatchers>>}[4m]
)
)
"resources":
"overrides":
"namespace":
"resource": "namespace"
"node":
"resource": "node"
"pod":
"resource": "pod"
"memory":
"containerLabel": "container"
"containerQuery": |
sum by (<<.GroupBy>>) (
container_memory_working_set_bytes{<<.LabelMatchers>>,container!="",pod!=""}
)
"nodeQuery": |
sum by (<<.GroupBy>>) (
node_memory_working_set_bytes{<<.LabelMatchers>>}
)
"resources":
"overrides":
"node":
"resource": "node"
"namespace":
"resource": "namespace"
"pod":
"resource": "pod"
"window": "5m"
最后,我们来看下external 类型的扩容指标如何配置,上面讲到的hpa 扩缩容指标类型都是在k8s集群里产生的指标,它们都限定在了一个namespace里面,除此以外,hpa模块还允许配置第三方的指标类型,比如集群外部的消息队列产生的指标,这类型的指标被称作External类型。 在hpa里配置案例如下, 。
type: External
external:
metric:
name: queue_messages_cnt
selector:
matchLabels:
app: "lanpangzi"
# External指标类型下只支持Value和AverageValue类型的目标值
target:
type: AverageValue
averageValue: 30
发往api server的请求格式如下 。
/apis/external.metrics.k8s.io/v1beta1/namespaces/default/queue_messages_cnt
由于外部指标和namespace无关,所以在配置prometheus adapter的规则配置文件的时候,指定下指标是namespace无关的.
externalRules:
- seriesQuery: 'queue_messages_cnt'
resources:
namespaced: false
name:
matches: 'queue_messages_cnt'
as: 'queue_messages_cnt'
metricsQuery: avg(<<.Series>>{<<.LabelMatchers>>})
探索HPA配置的含义过程中,其实可以发现k8s在针对HPA扩容依据的拓展方式上,就是规定了3组api group(metrics.k8s.io,external.metrics.k8s.io,custom.metrics.k8s.io),并且用基本一致的http请求,让第三方(prometheus adapter)在声明为api service 的时候指定为对应的api group,然后解析请求路径和参数来进而对prometheus查询 即完成了对HPA扩容指标的查询.
关于prometheus adapter更多的配置案例建议直接看prometheus adapter的doc目录下的示例.
最后此篇关于k8s自动扩缩容HPA原理及adapter配置详解的文章就讲到这里了,如果你想了解更多关于k8s自动扩缩容HPA原理及adapter配置详解的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
前言 “大伙得眼里有活,看见同事忙的时候要互相帮助,这样我们团队才能快速成长,出成绩,多干点活没坏处的,领导都看在眼里记在心里,不会亏待大伙。
我目前正在尝试使用 prometheus 和 prometheus 适配器运行一个自动缩放演示,我想知道是否有一种方法可以根据 prometheus 从另一个部署中收集的指标自动缩放我的一个部署。 我
我们有一个Istio集群,我们正在尝试为Kubernetes配置水平容器自动缩放。我们希望将请求计数用作hpa的自定义指标。我们如何才能将Istio的Prometheus用于同一目的? 最佳答案 事实
我有两个彩色轨道,我在其中部署了两个不同版本的 web 应用程序 (nginx+php-fpm),这些轨道可通过称为 live 和 next 的服务使用。 经典的方式是部署Web应用程序的新版本接下来
副本和 HPA 有什么区别? 例如,以下部署配置了 3 个副本 apiVersion: apps/v1 kind: Deployment metadata: name: hello spec:
有没有办法在 Azure Kubernetes 服务上启用基于“每秒请求”的扩展? AKS 中的 HPA 确实允许基于 CPU 和内存限制进行水平 Pod 扩展,但没有直接的方法来实现这一点 - 每秒
HPA-如何避免因CPU使用率激增而扩大规模(不在启动时) 在为其他国家/地区加载业务配置时,CPU负载会增加1分钟,但我们要避免在1分钟内扩大规模。 在下面的图片中,CurrentMetricVal
我正在运行带有HPA的Kubernetes集群v1.16(当前是GKE的最新版本),该集群可基于自定义指标(具体来说是从Google云监控中获取的Rabbitmq消息计数)来扩展部署。 问题 当消息数
我在HPA上发现istio网关有问题。 为什么10m等于10%? 10m 1%不是吗? Kubernetes版本是1.18.5。 # kubectl get hpa --all-namespaces
我们的Web服务API上似乎遇到了一些内部服务器错误(500),似乎是在作为自动缩放器配置的一部分引入或删除了新容器时。 自然,这种事情很难解决,因为您并不总是能够控制 pods 的启动和停止的时间。
从 Kubernetes v1.18 开始,v2beta2 API 允许通过 Horizontal Pod Autoscalar (HPA) 行为字段配置缩放行为。 我计划将具有自定义指标的 HP
我想要实现的是创建一个能够扩展的 Horizontal Pod Autoscaler worker根据 controller 生成的自定义指标生成 Pod荚。 我已经让 Prometheus 抓取
问题设置。 假设我有 2 个 pod,A 和 B。我希望能够根据来自某个任意来源的某个任意数字动态缩放 pod A。假设 pod B 是这样一个源:例如,它可以有一个 HTTP 服务器,它的端点在请求
我正在尝试配置 kubernetes 水平 pod 自动缩放。我部署的定义是 here . 我开始 heapster 部署和 heapster 服务,如下所示: # kubectl run heaps
我终于部署了与其中一个部署相关的 hpa,但 hpa 没有按预期工作。我可以看到利用率远远超过实际情况,甚至不匹配所有 pod 的利用率总和。不确定这个平均利用率是如何计算的,当有 2 个 pod 的
是否有一个“主开关”来启用/禁用 Keda 和 HPA?我可以通过将副本计数编辑为 0 来启用/禁用扩展规则,但是是否有主要的启用/禁用字段? cooldownPeriod: 1800 max
我有一个在 Kubernetes 集群上运行的 openjdk:8 镜像。我添加了内存 HPA(Horizontal Pod Autoscaling),它可以很好地扩展,但由于 JVM 不会将内存
我正在尝试基于GPU利用率在GCP中实现水平荚自动缩放(HPA)。 我的hpa.yaml文件如下所示: kind: HorizontalPodAutoscaler metadata: name:
我已经为我在 Kubernetes 中的部署之一配置了 hpa。 有什么方法可以检查部署中是否发生 HPA 缩放以及何时发生? 我没有部署普罗米修斯或任何监控解决方案。 最佳答案 如果您创建了 HPA
所以这发生在 EKS K8s v1.15 上。您可以在 describe 输出中看到 api 版本。 millicpu 在 80 到 120 之间徘徊……这与 HPA 输出的副本数完全不匹配…… 这是
我是一名优秀的程序员,十分优秀!