Kubernetes 弹性伸缩全场景解读(二)- HPA 的原理与演进
前言
在上一篇文章 Kubernetes 弹性伸缩全场景解析 (一):概念延伸与组件布局中,我们介绍了在 Kubernetes 在处理弹性伸缩时的设计理念以及相关组件的布局,在今天这篇文章中,会为大家介绍在 Kubernetes 中弹性伸缩最常用的组件 HPA(Horizontal Pod Autoscaler)。HPA 是通过计算 Pod 的实际工作负载进行重新容量规划的组件,在资源池符合满足条件的前提下,HPA 可以很好的实现弹性伸缩的模型。HPA 到目前为止,已经演进了三个大版本,本文将会为大家详细解析 HPA 底层的原理以及在 Kubernetes 中弹性伸缩概念的演变历程。
HPA 基本原理
HPA 是根据实际工作负载水平伸缩容器数目的组件,从中可以提炼出两个非常重要的关键字:负载和数目。我们可以用一个非常简单的数学公式进行归纳:

下面举一个实际例子进行上述公式的阐述。
假设存在一个叫 A 的 Deployment,包含3个 Pod,每个副本的 Request 值是 1 核,当前 3 个 Pod 的 CPU 利用率分别是 60%、70% 与 80%,此时我们设置 HPA 阈值为 50%,最小副本为 3,最大副本为 10。接下来我们将上述的数据带入公式中:
- 总的
Pod的利用率是 60%+70%+80% = 210%; - 当前的
Target是 3; - 算式的结果是 70%,大于50%阈值,因此当前的
Target数目过小,需要进行扩容; - 重新设置
Target值为 5,此时算式的结果为 42% 低于 50%,判断还需要扩容两个容器; - 此时 HPA 设置
Replicas为 5,进行Pod的水平扩容。
经过上面的推演,可以协助开发者快速理解 HPA 最核心的原理,不过上面的推演结果和实际情况下是有所出入的,如果开发者进行试验的话,会发现 Replicas 最终的结果是 6 而不是 5。这是由于 HPA 中一些细节的处理导致的,主要包含如下三个主要的方面:
- 噪声处理
通过上面的公式可以发现,Target 的数目很大程度上会影响最终的结果,而在 Kubernetes 中,无论是变更或者升级,都更倾向于使用 Recreate 而不是 Restart 的方式进行处理。这就导致了在 Deployment 的生命周期中,可能会出现某一个时间,Target 会由于计算了 Starting 或者 Stopping 的 Pod 而变得很大。这就会给 HPA 的计算带来非常大的噪声,在 HPA Controller 的计算中,如果发现当前的对象存在 Starting 或者 Stopping 的 Pod 会直接跳过当前的计算周期,等待状态都变为 Running 再进行计算。
- 冷却周期
在弹性伸缩中,冷却周期是不能逃避的一个话题,很多时候我们期望快速弹出与快速回收,而另一方面,我们又不希望集群震荡,所以一个弹性伸缩活动冷却周期的具体数值是多少,一直被开发者所挑战。在 HPA 中,默认的扩容冷却周期是 3 分钟,缩容冷却周期是 5 分钟。
- 边界值计算
我们回到刚才的计算公式,第一次我们算出需要弹出的容器数目是 5,此时扩容后整体的负载是 42%,但是我们似乎忽略了一个问题:一个全新的 Pod 启动会不会自己就占用了部分资源?此外,8% 的缓冲区是否就能够缓解整体的负载情况?要知道当一次弹性扩容完成后,下一次扩容要最少等待 3 分钟才可以继续扩容。为了解决这些问题,HPA 引入了边界值 △,目前在计算边界条件时,会自动加入 10% 的缓冲,这也是为什么在刚才的例子中最终的计算结果为 6 的原因。
HPA 的演进历程
在了解了 HPA 的基本原理后,我们来聊一下 HPA 的演进历程,目前 HPA 已经支持了 autoscaling/v1、autoscaling/v1beta1 和 autoscaling/v1beta2 三个大版本。大部分的开发者目前比较熟悉的是autoscaling/v1 的版本,这个版本的特点是只支持 CPU 一个指标的弹性伸缩,大致的 yaml 内容如下:
apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
name: php-apache
namespace: default
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: php-apache
minReplicas:
maxReplicas:
targetCPUUtilizationPercentage:
接下来我们再来看一下 v2beta1 与 v2beta2 的 yaml,会发现里面支持的 metrics 类型增加了很多,结构也复杂了很多。
apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
metadata:
name: php-apache
namespace: default
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: php-apache
minReplicas:
maxReplicas:
metrics:
- type: Resource
resource:
name: cpu
target:
kind: AverageUtilization
averageUtilization:
- type: Pods
pods:
metric:
name: packets-per-second
targetAverageValue: 1k
- type: Object
object:
metric:
name: requests-per-second
describedObject:
apiVersion: extensions/v1beta1
kind: Ingress
name: main-route
target:
kind: Value
value: 10k
---
apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
name: php-apache
namespace: default
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: php-apache
minReplicas:
maxReplicas:
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization:
而这些变化的产生不得不提的是 Kubernetes 社区中对监控与监控指标的认识与转变。在 Kubernetes 中,有两个核心的监控组件 Heapster 与 Metrics Server。Heapster 是早期 Kubernetes 社区中唯一的监控组件,它所包含的功能很强大,通过采集 kubelet 提供的 metrics 接口,并支持监控数据的离线与归档。

大致的架构图如上:source 的部分是不同的数据来源,主要是 kubelet 的 common api 与后来提供的 summary api;processor 的作用是将采集的数据进行处理,分别在 namespace 级别、cluster 级别进行聚合,并创建新的聚合类型的监控数据;sink 的作用是数据离线与归档,常见的归档方式包括 influxdb、kafka 等等。Heapster 组件在相当长时间成为了 Kubernetes 社区中监控数据的唯一来源,也因此有非常多的和监控相关的组件通过 Heapster 的链路进行监控数据的消费。但是后来,Kubernetes 社区发现了 Heapster 存在非常严重的几个问题:
- 强大繁多的 Sink 由不同的 Maintainer 进行维护,50% 以上的 Heapster Issues 都是关于 Sink 无法使用的,而由于 Maintainer 的活跃度不同造成 Heapster 社区有大量的 issues 无法解决;
- 对于开发者而言,监控数据的类型已经不再是 CPU、Memory 这么简单的几个指标项了,越来越多的开发者需要应用内或者接入层的监控指标,例如 ingress 的 QPS、应用的在线活跃人数等等。而这些指标的获取是 Heapster 无法实现的;
- Prometheus 的成熟让 Heapster 的生存空间不断被挤压,自从 Prometheus 被 CNCF 收录为孵化项目,Heapster 的不可替代地位被正式移除。
社区经过反思后,决定将监控的指标边界进行划分,分为 Resource、Custom 和 External 三种不同的 Metrics,而 Heapster(Metrics Server) 的定位就只关心 Resource 这一种指标类型。为了解决代码维护性的问题,Metrics Server 对 Heapster 进行了裁剪,裁剪后的架构如下:

去掉了 Sink 的机制,并将调用方式改为标准的 API 注册的方式,这样的好处是既精简了核心代码的逻辑又提供了替代的可能,也就是说此时 Metrics Server 也是可以替代的,只要实现了相同的 API 接口,并注册到 API Server 上,就可以替代 Metrics Server。
接下来我们解析一下三种不同的 Metrics 与使用的场景:
| API | 注释 | |
| Resource | metrics.k8s.io | Pod的资源指标,计算的时要除以Pod数目再对比阈值进行判断 |
| Custom | custom.metrics.k8s.io | Object: CRD等对象的监控指标,直接计算指标比对阈值 Pods : 每个Pod的自定义指标,计算时要除以Pods的数目 |
| External | external.metrics.k8s.io | External:集群指标的监控指标,通常由云厂商实现 |
其中 autoscaling/v2beta1 支持 Resource 与 Custom 两种指标,而 autoscaling/v2beta2 中增加了 External 的指标的支持。
最后
HPA 目前已经进入了 GA 阶段,在大体的功能上面不会进行过多的变化,目前社区的主要发力点在如何配置化的调整细节参数、丰富监控 adapter 的实现等等。在本文中,我们在概念上给大家介绍了 HPA 的一些原理以及发展的趋势,在下一篇文章中,我们会为大家讲解如何开启 v2beta1 与 v2beta2 的。
Kubernetes 弹性伸缩全场景解读(二)- HPA 的原理与演进的更多相关文章
- Kubernetes 弹性伸缩全场景解读(五) - 定时伸缩组件发布与开源
作者| 阿里云容器技术专家刘中巍(莫源) 导读:Kubernetes弹性伸缩系列文章为读者一一解析了各个弹性伸缩组件的相关原理和用法.本篇文章中,阿里云容器技术专家莫源将为你带来定时伸缩组件 kub ...
- Kubernetes弹性伸缩全场景解读(五) - 定时伸缩组件发布与开源
前言 容器技术的发展让软件交付和运维变得更加标准化.轻量化.自动化.这使得动态调整负载的容量变成一件非常简单的事情.在kubernetes中,通常只需要修改对应的replicas数目即可完成.当负载的 ...
- Kubernetes 弹性伸缩全场景解析 (四)- 让核心组件充满弹性
前言 在本系列的前三篇中,我们介绍了弹性伸缩的整体布局以及HPA的一些原理,HPA的部分还遗留了一些内容需要进行详细解析.在准备这部分内容的期间,会穿插几篇弹性伸缩组件的最佳实践.今天我们要讲解的是 ...
- Kubernetes 弹性伸缩全场景解析(三) - HPA 实践手册
在上一篇文章中,给大家介绍和剖析了 HPA 的实现原理以及演进的思路与历程.本文我们将会为大家讲解如何使用 HPA 以及一些需要注意的细节. autoscaling/v1 实践 v1 的模板可能是大家 ...
- Kubernetes 弹性伸缩全场景解析 (一)- 概念延伸与组件布局
传统弹性伸缩的困境 弹性伸缩是Kubernetes中被大家关注的一大亮点,在讨论相关的组件和实现方案之前.首先想先给大家扩充下弹性伸缩的边界与定义,传统意义上来讲,弹性伸缩主要解决的问题是容量规划与实 ...
- Kubernetes 弹性伸缩全场景解析 (一):概念延伸与组件布局
传统弹性伸缩的困境 弹性伸缩是 Kubernetes 中被大家关注的一大亮点,在讨论相关的组件和实现方案之前.首先想先给大家扩充下弹性伸缩的边界与定义,传统意义上来讲,弹性伸缩主要解决的问题是容量规划 ...
- Kubernetes 弹性伸缩HPA功能增强Advanced Horizontal Pod Autoscaler -介绍部署篇
背景 WHAT(做什么) Advanced Horizontal Pod Autoscaler(简称:AHPA)是kubernetes中HPA的功能增强. 在兼容原生HPA功能基础上,增加预测.执行模 ...
- Docker(三):利用Kubernetes实现容器的弹性伸缩
一.前言 前两章有的介绍docker与Kubernetes.docker是项目运行的容器,Kubernetes则是随着微服务架构的演变docker容器增多而进行其编排的重要工具.Kubernetes不 ...
- Serverless 与容器决战在即?有了弹性伸缩就不一样了
作者 | 阿里云容器技术专家 莫源 本文整理自莫源于 8 月 31 日 K8s & cloudnative meetup 深圳场的演讲内容.****关注"阿里巴巴云原生" ...
随机推荐
- Jenkins 在 Tomcat 运行访问路径设置
问题 最近用 Tomcat 搭建了个 Jenkins ,但是访问的时候需要端口加 /jenkins/ 才能进行访问.我们是直接将 Jenkins.war 包放在 webapps下的. 我们想直接通过不 ...
- .NET MVC5简介(四)Filter和AuthorizeAttribute权限验证
在webform中,验证的流程大致如下图: 在AOP中: 在Filter中: AuthorizeAttribute权限验证 登录后有权限控制,有的页面是需要用户登录才能访问的,需要在访问页面增加一个验 ...
- asp.net 关于gridview使用的一些小技巧
gridview中嵌套控件示例 —— 添加了一个linkbutton 前台: <asp:GridView ID="gv2" runat="server" ...
- python基础(20):序列化、json模块、pickle模块
1. 序列化 什么叫序列化——将原本的字典.列表等内容转换成一个字符串的过程就叫做序列化. 1.1 为什么要有序列化 为什么要把其他数据类型转换成字符串?因为能够在网络上传输的只能是bytes,而能够 ...
- python基础(9):基本数据类型四(set集合)、基础数据类型补充、深浅拷贝
1. 基础数据类型补充 li = ["李嘉诚", "麻花藤", "⻩海峰", "刘嘉玲"] s = "_&qu ...
- Python-标准库(常用模块)
前言: 之所以为不同模块划分重要程度,是因为大家不不可能精力一直集中,也不可能一下掌握所有, 但这个并不表示重要度低的可以不用掌握 ! 你必须掌握的点是每个模块分别干什么事,今后在需要实现某些功能时能 ...
- tinyriscv---一个从零开始写的极简、易懂的开源RISC-V处理器核
本项目实现的是一个微riscv处理器核(tinyriscv),用verilog语言编写,只求以最简单.最通俗易懂的方式实现riscv指令的功能,因此没有特意去对代码做任何的优化,因此你会看到里面写的代 ...
- git fetch & pull详解
1.简单概括 先用一张图来理一下git fetch和git pull的概念: 可以简单的概括为: git fetch是将远程主机的最新内容拉到本地,用户在检查了以后决定是否合并到工作本机分支中. 而g ...
- SpringBoot(八) SpringBoot整合Kafka
window下安装kafka和zooker,超详细:https://blog.csdn.net/weixin_33446857/article/details/81982455 kafka:安装下载教 ...
- Meterpreter初探
Meterpreter Meterpreter号称"黑客瑞士军刀",Meterpreter是Metasploit框架中的一个杀手锏,通常作为漏洞溢出后的攻击载荷使用,攻击载荷在触发 ...