可扩展的应用程序可以使用横向或纵向扩展来动态调整云资源。为了帮助选择最佳策略,本文主要比较了kubernetes中的水平和垂直扩展。通过对Web应用进行全面的负载测量实验,结果表明水平扩展更高效,对负载变化的响应更快,对应用响应时间的影响更小。简介云服务的负载可能会随时间发生变化。为了实现可扩展性,需要采用基于特定指标(如CPU)的自动扩展策略来扩展应用程序的处理能力。为此,我们需要平衡应用的QoS和云基础设施的开销,即量入为出。目前有两种伸缩方式:水平伸缩,即根据负载情况增减服务数量;垂直,即服务的资源(CPU或内存)会随着负载的增加或减少。但即使使用这两种方法,也没有明确定义的标准来决定使用哪种方法。此外,缺乏与垂直自动缩放相关的分析,以及它与水平自动缩放在性能和成本效益方面的比较。因此,为了评估这两种方法的性能,我们在压力测试工具的帮助下使用kubernetes做了一个测量实验,该工具可以以受控的方式向“忙等待”应用程序发送请求,并对这些机制进行了评估根据负载变化后自动缩放决策的时间、每个决策请求的CPU容量以及对应用程序响应时间的影响。Kubernetes的自动伸缩策略k8s是一个基于Borg的开源项目,专注于容器编排,让容器应用程序在集群中运行,同时简化不同环境(生产、开发等)的配置。简而言之,k8s提供了一套物理机和虚拟机(节点),其中master负责控制和分配任务给worker节点。在k8s中,pod是节点上最小的可分配单元。一个Pod可以打包一个或多个容器并定义执行规则。需要注意的是,需要保证节点有足够的资源来运行对应的pod。为了在k8s中创建对象,需要创建包含所需规范的配置文件。K8s对象可以用于不同的目的,比如监控、网络配置、伸缩等,因此需要根据不同的目的选择不同的类型。这里使用的类型有:horizo??ntalpodautoscalerverticalpodautoscalerHorizo??ntalPodAutoscaler,horizo??ntalautoscaler的目的是减少或增加集群中的Pod数量,以高效利用资源,满足应用的需求。这种扩展方法围绕某些指标,例如CPU、内存、自定义指标或外部指标(基于Kubernetes外部的应用程序负载)。[2][3]为了使用水平缩放,您需要创建一个Horizo??ntalPodAutoscaler配置文件并定义CPU百分比使用限制。如果Pod利用率达到此限制,将创建更多副本。HPA每15秒(可变)检查是否需要创建新的Pod。HPA背后的算法是基于HPA观察到的所有Pod的平均当前利用率(U?)、期望利用率(U)和当前副本数(U?),因此可以按照以下格式计算:Nd=Na?(Ua/Ud)Nd=Na?(Ua/Ud)为了更好地理解上述格式,我们假设以下场景:一个集群中有5个副本(N?=5),平均利用率限制为100毫核或0.1个CPU核(U=100)。在负载峰值之后,所有pod的平均利用率上升到200m(U=200)。套用公式得到N=5*(200/100)=10,其中N=10是保证平均利用率为100m并考虑阈值的理想Pod数量。通过上面的例子可以看出,HPA会将副本数翻倍,而不是一次只创建一个副本,这使得HPA非常准确。当负载减少时,HPA有一个默认延迟(5分钟)以缩减。仅当利用率低于定义的利用率限制时才开始计时。VerticalPodAutoscaler垂直缩放的目的是增加或减少现有Pod分配的资源(CPU或内存)。在Kubernetes中,它修改Pod请求的资源容量。[4]为了使用这个方法,你需要创建一个VerticalPodAutoscaler类型的对象,并指定需要自动缩放的deployment。这种方法包含3个主要组件:Updater:充当哨兵,检查Pod是否有足够的资源,否则它将使用预期的资源来重启这些Pod。Admissioncontroller:配合updater定义合适的pod请求资源容量。Recommender:一种监视资源,它根据过去或当前的利用率提供扩大或缩小内存或CPU的建议。目前VPA提供了3种Recommender:Target:推荐理想的内存和CPU容量Upperbound:推荐请求资源的上限,如果请求大于这个限制,考虑置信度因素,Pod的大小会降低Lowerbound:推荐请求资源的下限。如果请求低于这个限制,考虑到置信度因素,Pod的大小将被扩展。置信因子是一种使VPA在其自动缩放决策中更加保守的方法。该方法使用以下变量:当前Pod请求CPU(R?)、下限(B?)及其置信度(a?)以及上限(B?)及其置信度(a?)。当R?>(B?*a?)时,VPA会减小资源大小,其中置信因子a?会随着Pod启动时间的增加而缓慢收敛到1。上限的置信因子计算为a?=(1+1/Δ?),其中Δ?是自创建Pod以来的天数。另一方面,当R?<(B?*a?)时,VPA会增加资源规模,其中置信因子a?会随着Pod启动时间的增加而增加,慢慢收敛到1。下限置信因子计算公式是a?=(1+0.001/Δ?)^-2。这样,有了置信度,VPA就可以快速做出决定。为了更好的理解,假设一个pod当前请求CPU为R?=100,当前下限为B?=150,启动时间为5分钟。将其转换为天数,得到Δ?=5/60/24=0.003472。下限置信度为a?=(1+0.001/0.00347)^-2=0.6,因此,可以看出100<150*0.6?100<90,结论不成立,容量Pod此时不会增加。为了重新创建pod,置信度至少应为a?=0.67,换言之,重建大约需要7分钟。验证环境为了生成和分析实验结果,有必要创建一个测试环境并定义一种生成资源利用率以触发自动缩放策略的方法。所有实验都是自动化的,实验数据被保存和组织。环境的架构和组件如下图所示:Eventos:EventAplica??o:ApplicationLegenda:Subtitle绿色:分发负载蓝色:收集集群信息红色:日志存储容器编排环境使用Minikube,用于生成负载的工具是嘿基准工具。它是一个用Go编写的压力测试工具,能够并发大量请求,此外,它还包含所有需要的参数:定义请求执行的长度定义并行worker的数量定义worker发送请求的速率为了在MinikubeLoad中生成,我们开发了一个node.jsweb应用程序,它会暴露一个REST,它会调用一个busy-wait函数,使服务的CPU-core使用率在一个时间内达到100%一定的毫秒周期,如下图所示,函数接收一个服务时间,并保持CPU忙碌,直到时间超时。评估场景考虑垂直伸缩至少需要一个被监控的Pod,所以为了保持配置相似,需要为每个伸缩策略配置2个初始Pod。另外,每个Pod初始请求的CPU是0.15个CPU-cores,限制是1.5个CPU-cores。在所有评估的场景中,服务时间(端点处理请求所花费的时间)是常量S=0.175秒。负载强度由发送请求的速率(λ)和并发客户端数(每秒一个请求)决定。实验的每个场景分为9个阶段,每个阶段包含不同的负载,每个阶段的执行时间为2分钟,每个场景的总执行时间为18分钟。为了让每个阶段都能达到理想的CPU利用率,根据队列理论的运行规则来定义请求率。根据利用率规律,定义流量强度为ρ=λ?S。例如,达到2核利用率(ρ=2)的服务时间为S=0.1,每秒请求速率为λ=ρ/S=2/0.1=20。但是如果请求率超过40,那么等式就不再平衡了,因为此时的负载确实需要4核。[5]实验的阶段流程如上图所示,请求率λ=2(需要ρ=0.35CPU-cores);λ=4(需要ρ=0.7个CPU内核);λ=6(需要ρ=1.05个CPU核数);和λ=8(需要ρ=1.4个CPU内核),因此,这些场景假设以下组合:λ=[第一个场景中的2,2,4,6,8,6,4,2,2],以非激进的方式逐渐增加或减少负载。在第二种情况下,λ=[2,2,8,8,8,2,2,2,2],负载突然增加,并保持3个阶段,然后在剩余阶段降低到最低值第三种情况,λ=[2,2,8,8,2,2,2,2,2],与第二种情况类似,但高负载持续时间更短在第四种情况下,λ=[2,2,8,2,8,2,8,2,2],使用多个峰值负载一旦定义了这些场景,就可以使用脚本实现它们的自动化。在实验执行过程中,KubernetesAPI将提供评估所需的关键数据:1)CPU使用率;2)autoscaler推荐值;3)PodRequest的CPU编号。此数据每10秒检索一次并保存到日志文件中。因此,使用此信息,可以确定每个Pod请求的CPU如何随时间变化。同时,每次执行脚本产生负载(使用嘿工具)时,应用的指标也会保存到日志文件中,为测试提供应用行为数据。结论每种自动缩放策略下将执行四个实验场景。每种方法的初始Pod数量为2,每个Pod的CPU-core为0.15,随着时间的推移会通过扩展容器进行修改。图1和图2展示了实验过程中每个Pod的requestCPU。虚线表示在负载的每个阶段达到100%使用率所需的CPU容量。图1:垂直扩展中每个Pod请求的CPU。可以看出,在VPA中,重新分配资源是有延迟的,大部分时间停留在CPU容量低于需要的时候(虚线下方的彩色条)。场景一的负载逐渐增加,自动伸缩决策的延迟比较大,而场景二、三的负载变化比较突然,延迟比较低。场景4的负载峰值时间比较短,只有在第8阶段才会出现资源申请。另外可以看出,在扩容的时候,VPA请求的CPU比需要的CPU要大,而在缩容的时候,VPA也比较保守。此外,即使在最近5个低强度负载期间,当请求的资源大于所需的资源时,VPA也没有缩减。这种延迟背后的原因是由于机制的置信度因素,需要更多时间来提高推荐的可信度。此外,在某些时候有3个pod的原因是,在扩展pod时,VPA会创建一个具有所需资源容量的新pod,并在新pod准备就绪时终止旧pod。因此,置信因子可以减少多次重建Pod的开销。图2:水平扩展中每个Pod请求的CPU在大多数情况下,HPA能够有效地响应工作负载变化(尽管请求的CPU略高于需要)。当负载增加时,平均扩展决策时间为40秒。只有在所有场景的第3阶段以及场景1的第4和第5阶段,CPU才会保持低于所需值约1分钟。HPA能够在延迟5分钟后缩小,而VPA则不能。在场景4中,HPA过度请求CPU资源,这对于处理短期峰值是有利的,但从长远来看,可能会对基础设施成本产生一定的影响。图3:垂直和水平缩放的应用程序响应时间图3比较了在每个场景的加载阶段向Web应用程序发出请求的响应时间。每个框的中间线代表中值,而点和三角形是每个阶段响应时间的平均值。在所有情况下,水平自动缩放的响应时间都非常接近服务时间(0.175秒),在负载增加的几个阶段,只有平均值和第三四分位数稍大。另一方面,由于在各个阶段调整pod的延迟,垂直自动缩放显示的响应时间远大于服务时间(均值和四分位数)。可以说,在评估这两种使用默认配置的自动伸缩策略时,HPA更有效,它可以更快地响应负载变化,并且有足够数量的Pod来处理请求,而VPA则受到调整的负面影响Pod延迟。总结这项工作通过测量实验分析了Kubernetes中水平和垂直自动缩放的性能。为此,需要有一种方式来产生负载并使用压力测试工具来控制负载,并创建多个场景来分析自动缩放的行为,重点关注响应时间、Pod的CPU请求指标和自动缩放时间时间。从这个实验可以看出,水平自动伸缩相对不保守,但资源调整相对更高效。重要的是要注意,这种精度是由水平pod自动缩放容器算法的客观性决定的,该算法将请求的资源保持在定义的平均资源使用限制范围内。相比之下,垂直自动缩放在其资源应用决策中更为保守,因为它依赖于随时间增加置信度因子的对数。可以得出结论,在更长时间的实验中,可以生成更多的pod执行历史数据,垂直弹性伸缩将更有效地执行弹性伸缩决策。在本实验的参数和场景下,横向自动伸缩表现出更高的效率,其决策的准确性提供了资源灵活性和更快的Web应用程序响应时间。需要注意的是,在本期结束时,垂直自动缩放仍处于测试阶段,仍会收到每日更新,因此未来可能会提高效率。另外,本次实验使用的是Kubernetes默认配置,修改参数可能会产生不同的结果。
