Kubernetes 弹性伸缩全场景解析 (一)- 概念延伸与组件布局

传统弹性伸缩的困境

弹性伸缩是Kubernetes中被你们关注的一大亮点,在讨论相关的组件和实现方案以前。首先想先给你们扩充下弹性伸缩的边界与定义,传统意义上来说,弹性伸缩主要解决的问题是容量规划与实际负载的矛盾。网络

如上图所示,蓝色的水位线表示集群的容量随着负载的提升不断的增加,红色的曲线表示集群的实际的负载真实的变化。而弹性伸缩要解决的就是当实际负载出现激增,而容量规划没有来得及反应的场景。微服务

常规的弹性伸缩是基于阈值的,经过设置一个资源缓冲水位来保障资源的充盈,一般15%-30%左右的资源预留是比较常见的选择。换言之就是经过一个具有缓冲能力的资源池用资源的冗余换取集群的可用。布局

这种方式表面上看是没有什么问题的,确实在不少的解决方案或者开源组件中也是按照这种方式进行实现的,可是当咱们深刻的思考这种实现方案的时候会发现,这种方式存在以下三个经典问题。大数据

1. 百分比碎片难题网站

在一个Kubernetes集群中,一般不仅包含一种规格的机器,针对不一样的场景、不一样的需求,机器的配置、容量可能会有很是大的差别,那么集群伸缩时的百分比就具有很是大的迷惑性。假设咱们的集群中存在4C8G的机器与16C32G的机器两种不一样规格,对于10%的资源预留,这两种规格是所表明的意义是彻底不一样的。spa

特别是在缩容的场景下,一般为了保证缩容后的集群不处在震荡状态,咱们会一个节点一个节点或者二分法来缩容节点,那么如何根据百分比来判断当前节点是处在缩容状态就尤其重要,此时若是大规格机器有较低的利用率被判断缩容,那么颇有可能会形成节点缩容后,容器从新调度后的争抢饥饿。若是添加判断条件,优先缩容小配置的节点,则有可能形成缩容后资源的大量冗余,最终集群中可能会只剩下全部的巨石节点。设计

2. 容量的规划炸弹code

还记得在没有使用容器前,是如何作容量规划的吗?通常会按照应用来进行机器的分配,例如,应用A须要2台4C8G的机器,应用B须要4台8C16G的机器,应用A的机器与应用B的机器是独立的,相互不干扰。到了容器的场景中,大部分的开发者无需关心底层的资源了,那么这个时候容量规划哪里去了呢?对象

在Kubernetes中是经过RequestLimit的方式进行设置,Request表示资源的申请值,Limit表示资源的限制值。既然RequestLimit才是容量规划的对等概念,那么这就表明着资源的实际计算规则要根据RequestLimit才更加准确。而对于每一个节点预留资源阈值而言,颇有可能会形成小节点的预留没法知足调度,大节点的预留又调度不完的场景。事件

3. 资源利用率困境

集群的资源利用率是否能够真的表明当前的集群状态呢?当一个Pod的资源利用率很低的时候,不表明就能够侵占他所申请的资源。在大部分的生产集群中,资源利用率都不会保持在一个很是高的水位,但从调度来说,资源的调度水位应该保持在一个比较高的水位。这样才能既保证集群的稳定可用,又不过于浪费资源。

若是没有设置RequestLimit,而集群的总体资源利用率很高这意味着什么?这表示全部的Pod都在被以真实负载为单元进行调度,相互之间存在很是严重的争抢,并且简单的加入节点也丝毫没法解决问题,由于对于一个已调度的Pod而言,除了手动调度与驱逐没有任何方式能够将这个Pod从高负载的节点中移走。那若是咱们设置了RequestLimit而节点的资源利用率又很是高的时候说明了什么呢?很惋惜这在大部分的场景下都是不可能的,由于不一样的应用不一样的负载在不一样的时刻资源的利用率也会有所差别,大几率的状况是集群尚未触发设置的阈值就已经没法调度Pod了。

弹性伸缩概念的延伸

既然基于资源利用率的弹性伸缩有上述已知的三个问题,有什么办法能够来解决呢?随着应用类型的多样性发展,不一样类型的应用的资源要求也存在愈来愈大的差别。弹性伸缩的概念和意义也在变化,传统理解上弹性伸缩是为了解决容量规划和在线负载的矛盾,而如今是资源成本与可用性之间的博弈。若是将常见的应用进行规约分类,能够分为以下四种不一样类型:

  • 在线任务类型

比较常见的是网站、API服务、微服务等常见的互联网业务型应用,这种应用的特色是对常规资源消耗较高,好比CPU、内存、网络IO、磁盘IO等,对于业务中断容忍性差。

  • 离线任务类型

例如大数据离线计算、边缘计算等,这种应用的特色是对可靠性的要求较低,也没有明确的时效性要求,更多的关注点是成本如何下降。

  • 定时任务类型

定时运行一些批量计算任务是这种应用的比较常见形态,成本节约与调度能力是重点关注的部分。

  • 特殊任务类型

例如闲时计算的场景、IOT类业务、网格计算、超算等,这类场景对于资源利用率都有比较高的要求。

单纯的基于资源利用率的弹性伸缩大部分是用来解决第一种类型的应用而产生的,对于其余三种类型的应用并非很合适,那么Kubernetes是如何解决这个问题的呢?

kubernetes的弹性伸缩布局

Kubernetes将弹性伸缩的本质进行了抽象,若是抛开实现的方式,对于不一样应用的弹性伸缩而言,该如何统一模型呢?Kubernetes的设计思路是将弹性伸缩划分为保障应用负载处在容量规划以内与保障资源池大小知足总体容量规划两个层面。简单理解,当须要弹性伸缩时,优先变化的应该是负载的容量规划,当集群的资源池没法知足负载的容量规划时,再调整资源池的水位保证可用性。而二者相结合的方式是没法调度的Pod来实现的,这样开发者就能够在集群资源水位较低的时候使用HPA、VPA等处理容量规划的组件实现实时极致的弹性,资源不足的时候经过Cluster-Autoscaler进行集群资源水位的调整,从新调度,实现伸缩的补偿。二者相互解耦又相互结合,实现极致的弹性。

在Kubernetes的生态中,在多个维度、多个层次提供了不一样的组件来知足不一样的伸缩场景。若是咱们从伸缩对象与伸缩方向两个方面来解读Kubernetes的弹性伸缩的话,能够获得以下的弹性伸缩矩阵。

  • cluster-autoscaler:kubernetes社区中负责节点水平伸缩的组件,目前处在GA阶段(General Availability,即正式发布的版本)。
  • HPA:kubernetes社区中负责Pod水平伸缩的组件,是全部伸缩组件中历史最悠久的,目前支持autoscaling/v1autoscaling/v2beta1autoscaling/v2beta2,其中autoscaling/v1只支持CPU一种伸缩指标,在autoscaling/v2beta1中增长支持custom metrics,在autoscaling/v2beta2中增长支持external metrics。
  • cluster-proportional-autoscaler:根据集群的节点数目,水平调整Pod数目的组件,目前处在GA阶段。
  • vetical-pod-autoscaler:根据Pod的资源利用率、历史数据、异常事件,来动态调整负载的Request值的组件,主要关注在有状态服务、单体应用的资源伸缩场景,目前处在beta阶段。
  • addon-resizer:根据集群中节点的数目,纵向调整负载的Request的组件,目前处在beta阶段。

在这五个组件中,cluster-autoscaler、HPA、cluster-proportional-autoscaler是目前比较稳定的组件,建议有相关需求的开发者进行选用。

对于百分之八十以上的场景,咱们建议客户经过HPA结合cluster-autoscaler的方式进行集群的弹性伸缩管理,HPA负责负载的容量规划管理而cluster-autoscaler负责资源池的扩容与缩容。

最后

在本文中,和你们主要讨论的是在云原生时代下弹性伸缩概念的延伸,以及Kubernetes社区是如何经过解耦的方式经过多个转职的组件实现了两个维度的弹性伸缩,在本系列后面的文章中会为一一解析每一个弹性伸缩组件的相关原理与用法。



本文做者:莫源

阅读原文

本文为云栖社区原创内容,未经容许不得转载。

相关文章
相关标签/搜索