HPA实践干货
HPA(HorizontalPodAutoscaler)
为什么要自动扩缩容?
HPA可以为您的服务带来两个直接的帮助:
1,在需要计算和内存资源时提供资源,在不需要时释放它们
2,按需增加/降低性能以实现SLA
在 k8s 中扩缩容分为两种:
1、Node 层面:
kubernetes cluster-autoscaler
在使用 kubernetes 集群经常问到的一个问题是,我应该保持多大的节点规模来满足应用需求呢? cluster-autoscaler 的出现解决了这个问题, 可以通过 cluster-autoscaler 实现节点级别的动态添 加与删除,动态调整容器资源池,应对峰值流量
2、Pod 层面:
我们一般会使用 Deployment 中的 replicas 参数,设置多个副本来保证服务的高可用,但是这是 一个固定的值,比如我们设置 10 个副本,就会启 10 个 pod 同时 running 来提供服务。 如果这个服务平时流量很少的时候,也是 10 个 pod 同时在 running,而流量突然暴增时,又可能 出现 10 个 pod 不够用的情况。针对这种情况怎么办?就需要自动扩缩容:
Kubernetes 对 Pod 的扩缩容分为:
手动和自动两种
1、手动模式:通过 kubectl scale 命令,这样需要每次去手工操作一次,而且不确定什么时候业务 请求量就很大了,所以如果不能做到自动化的去扩缩容的话,这也是一个很麻烦的事情
2、自动模式:如果 Kubernetes 系统能够根据 Pod 当前的负载的变化情况来自动的进行扩缩容就 好了,因为这个过程本来就是不固定的,频繁发生的,所以纯手工的方式不是很现实
自动扩缩容的方案有哪些?
1.1 Kubernetes HPA(Horizontal Pod Autoscaling) 通过此功能,只需简单的配置,便可以利用监控指标(cpu 使用率、磁盘、自定义的等)自动的扩容 或缩容服务中 Pod 数量,当业务需求增加时,系统将无缝地自动增加适量 pod 容器,提高系统稳定 性。
1.2 kubernetes KPA(Knative Pod Autoscaler)基于请求数对 Pod 自动扩缩容,KPA 的主要限制在于它不支持基于 CPU 的自动扩缩容。
1.3 kubernetes VPA(Vertical Pod Autoscaler)垂直 Pod 自动扩缩容,VPA 会基于 Pod 的资源使用情况自动为集群设置资源占用的限制,从而让 集群将 Pod 调度到有足够资源的最佳节点上。VPA 也会保持最初容器定义中资源 request 和 limit 的占比。
它会根据容器资源使用率自动设置 pod 的 CPU 和内存的 requests,从而允许在节点上进行适当的 调度,以便为每个 Pod 提供适当的可用的节点。它既可以缩小过度请求资源的容器,也可以根据其 使用情况随时提升资源不足的容量。
基于 HPA
要想实现自动扩缩容,需要先考虑如下几点:
1.通过哪些指标决定扩缩容?
HPA v1 版本可以根据 CPU 使用率来进行自动扩缩容:但是并非所有的系统都可以仅依靠 CPU 或者 Memory 指标来扩容,对于大多数 Web 应用的后端 来说,基于每秒的请求数量进行弹性伸缩来处理突发流量会更加的靠谱,所以对于一个自动扩缩容系 统来说,我们不能局限于 CPU、Memory 基础监控数据,每秒请求数 RPS 等自定义指标也是十分 重要。
HPA v2 版本可以根据自定义的指标进行自动扩缩容
注意:hpa v1 只能基于 cpu 做扩容所用
hpa v2 可以基于内存和自定义的指标做扩容和缩容
2.如何采集资源指标?
如果我们的系统默认依赖 Prometheus,自定义的 Metrics 指标则可以从各种数据源或者 exporter 中获取,基于拉模型的 Prometheus 会定期从数据源中拉取数据。 也可以基于 metrics- server 自动获取节点和 pod 的资源指标
3.如何实现自动扩缩容?
K8s 的 HPA controller 已经实现了一套简单的自动扩缩容逻辑,默认情况下,每 30s 检测一次指 标,只要检测到了配置 HPA 的目标值,则会计算出预期的工作负载的副本数,再进行扩缩容操作。 同时,为了避免过于频繁的扩缩容,默认在 5min 内没有重新扩缩容的情况下,才会触发扩缩容。
HPA 本身的算法相对比较保守,可能并不适用于很多场景。例如,一个快速的流量突发场景,如果 正处在 5min 内的 HPA 稳定期,这个时候根据 HPA 的策略,会导致无法扩容。
利用 HPA 基于 CPU 指标实现 pod 自动扩缩容
HPA 全称是 Horizontal Pod Autoscaler,翻译成中文是 POD 水平自动伸缩, HPA 可以基于 CPU 利用率对 deployment 中的 pod 数量进行自动扩缩容(除了 CPU 也可以基于自定义的指标 进行自动扩缩容)。pod 自动缩放不适用于无法缩放的对象,比如 DaemonSets。
HPA 由 Kubernetes API 资源和控制器实现。控制器会周期性的获取平均 CPU 利用率,并与目标 值相比较后调整 deployment 中的副本数量。
1、HPA 工作原理
HPA 是根据指标来进行自动伸缩的,目前 HPA 有两个版本–v1 和 v2beta
HPA 的 API 有三个版本,通过 kubectl api-versions | grep autoscal 可看到 autoscaling/v1
autoscaling/v2beta1
autoscaling/v2beta2
autoscaling/v1 只支持基于 CPU 指标的缩放; 默认情况下为v1
autoscaling/v2beta1 支持 Resource Metrics(资源指标,如 pod 的 CPU,内存)和 Custom Metrics(自定义指标)的缩放;
autoscaling/v2beta2 支持 Resource Metrics(资源指标,如 pod 的 CPU,内存)和 Custom Metrics(自定义指标)和 ExternalMetrics(额外指标)的缩放,但是目前也仅仅是处于 beta 阶段 指标从哪里来?
K8S 从 1.8 版本开始,CPU、内存等资源的 metrics 信息可以通过 Metrics API 来获取,用户可以 直接获取这些 metrics 信息(例如通过执行 kubect top 命令),HPA 使用这些 metics 信息来实 现动态伸缩。
Metrics server:
1、Metrics server 是 K8S 集群资源使用情况的聚合器
2、从 1.8 版本开始,Metrics server 可以通过 yaml 文件的方式进行部署 3、Metrics server 收集所有 node 节点的 metrics 信息
HPA 如何运作?
HPA 的实现是一个控制循环,由 controller manager 的--horizontal-pod-autoscaler-sync- period 参数指定周期(默认值为 15 秒)。每个周期内,controller manager 根据每个 HorizontalPodAutoscaler 定义中指定的指标查询资源利用率。controller manager 可以从 resource metrics API(pod 资源指标)和 custom metrics API(自定义指标)获取指标。
然后,通过现有 pods 的 CPU 使用率的平均值(计算方式是最近的 pod 使用量(最近一分钟的平均 值,从 metrics-server 中获得)除以设定的每个 Pod 的 CPU 使用率限额)跟目标使用率进行比 较,并且在扩容时,还要遵循预先设定的副本数限制:MinReplicas <= Replicas <= MaxReplicas。
计算扩容后 Pod 的个数:sum(最近一分钟内某个 Pod 的 CPU 使用率的平均值)/CPU 使用上限的 整数+1
扩容流程:
1、创建 HPA 资源,设定目标 CPU 使用率限额,以及最大、最小实例数
2、收集一组中(PodSelector)每个 Pod 最近一分钟内的 CPU 使用率,并计算平均值
3、读取 HPA 中设定的 CPU 使用限额
4、计算:平均值之和/限额,求出目标调整的实例个数
5、目标调整的实例数不能超过 1 中设定的最大、最小实例数,如果没有超过,则扩容;超过,则扩 容至最大的实例个数
6、回到 2,不断循环
基于CPU创建HPA
安装数据采集组件 metrics-server
metrics-server 是一个集群范围内的资源数据集和工具,metrics-server 也只是显示数 据,并不提供数据存储服务,主要关注的是资源度量 API 的实现,比如 CPU、文件描述符、内存、 请求延时等指标,metric-server 收集数据给 k8s 集群内使用,如 kubectl,hpa,scheduler 等
华为云自带metrics-server插件可以直接使用
为服务创建HPA
#给admin-center-server 这个 deployment 创建 HPA,直接执行命令添加的HPA默认使用autoscaling/v1 版本
kubectl autoscale deployment admin-center-server --cpu-percent=50 --min=1 --max=10
#命令解释说明
kubectl autoscale deployment admin-center-server (admin-center-server 表示 deployment 的名字) -- cpu-percent=50(表示 cpu 使用率不超过 50%) --min=1(最少一个 pod) --max=10(最多 10 个 pod)
#验证 HPA 是否创建成功
kubectl get hpa -n dev
#将指标调小至10%(压测),查看HPA已出发指标,此时 实例个数 = 平均值之和/限额 = 6 +1 = 7个实例
压力降下来后,会有默认5分钟的scaledown的时间,可以通过controller-manager的如下参数设置:--horizontal-pod-autoscaler-downscale-stabilization
基于内存创建HPA
基于内存或自定义参数进行扩容的需选择对应apiVersion版本
vim hap-v1.yaml
apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
metadata:
name: admin-center-server
spec:
maxReplicas: 3
minReplicas: 1
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: admin-center-server
metrics:
- type: Resource
resource:
name: memory
targetAverageUtilization: 60
- type: Resource
resource:
name: cpu
targetAverageUtilization: 60
HPA存在的问题
问题一、HPA存在扩容死区
现象:当Request=Limit时,期望利用率超过90%时,无法正常扩容。
原因剖析:HPA中存在容忍度(默认为10%),指标变化幅度小于容忍度时,HPA会忽略本次扩/缩动作。若当期望利用率为90%时,则实际利用率在81%-99%之间,都会被HPA忽略。
避坑指南:当Request=Limit时,避免设置过高的期望利用率,一来避免扩容死区;二来被动扩容有一定的迟滞时间,留下更多的缓冲余量以应对突增流量。
问题二、误解利用率计算方法,HPA扩容与预期使用量不符
现象:当Limit > Request时,配置50%的利用率,使用量未达到Limit的50%便扩容。
原因剖析:HPA计算利用率是基于Request计算,当Limit > Request时,实际利用率是可以超过100%。
避坑指南:对于较为重要的应用,应当设置Request=Limit保证资源的独占。对于可以容忍资源共享的应用,对应的期望利用率也不应设置的过高,在集群资源紧张时,超量使用资源的Pod很有可能会被杀死,从而造成服务中断。
问题三、弹性行为总是滞后的,扩缩行为与心理预期不符
现象:指标突增时,HPA不会立刻扩容,且扩容可能是分多次进行,最终稳定时的实例数也与预期不同。
原因剖析:HPA的设计架构决定了,HPA扩/缩容总是滞后的,且扩/缩容收到弹性行为(behavior)与容忍度共同作用。其中弹性行为限制了扩/缩容速率,不会一口气扩/缩到期望实例数。而容忍度会忽略指标的小幅度变化,从而导致在多次扩容的场景下,最终计算的实例数可能与一开始计算出的实例数不同。
HPA从Metrics API获取对应的指标数据,每15秒获取一次数据导致弹性行为滞后