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

写在前面
我们平时部署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 version
Client 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 node
NAME 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-server
kubectl top node
部署一个测试的Pod(Webapi)
创建一个hpa-api.yaml的文件内容如下:
apiVersion: apps/v1
kind: Deployment
metadata:
name: hpa-api
spec:
selector:
matchLabels:
app: hpa-api
replicas: 1
template:
metadata:
labels:
app: hpa-api
spec:
containers:
- name: hpa-api
image: gebiwangshushu/hei-ocelot-api:1.0 #这是我写其他文章上传的镜像,代码:https://github.com/gebiWangshushu/Hei.Ocelot.ApiGateway/blob/master/Hei.Api/Controllers/WeatherForecastController.cs
ports:
- containerPort: 80
resources:
requests:
cpu: 1000m
memory: 100Mi
# limits:
# cpu: 100m
# memory: 100Mi
---
apiVersion: v1
kind: Service
metadata:
name: hpa-api
labels:
app: hpa-api
spec:
ports:
- port: 80
nodePort: 30999
type: NodePort
selector:
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;
访问看看:

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/v1
kind: 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: Utilization
averageUtilization: 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 hpa
NAMESPACE 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-api
Name: 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 4
ScalingActive 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.io、custom.metrics.k8s.io 或 external.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
类似本实例的示意图:

可以看到这里的指标,是针对所有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://www.cnblogs.com/fanggege/p/12299923.html
k8s HPA(HorizontalPodAutoscaler)--自动水平伸缩的更多相关文章
- k8s Pod的自动水平伸缩(HPA)
我们知道,当访问量或资源需求过高时,使用:kubectl scale命令可以实现对pod的快速伸缩功能 但是我们平时工作中我们并不能提前预知访问量有多少,资源需求多少. 这就很麻烦了,总不能为了需求总 ...
- 在阿里云上进行Docker集群的自动弹性伸缩
摘要: 在刚刚结束的云栖大会上,阿里云容器服务演示了容器的自动弹性伸缩,能够从容应对互联网应用的峰值流量.阿里云容器服务不仅支持容器级别的自动弹性伸缩,也支持集群节点级别的自动弹性伸缩.从而真正做到从 ...
- ASP.NET中使用JavaScript实现图片自动水平滚动效果
参照网上的资料,在ASP.NET中使用JavaScript实现图片自动水平滚动效果. 1.页面前台代码: <%@ Page Language="C#" AutoEventWi ...
- k8s HPA自动收缩
HPA自动收缩 autoscale 自动调整一个 Deployment, ReplicaSet, 或者 ReplicationController 的副本数量 #创建一个replicaset测试 [r ...
- kubernetes 水平伸缩及yaml格式编写
Replication Controller:用来部署.升级PodReplica Set:下一代的Replication ControllerDeployment:可以更加方便的管理Pod和Repli ...
- 三十三、HPA实现自动扩缩容
通过HPA实现业务应用的动态扩缩容 HPA控制器介绍 当系统资源过高的时候,我们可以使用如下命令来实现 Pod 的扩缩容功能 $ kubectl -n luffy scale deployment m ...
- Kubernetes自动横向伸缩集群节点以及介绍PDB资源
在kubernetes中,有HPA在需要的时候创建更多的pod实例.但万一所有的节点都满了,放不下更多pod了,怎么办?显然这个问题并不局限于Autoscaler创建新pod实例的场景.即便是手动创建 ...
- k8s资源应用的自由伸缩Scale(up/down)
伸缩(Scale Up/Down)是指在线增加或减少 Pod 的副本数. 1.增加副本 Deployment nginx-deployment初始是两个副本. [root@k8s-master k ...
- Pod Preset玩转K8S容器时区自动配置
缘由默认的情况,在K8S里启动一个容器,该容器的设置的时区是UTC0,但是对于很多客户而言,其主机环境并不在UTC0.例如中国客户在UTC8.如果不把容器的时区和主机主机设置为一致,则在查找日志等时候 ...
- css实现水平伸缩菜单
ul li a{transition:width 500ms ease;} a:hover{width:*;} 高度向上延伸用height:*;margin-top:-*px;//负值实现向上
随机推荐
- 【2020NOI.AC省选模拟#7】A. t1
题目链接 原题解: 由于$+$满足幂等性,我们可以设$f_{i,j}$为从$i$号点向根$2^j$个点的权值之和,并且倍增计算出$f$.在查询是,可以像ST表一样用至多四个$f$中的路径拼出询问路径. ...
- Linux 第二节(基本命令)
www.linuxcool.com 一.ifconfig 1.Ip 地址 2.MAC地址 3.收到的数据包(RX) 4.发送的数据包(Tx) 二.uname uname -a //查看系统内核及 ...
- React-Native笔记--node_modules删除
在开发RN项目过程中,经常会用到删除node_modules文件夹的命令,现总结如下: 方式1: npm install rimraf -g rimraf node_modules方式2: rmdir ...
- 在Unity3D中开发的Sketch Shader
Pencil Sketch Shader 特点 此素描渲染风格的Shader是顶点片元Shader,由本人手动编写完成. 此素描渲染风格的Shader已经在移动设备真机上进行过测试,可以直接应用到您的 ...
- 通过ref调取子组件方法
子 async update(res){ //this.$refs.child.animates(); this.userform = res; }, 主 <DetailEdit @detail ...
- arthas jad 反编译 xxx类 ,报 No class found for:xxx
可能的原因: 类名不对,需要用全限定名,并且注意区分大小写 根据官方的文档,arthas jad 只能反编译已经加载的类.
- Netty基本编写
一. public class Server { public static void main(String[] args) throws Exception { //1 创建线两个程组 //一个是 ...
- xlwings简单使用
xlwings能够非常方便的读写Excel文件中的数据,并且能够进行单元格格式的修改 xlwings基本操作 打开已有的Excel文档 # 导入xlwings模块 # 打开Excel程序,默认设置:程 ...
- 类继承(c++ primer plus)课后习题
第一题: // base class class Cd { // represents a CD disk private: char performers[50]; char label[20]; ...
- 20220720 第七组 陈美娜 Java String用法
关于String引用数据类型 1.字符串中,两个变量的==指的是虚地址 2.String一旦声明不可改变:赋值进去,原值不会被替代.原值也可能指向其他地址: 3.s.length():字符的个数 4. ...