k8s HPA(HorizontalPodAutoscaler)-自动水平伸缩

b8832d8d710c48736f3c32cdae657754.jpeg

Horizontal Pod Autoscaling in Kubernetes

写在前面

我们平时部署web服务,当服务压力大撑不住的时候,我们会加机器(加钱);一般没有上容器编排是手动加的,临时加的机器,临时部署的服务还要改Nginx的配置,最后回收机器的时候,也是手动回收,手动修改Nginx的,挺麻烦的其实;

而K8s是支持这整个流程的自动化的,也就是HPA;

HPA介绍

HPA:全称Horizontal Pod Autoscaler ,对应中文叫Pod的自动水平伸缩

Pod的水平伸缩是水平方向增加/减少Pod的数量;

Pod的垂直伸缩则是垂直方向上控制Pod的硬件,比如增加/缩减CPU、内存等资源;

k8s的HPA一般会根据一个具体的指标来做,比如常见CPU、内存的负载;也可以根据web服务的吞吐量、单位时间内的传输字节数等;另外还可以根据自定义的指标,比如RabbitMQ的队列数量、Webhook等;

我这里先讲讲怎么根据CPU、内存的负载来做HPA;

HPA实操

环境

$ kubectl versionClient Version: version.Info{Major:"1", Minor:"22", GitVersion:"v1.22.5"Server Version: version.Info{Major:"1", Minor:"22", GitVersion:"v1.22.5"
$ kubectl get nodeNAME             STATUS   ROLES                  AGE    VERSION
docker-desktop   Ready    control-plane,master   177d   v1.22.5

检查获取指标是否正常

是否安装了metrics-server

HPA是需要获取具体的指标做伸缩的, metrics-server是提供指标的

$ kubectl  get pod -n kube-system|grep   metrics-server
metrics-server-5d78c4b4f5-x5c46          1/1     Running   2 (3d12h ago)       10d

是否正常获取指标

$ kubectl  top node 
docker-desktop   133m         0%     2671Mi          16%

如果没有的,需先安装metrics-server

安装metrics-server

下载yaml

wget https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml

修改yaml

spec:containers:- args:- --cert-dir=/tmp- --secure-port=4443- --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname- --kubelet-use-node-status-port- --metric-resolution=15s- --kubelet-insecure-tls #加上这个(不推荐生产这样用)#image: k8s.gcr.io/metrics-server/metrics-server:v0.6.1 #这个镜像需要梯子image: registry.cn-hangzhou.aliyuncs.com/chenby/metrics-server:v0.6.1 #换成网友阿里云的镜像imagePullPolicy: IfNotPresent

提交yaml

kubectl apply -f  components.yaml  -n kube-system

再验证

kubectl  get pod -n kube-system|grep   metrics-serverkubectl  top node

部署一个测试的Pod(Webapi)

创建一个hpa-api.yaml的文件内容如下:

apiVersion: apps/v1
kind: Deployment
metadata:name: hpa-api
spec:selector:matchLabels:app: hpa-apireplicas: 1template:metadata:labels:app: hpa-apispec:containers:- name: hpa-apiimage: gebiwangshushu/hei-ocelot-api:1.0 #这是我写其他文章上传的镜像,代码:https://github.com/gebiWangshushu/Hei.Ocelot.ApiGateway/blob/master/Hei.Api/Controllers/WeatherForecastController.csports:- containerPort: 80resources:requests:cpu: 1000mmemory: 100Mi# limits:#   cpu: 100m#   memory: 100Mi
---
apiVersion: v1
kind: Service
metadata:name: hpa-apilabels:app: hpa-api
spec:ports:- port: 80nodePort: 30999type: NodePortselector:app: hpa-api
kubectl apply -f hpa-api.yaml

这里创建了一个测试的webapi,所用镜像是gebiwangshushu/hei-ocelot-api:1.0,源码在这;这个Deployment的副本数是1,资源requests为cpu: 1000m         memory: 100Mi;并且创建了一个nodePort:30999 类型的Service;

访问看看:

424c35c54cdc8e0ae27091e582734469.png
image-20221008112122162

172.16.6.90 是我自己k8s集群的地址;测试的webapi部署好了,我们来给他创建一个HPA(HorizontalPodAutoscaler);

创建HPA--HorizontalPodAutoscaler

查看当前HPA支持版本:

$ kubectl api-versions|grep autoscaling
autoscaling/v1
autoscaling/v2beta1
autoscaling/v2beta2

autoscaling/v1:  只支持基于CPU的自动伸缩autoscaling/v2beta1: 支持Resource Metrics(资源指标,如pod的CPU)和Custom Metrics(自定义指标)的缩放。autoscaling/v2beta2:支持Resource Metrics(资源指标,如pod的CPU)和Custom Metrics(自定义指标)和ExternalMetrics(额外指标)的缩放。

创建一个HPA.yaml的文件,内容如下:

apiVersion: autoscaling/v2beta2 
kind: HorizontalPodAutoscaler
metadata:name: hpa-api
spec:scaleTargetRef:apiVersion: apps/v1kind: Deployment  #针对Deployment做伸缩name: hpa-api minReplicas: 1   #最小副本数maxReplicas: 10  #最大副本数metrics: - type: Resource resource:name: cpu target:type: Utilization  #Utilization 使用率做指标averageUtilization: 50 #CPU平均使用率超requests要求的cpu的50%时,开始做扩容#type: averageValue #averageValue: 30  #使用平均值averageValue(平均值) 做指标
  • type: Utilization   #Utilization 表示用使用率作为指标,此外还有Value 或 AverageValue

  • averageUtilization:  50  表示CPU平均使用率超requests要求的cpu的50%时,开始做扩容

  • apiVersion: autoscaling/v2beta2  autoscaling的版本,不同版本的字段和支持的指标不一样;

当然,这里的apiVersion: autoscaling/v2beta2 ,支持还支持很多参数,例如:

metrics: - type: Resource resource:name: cpu target:type: UtilizationaverageUtilization: 60 #CPU平均负载超requests60%时,开始做扩容# - type: Resource#   resource:#     name: cpu #     target:#       type: AverageValue #       averageValue: 500m # - type: Pods #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/v1#       kind: Ingress#       name: main-route#     target:#       type: Value#       value: 10k# behavior: #控制伸缩行为速率的#   scaleDown: #     policies: #支持多个策略#     - type: Pods #       value: 4 #       periodSeconds: 60  #60秒内#最多缩容4个pod#     - type: Percent#       value: 300  #       periodSeconds: 60 #60秒内#最多缩容300%#     selectPolicy: Min#     stabilizationWindowSeconds: 300 #   scaleUp: #     policies: #     - type: Pods#       value: 5 #       periodSeconds: 60 #60秒内#最多缩容5个pod#     # - type: Percent#     #   value: 100  #最多扩容100%#     #   periodSeconds: 60 #60秒内#     selectPolicy: Max#     stabilizationWindowSeconds: 0

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

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

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

  • Pods:指的是伸缩对象(statefulSet、replicaController、replicaSet)底下的Pods的指标,数据需要第三方的adapter提供,并且只允许AverageValue类型的目标值。

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

另外还有自定义指标等,需要1.23及以上版本才支持了;

创建HPA资源

kubectl apply -f HPA.yaml

查看HPA

$ kubectl get hpaNAMESPACE    NAME      REFERENCE            TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
aspnetcore   hpa-api   Deployment/hpa-api   0%/50%    1         10        1          8d

验证

hpa开启watch监控模式

$ kubectl get hpa --watch
NAME      REFERENCE            TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
hpa-api   Deployment/hpa-api   0%/50%    1         10        1          8d
... 
#阻塞监听状态

用ab压测工具压一下

ab -n 200000 -c 10 http://172.16.6.90:30999/user

没安装的自己搜索安装下,这里的 -n:请求个数,-c : 请求并发数

查看资源使用情况

$ kubectl top po
NAME                      CPU(cores)   MEMORY(bytes)
hpa-api-88ddc5c49-2vgjd   1m           301Mi
hpa-api-88ddc5c49-4h5pz   1m           300Mi
hpa-api-88ddc5c49-8c8d2   1m           340Mi
hpa-api-88ddc5c49-8hmnm   1m           300Mi
hpa-api-88ddc5c49-cgxm9   1m           23Mi
hpa-api-88ddc5c49-tdrc6   1m           23Mi

扩容情况

kubectl get hpa --watch
NAME      REFERENCE            TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
hpa-api   Deployment/hpa-api   0%/50%    1         10        1          8d
hpa-api   Deployment/hpa-api   262%/50%   1         10        1          8d
hpa-api   Deployment/hpa-api   33%/50%    1         10        4          8d
hpa-api   Deployment/hpa-api   0%/50%     1         10        6          8d  #这里请求结束了

伸容过程

$ kubectl describe hpa hpa-apiName:                                                  hpa-api
...
Reference:                                             Deployment/hpa-api
Metrics:                                               ( current / target )resource cpu on pods  (as a percentage of request):  262% (2628m) / 50%  #这里资源直接远超1000m的50%,达到了262% (2628m)
Deployment pods:                                       1 current / 4 desired
..
Deployment pods:                                       1 current / 4 desired
Conditions:Type            Status  Reason            Message----            ------  ------            -------AbleToScale     True    SucceededRescale  the HPA controller was able to update the target scale to 4ScalingActive   True    ValidMetricFound  the HPA was able to successfully calculate a replica count from cpu resource utilization (percentage of request)ScalingLimited  True    ScaleUpLimit      the desired replica count is increasing faster than the maximum scale rateEvents:Type    Reason             Age   From                       Message----    ------             ----  ----                       -------Normal  SuccessfulRescale  39s   horizontal-pod-autoscaler  New size: 4; reason: cpu resource utilization (percentage of request) above target #扩容到4个Normal  SuccessfulRescale  3m11s  horizontal-pod-autoscaler  New size: 6; reason: All metrics below target #扩容到6个

一旦 CPU 利用率降至 0,HPA 会自动将副本数缩减为 1;

扩容详情

HPA 控制器基于 Master 的 kube-controller-manager 服务启动参数 --horizontal-pod-autoscaler-sync-period 定义的探测周期(默认值为 15s) , 周期性地监测目标 Pod 的资源性能指标, 并与 HPA 资源对象中的扩缩容条件进行对比, 在满足条件时对 Pod 副本数量进行调整

在每个时间段内,控制器管理器都会根据每个 HorizontalPodAutoscaler 定义中指定的指标查询资源利用率。控制器管理器找到由 scaleTargetRef 定义的目标资源,然后根据目标资源的 .spec.selector 标签选择 Pod, 并从资源指标 API(针对每个 Pod 的资源指标)或自定义指标获取指标 API(适用于所有其他指标)。

  • 对于按 Pod 统计的资源指标(如 CPU),控制器从资源指标 API 中获取每一个 HorizontalPodAutoscaler 指定的 Pod 的度量值,如果设置了目标使用率, 控制器获取每个 Pod 中的容器资源使用 情况, 并计算资源使用率。如果设置了 target 值,将直接使用原始数据(不再计算百分比)。接下来,控制器根据平均的资源使用率或原始值计算出扩缩的比例,进而计算出目标副本数。

    需要注意的是,如果 Pod 某些容器不支持资源采集,那么控制器将不会使用该 Pod 的 CPU 使用率。

  • 如果 Pod 使用自定义指示,控制器机制与资源指标类似,区别在于自定义指标只使用 原始值,而不是使用率。

  • 如果 Pod 使用对象指标和外部指标(每个指标描述一个对象信息)。这个指标将直接根据目标设定值相比较,并生成一个上面提到的扩缩比例。在 autoscaling/v2beta2 版本 API 中,这个指标也可以根据 Pod 数量平分后再计算。

HorizontalPodAutoscaler 的常见用途是将其配置为从(metrics.k8s.iocustom.metrics.k8s.ioexternal.metrics.k8s.io)获取指标。metrics.k8s.io API 就是我们前面安装Metrics Server 的插件;

扩容算法

期望副本数 = ceil[当前副本数 * (当前指标 / 期望指标)]

例如,如果当前指标值为 200m,而期望值为 100m,则副本数将加倍, 因为 200.0 / 100.0 == 2.0 如果当前值为 50m,则副本数将减半, 因为 50.0 / 100.0 == 0.5。如果比率足够接近 1.0(在全局可配置的容差范围内,默认为 0.1), 则控制平面会跳过扩缩操作。

套入上面的实例:

期望副本数 = ceil[ 1 * (262% / 50%)] == 6

类似本实例的示意图:

db55c5e002442c9007d53a2143cf31ec.png
img

可以看到这里的指标,是针对所有pod的;

总结

k8s的东西太多,只学了点皮毛,有个基本的概念就赶紧记下来;k8s集群版本、HPA的版本的不同又有很多限制与字段的区别,需要后面更多的实践与学习;

[参考]

https://kubernetes.io/zh-cn/docs/tasks/run-application/horizontal-pod-autoscale/#algorithm-details

https://blog.51cto.com/smbands/4903843

https://kubernetes.io/zh-cn/docs/reference/kubernetes-api/workload-resources/horizontal-pod-autoscaler-v2beta2/

https://www.cnblogs.com/fanggege/p/12299923.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/281775.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

spark java 逻辑回归_逻辑回归分类技术分享,使用Java和Spark区分垃圾邮件

原标题:逻辑回归分类技术分享,使用Java和Spark区分垃圾邮件由于最近的工作原因,小鸟很久没给大家分享技术了。今天小鸟就给大家介绍一种比较火的机器学习算法,逻辑回归分类算法。回归是一种监督式学习的方式,与分类类似…

jQuery.extend()方法

定义和用法jQuery.extend()函数用于将一个或多个对象的内容合并到目标对象。 注意: 1. 如果只为$.extend()指定了一个参数,则意味着参数target被省略。此时,target就是jQuery对象本身。通过这种方式,我们可以为全局对象jQuery添加…

Wget用法、参数解释的比较好的一个文章

一个语句就可以下载cvpr2016的全部论文: wget -c -N --no-clobber --convert-links --random-wait -r -p -E -e robotsoff -U mozilla http://www.cv-foundation.org/openaccess/CVPR2016.py 其中,-c表示断点续传;-N表示已经下载的内容不再重…

.NET VS智能提示汉化 (.Net6)

先上现成的.net6汉化文件,可以手动下载后参照 [如何为 .NET 安装本地化的 IntelliSense 文件 ](https://learn.microsoft.com/zh-cn/dotnet/core/install/localized-intellisense)进行安装。或者使用后文的工具进行自动安装。无对照英文在前中文在前汉化内容来自 官…

老人寻求到一名程序员,用2W行代码给自己打造了一幅肖像画

今天翻墙看了下国外的论坛,看到了一位版主给一位老人描绘肖像画的文章,不得不说这位大佬是真的厉害,近20000行代码,而且还画的很像,像小编我这种手残党,用笔也不能画出来,不得不服,今…

一题多解,ASP.NET Core应用启动初始化的N种方案[下篇]

[接上篇]“天下大势,分久必合,合久必分”,ASP.NET应用通过GenericWebHostService这个承载服务被整合到基于IHostBuilder/IHost的服务承载系统中之后,也许微软还是意识到Web应用和后台服务的承载方式还是应该加以区分,于…

GitHub服务中断24小时11分钟事故分析报告\n

上周,GitHub经历了一次事故,导致服务降级24小时11分钟。虽然平台的某些部分不受事故影响,但仍然有多个内部系统受到了影响,向用户显示了过时且不一致的内容。所幸没有用户数据丢失,但针对几秒钟数据库写入的手动调整工…

php 合并 字符串_PHP如何去重合并字符串

本篇文章主要给大家介绍PHP如何去重合并字符串。推荐教程:《PHP教程》对于PHP学习者来说,合并多个字符串,应该并不是很难。但是如果这多个字符串中,有相同元素,当我们想要合并他们并且要使其值具有唯一值。也就是说合并…

软概(lesson 2):课堂测试

一、测试题目 二、完成过程 1.设计思想 ①连接mysql数据库 ②设计user类,增加参数 ③设计add类,向数据库内增加内容 ④设计addInput页面,完成录入操作 ⑤设计add页面,接收录入的参数,并调用add类函数 2.源代码 user.ja…

谷歌Gboard输入法新增“无痕模式”:仅在Chrome隐身窗口中适用

据外媒Android Police报道,如大家所知道的,Chrome浏览器中的“隐身模式”是为了防止你的私密浏览记录被其他人看到,但是,在这种模式下,你的输入法键盘依然会记住你输入的短语,为了阻止你的键盘在Chrome隐身…

php两个数组融合,php合并两个数组的方式有哪些

1、arrary_merge示例代码:$arr1 array(1, 2, 3, 4, 5);$arr2 array(1, 2, 6, 7, 8, 9, 10);$result1 array_merge($arr1, $arr2);$arr3 array("name" > "itbsl", "age" > 13, "sex" > "Male");$arr…

最近对latin-1这个字符集产生了不少好感

【简介】 最近我要解析一个数据库中间件的日志、这个中间件会在日志中记录SQL发往的后台DB ,执行耗时,对应的SQL;中间件直接把SQL写到 了日志中去,并没有对SQL进行适当的编码转换;理想情况下这个也不会有什么问题,不幸…

面象对象设计原则之六:迪米特原则(LeastKnowledge Principle, LKP)

迪米特法则来自于1987年美国东北大学(Northeastern University)一个名为“Demeter”的研究项目。迪米特法则又称为最少知识原则(LeastKnowledge Principle, LKP),其定义如下: 迪米特法则(Law of Demeter, LoD):一个软件实体应当尽可能少地与…

其他对象的表单

1.textarea&#xff1a; textarea对象就想是input对象中的text样式的表单&#xff0c;只不过是扩展过的text样式表单。它可以通过行&#xff08;rows&#xff09;属性和列&#xff08;cols&#xff09;属性来编辑文本域的大小。最常见于留言板、论坛时回帖时的文本框等。 <h…

WinForm(十三)WebView2

WebView是WinForm框架中一个控件&#xff0c;用来对网页信息交互&#xff0c;有时Web自己开发的&#xff0c;有时Web是三方的。下面通过一个例子来看看WebView2的使用。首先看Web的逻辑&#xff0c;是一个商品添加页面&#xff0c;用AlpineJS和BootStrap来开发的&#xff0c;业…

Fluent UDF【4】:C语言

Fluent UDF利用的是C语言&#xff0c;本文简单介绍在UDF中经常会用到的C语言常识。 本文部分内容来自UDF手册。 1 C语言中的注释 C语言中的注释利用/*及*/来实现。例如: /*这是一个注释*/ 注释也可以跨行实现&#xff0c;如: /*这是一个 跨行注释*/ 注意:在编写UDF的过程中&…

java 画砖块,钢笔画入门:教你画砖块

说到砖块很多朋友会想到搬砖&#xff0c;绘画吧今天要教大家用钢笔画一块砖&#xff0c;因为画建筑的时候经常要画砖墙&#xff0c;我们先从简单的砖块学起&#xff0c;之后绘画吧会给大家分享画一面砖墙的哦。绘制要点&#xff1a;本教程的主体物选择了一块有小残缺面的砖头。…

[转] Node.js的线程和进程

[From] http://www.admin10000.com/document/4196.html 前言 很多Node.js初学者都会有这样的疑惑&#xff0c;Node.js到底是单线程的还是多线程的&#xff1f;通过本章的学习&#xff0c;能够让读者较为清晰的理解Node.js对于单/多线程的关系和支持情况。同时本章还将列举一些让…

第三方支付异步通知的陷阱

版权声明&#xff1a;本文为博主原创文章&#xff0c;未经博主允许不得转载。 https://blog.csdn.net/j16421881/article/details/78703792 用户下单后调用第三方支付付款&#xff0c;然后接收第三方支付的异步通知&#xff0c;以便确认支付是否成功。 如下图 但异步通知可能…

2.3 万 Star,Nginx 可视化配置工具

你好&#xff0c;这里是 Dotnet 工具箱&#xff0c;定期分享 Dotnet 有趣&#xff0c;实用的工具或组件&#xff0c;希望对您有用&#xff01;对于前后端开发工程师来说&#xff0c; Nginx 是必须掌握的工具&#xff0c;因为它不仅仅是一个 Web Server&#xff0c;还包含了其他…