写在前面

我们平时部署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.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

类似本实例的示意图:

可以看到这里的指标,是针对所有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

k8s HPA(HorizontalPodAutoscaler)--自动水平伸缩的更多相关文章

  1. k8s Pod的自动水平伸缩(HPA)

    我们知道,当访问量或资源需求过高时,使用:kubectl scale命令可以实现对pod的快速伸缩功能 但是我们平时工作中我们并不能提前预知访问量有多少,资源需求多少. 这就很麻烦了,总不能为了需求总 ...

  2. 在阿里云上进行Docker集群的自动弹性伸缩

    摘要: 在刚刚结束的云栖大会上,阿里云容器服务演示了容器的自动弹性伸缩,能够从容应对互联网应用的峰值流量.阿里云容器服务不仅支持容器级别的自动弹性伸缩,也支持集群节点级别的自动弹性伸缩.从而真正做到从 ...

  3. ASP.NET中使用JavaScript实现图片自动水平滚动效果

    参照网上的资料,在ASP.NET中使用JavaScript实现图片自动水平滚动效果. 1.页面前台代码: <%@ Page Language="C#" AutoEventWi ...

  4. k8s HPA自动收缩

    HPA自动收缩 autoscale 自动调整一个 Deployment, ReplicaSet, 或者 ReplicationController 的副本数量 #创建一个replicaset测试 [r ...

  5. kubernetes 水平伸缩及yaml格式编写

    Replication Controller:用来部署.升级PodReplica Set:下一代的Replication ControllerDeployment:可以更加方便的管理Pod和Repli ...

  6. 三十三、HPA实现自动扩缩容

    通过HPA实现业务应用的动态扩缩容 HPA控制器介绍 当系统资源过高的时候,我们可以使用如下命令来实现 Pod 的扩缩容功能 $ kubectl -n luffy scale deployment m ...

  7. Kubernetes自动横向伸缩集群节点以及介绍PDB资源

    在kubernetes中,有HPA在需要的时候创建更多的pod实例.但万一所有的节点都满了,放不下更多pod了,怎么办?显然这个问题并不局限于Autoscaler创建新pod实例的场景.即便是手动创建 ...

  8. k8s资源应用的自由伸缩Scale(up/down)

    伸缩(Scale Up/Down)是指在线增加或减少 Pod 的副本数. 1.增加副本 Deployment   nginx-deployment初始是两个副本. [root@k8s-master k ...

  9. Pod Preset玩转K8S容器时区自动配置

    缘由默认的情况,在K8S里启动一个容器,该容器的设置的时区是UTC0,但是对于很多客户而言,其主机环境并不在UTC0.例如中国客户在UTC8.如果不把容器的时区和主机主机设置为一致,则在查找日志等时候 ...

  10. css实现水平伸缩菜单

    ul li a{transition:width 500ms ease;} a:hover{width:*;} 高度向上延伸用height:*;margin-top:-*px;//负值实现向上

随机推荐

  1. trzcopy

    @echo offcd /d %~dp0setlocal enabledelayedexpansionset aa=伟大的中国!我为你自豪echo 替换前:%aa%echo 替换后:%aa:中国=中华 ...

  2. win10任务栏图标设置“不合并标签但隐藏文字”

    设置如图不分组即可,下载链接 https://files-cdn.cnblogs.com/files/slyuan/7tt_setup.rar

  3. 基于rabbitmq之MQTT协议的智能家居

    智能家居项目 智能可燃气体报警器 产品是一款可燃气体报警器,如果家中燃气泄露浓度到达一定阈值,报警器检测到并上传气体浓度值给后台,后台以电话.短信.微信等方式,提醒用户家中可能有气体泄漏. 用户还可能 ...

  4. 什么是跨域及如何解决、json和jsonp

    1.跨域: 出于浏览器的同源策略限制,同源策略会阻止一个域的javascript脚本和另外一个域的内容进行交互. 同源:即指在同一个域中,就是两个页面具有相同的协议(protocol),主机(host ...

  5. element UI 选择时间点(可选择某一个或者多个时间点)

    html代码如下: <el-date-picker ref="datesRef" type="dates" v-model="searchObj ...

  6. c++学习5 预处理

    一 内存分区 内存的分区变量存储,一般可以分为以下五个区,它们分别是: 可读可写     堆区:使用malloc.calloc.realloc.free以及c++里面的new和delete去动态申请. ...

  7. 2月27日Android开发学习

    App工程目录结构 App工程分为两个层次,第一个层次是项目,另一个层次是模块. 模块依附于项目,每个项目至少有一个模块.一般而言的"编译运行App",指的是运行某一模块,而非运行 ...

  8. ceph 因权重问题导致pgs active+clean+remapped 状态

    1.现象: 2.原因:是因为前期权重调整不合理导致,调整回来就正常了 3.操作步骤: ceph osd crush reweight osd.2 0.98317    # osd 位置. 权重值 权重 ...

  9. Winform多线程访问UI控件问题

    Winform多线程无法访问UI控件,考虑使用委托方法解决.

  10. String 练习题

    题目一:获取指定字符串中,大写字母.小写字母.数字的个数. 题目二:将字符串中,第一个字母转换成大写,其他字母转换成小写,并打印改变后的字符串. 题目三:查询大字符串中,出现指定小字符串的次数.如&q ...