Cerebral vs Kubernetes Cluster Autoscaler: 抢占式自动缩放演示

cerebral_kubernetes.png

Cerebral是一个开源的工具,用于响应用户定义的策略生成的警报来增长或减少Kubernetes集群中节点池的大小。这些策略引用可插拔和可配置的度量标准后端,以收集度量标准以进行自动缩放决策。node

本文,在易于搭建的 Kops环境中将Cerebral与Kubernetes Cluster Autoscaler进行了公平地比较和对比。git

Kubernetes 伸缩基础

要了解生产中的自动缩放,咱们首先必须退后一步,从通常意义上理解Kubernetes的自动缩放。与Kubernetes相关的自动缩放器有几类:github

在本文中,咱们将重点介绍水平Pod自动缩放和群集自动缩放。它们一般相互串联使用,所以,咱们将研究HPA与集群自动缩放器之间的交互以及不一样集群自动缩放器实现之间的权衡。特别是,咱们将介绍Cerebral和Kubernetes Cluster Autoscaler(CA)项目之间的区别。json

Kubernetes Cluster Autoscaler 总览

Kubernetes Cluster Autoscaler采用一种简单的方法(至少在较高级别上)来决定什么时候将节点添加到集群中:当发现没法调度Pod并肯定添加新节点后将可以调度成功该Pod时,它将进行扩展。这种方法有不少好处,例如,它仅依赖于Kubernetes核心概念。它还保证仅在绝对须要时才添加节点,由于它知道因为资源不足而致使Pod处于pending状态。后端

这种方法的主要缺点是,它太慢了,没法知足实际的业务需求。在许多状况下,等到没法调度Pod的时间为时已晚。app

使用CA进行缩小也很简单:若是某个节点在必定时间内未获得充分利用,而且当前能够在该节点上运行的Pod能够从新安排到另外一个节点上,则它将删除该节点。负载均衡

对于CA如何工做的细节,FAQ是一个很好的资源。curl

Cerebral 总览

Cerebral的构建考虑了灵活性。它使operators能够轻松地对从各类来源收集的指标进行自动缩放配置,并能够经过使用自定义资源定义(CRD)在云环境之间轻松移植的方式进行配置。ide

Cerebral采用的抢占式自动缩放方法与标准的Kubernetes Cluster Autoscaler根本不一样。 Cerebral无需等待直到没法安排Pod,而是决定根据来自可配置指标后端的用户指定指标进行扩展。在撰写本文时,主要的Cerebral存储库中支持如下后端:Prometheus,InfluxDB和Kubernetes自己。工具

经过实现简单的接口并在新的MetricsBackend CRD中定义后端的配置,也能够轻松构建自定义后端。自定义后端的可能性是无限的。例如,可使用Cerebral基于特定于应用程序的队列的深度来自动缩放群集。

在本文中,咱们将坚持使用Kubernetes后端与Kubernetes CA进行公平比较。

有关Cerebral的工做方式的更多详细信息,以及其余指标后端和云提供商的入门信息,请参阅GitHub上的项目。

自动缩放实验

让咱们看一个简单的示例,将HPA与Kubernetes Cluster Autoscaler和Cerebral结合使用。这将使咱们可以在模拟的真实场景中对比Kubernetes CA和Cerebral。

若是您对实验自己不感兴趣,请随时跳至“关键”部分。

在AWS准备一个测试集群

虽然Cerebral已彻底集成到支持AWS的Containership Kubernetes Engine(CKE)中,但让咱们改用kops以便从基础上进行构建。

咱们建立了一个具备很是基本的kops集群配置的公共要点,任何人均可以复制它以进行后续操做。集群具备一个主节点和一个节点池(等于一个AWS Auto Scaling组),其最小大小为1个节点,最大大小为5个节点。只需在S3中建立一个新的存储桶以用做集群状态存储,而后按如下步骤建立集群便可。首先以kops建立集群配置:

kops --state=s3://bucket-name create -f https://gist.githubusercontent.com/mattkelly/692af294868ff50a6c5664ea63b7e9c4/raw/48b00e3dc3d7de18c040522a6392a92beb9dc7e1/kops\-autoscaling-demo-cluster-config.yaml

你应该能看到以下的输出:

image.png

如今apply更改以实际建立集群:

kops --state=s3://bucket-name update cluster autoscaling-experiment.k8s.local --yes

它可能会提示您首先指定一个公用SSH密钥。若是是这样,只需按照说明建立密钥,而后从新运行更新命令。

您应该看到一堆输出,而后最终是:

image-1.png

几分钟后,您应该可以与群集进行交互。尝试kubectl get nodes,直到它起做用为止(请注意,若是一切顺利,kops将适当地设置您的kubectl上下文)。

有关kops的更多信息,请参考存储库

部署 Kubernetes Metrics Server

水平Pod自动缩放器须要知道Pod正在消耗多少资源。
为此,咱们须要部署metrics-server。请注意,仅HPA才须要,而不是Cerebral或Kubernetes CA都须要。

启动并运行metrics-server的最简单方法是简单地克隆存储库并部署全部Kubernetes v1.8 +清单。不幸的是,咱们发现须要一些变通办法来使清单在此kops群集上正常工做。一旦再也不须要此解决方法,咱们将更新本文。

同时,您能够在个人fork上使用分支:

git clone git@github.com:mattkelly/metrics-server.git 
cd metrics-server 
git checkout bugfix/deploy-1.8+

应用如下相关清单:

kubectl apply -f deploy/1.8+/

检查metrics-server pod日志,以确保一切正常:

kubectl -n kube-system logs -lk8s-app=metrics-server

建立用于自动扩展的资源使用者部署

如今,咱们已经创建了一个群集,而且可使用运行情况良好的metrics server,让咱们继续建立一个部署,能够将其包装在HPA中以运行实验。若是咱们可以经过强制它消耗某些请求的结果而消耗指定数量的CPU或内存来使它按需扩展,那就太好了。幸运的是,生活在Kubernetes存储库深处的resource-consumer确实作到了这一点。

让咱们根据CPU利用率自动调整resource-consumer部署。咱们的工做节点池正在使用t2.small实例,这些实例具备1个CPU(1000 millicores)和2 GB的内存。因为工做池的最小节点数为1,而且还没有扩展,所以该池中只有一个节点。使用kubectl describe节点,咱们看到该节点已经在使用640 millicores的CPU:

image-2.png

让咱们在默认命名空间中运行resource-consumer,请求为100 millicores,并使用负载均衡器公开它,以便咱们向其发送请求:

kubectl run resource-consumer --image=gcr.io/kubernetes-e2e-test-images/resource-consumer:1.4 --expose --service-overrides='{ "spec": { "type": "LoadBalancer" } }' --port 8080 --requests='cpu=100m'

马上,咱们看到初始的单个副本正按预期从节点请求另外一个100m:

image-3.png

因为使用负载均衡器公开了resource-consumer的部署,所以咱们还应该可以使用kubectl get服务来查看它是否已正确分配了外部地址:

image-5.png

让咱们导出完整的地址以供之后发送请求:

export RESOURCE_CONSUMER_ADDRESS="http://$(kubectl get service resource-consumer -ojsonpath='{.status.loadBalancer.ingress[0].hostname}'):8080"

建立水平Pod自动缩放器(HPA)

如今,咱们将HPA添加到resource-consumer部署中。若是观察到的Pod CPU利用率超过Pod CPU请求的50%,则此HPA将添加一个新Pod(最多10个Pod)。若是部署中的Pod没有显示出很高的CPU利用率,它还将缩小到最少1个Pod。

kubectl autoscale deployment resource-consumer --cpu-percent=50 --min=1 --max=10

您应该可以使用kubectl get hpa看到新建立的HPA,由于它只是另外一个Kubernetes资源:

image-8.png

注意:HPA就像其余任何Kubernetes控制器同样都是循环检查。默认状况下,它们每15秒收集一次指标。所以,利用率百分比可能会短暂显示为<未知>,直到收集度量为止。

正如预期的那样,资源消耗者实际上并无消耗任何CPU,由于咱们还没有要求这样作。

如今咱们已经设置了HPA,让咱们经过消耗CPU并查看Kubernetes Cluster Autoscaler和Cerebral的反应来强制其扩展!

设置Kubernetes Cluster Autoscaler

咱们建立了一个公共gist,能够很容易地在此kops集群上启动和运行Kubernetes集群自动缩放器(CA)。它对AWS清单所示的CA示例进行了以下调整:

  • 添加已将主部署更新为参考的secret
  • 设置部署命令以正确地引用带有预期最小/最大界限的kops辅助节点池。
  • 添加容忍和节点选择器以使其仅在主节点上运行

只需下载文件,填写AWS_ACCESS_KEY_ID和AWS_SECRET_ACCESS_KEY的有效值,而后kubectl便可应用它。

您能够经过检查日志来检查集群自动伸缩器部署是否正常:

kubectl -n kube-system logs -lapp=cluster-autoscaler

此处应用的“cerebral-aws-engine”secret也能够与Cerebral自动缩放器一块儿使用。)

注意:这只是出于演示目的运行CA的一种简单方法。若是您对在生产环境中运行CA感兴趣,请阅读文档以肯定最适合您的环境(包括身份验证方法等)的文档。

使用Kubernetes集群自动缩放器进行集群自动缩放演示

仅当没法调度Pod时,Kubernetes Cluster Autoscaler才会缩放。这种缩放方法学是CA与Cerebral之间的主要区别之一。让咱们确切地了解这在实践中意味着什么。

为了模拟需求激增的开始,让咱们经过将请求发布到其ConsumeCPU端点来告诉resource-consumer消耗CPU:

curl --data "millicores=60&durationSec=600"  $RESOURCE_CONSUMER_ADDRESS/ConsumeCPU

若是愿意,您能够经过在第二个终端上运行watch来实时观看动做:

watch --differences kubectl get deployments,replicasets,pods,hpa

片刻以后,您应该看到此峰值致使HPA向部署中添加了另外一个Pod,以知足需求并保持部署中Pod的CPU利用率低于50%的目标:

image-9.png

再过一下子,您应该会看到状况稳定下来,而且HPA报告了新的CPU利用率:

image-10.png

而且kubectl describe nodes显示新副本向该节点添加了另外100m的CPU请求:

image-11.png

咱们有一个简单,可重复的环境,Horizo​​ntal Pod Autoscaler能够按预期工做。

如今,咱们假设在很短的时间内,需求会增长更多:

curl --data "millicores=120&durationSec=600"  $RESOURCE_CONSUMER_ADDRESS/ConsumeCPU

片刻以后,咱们看到HPA能够扩展以知足新的需求:

image-12.png

看起来咱们有一个处于待定状态的Pod,所以咱们尚未成功地进行扩展以知足新的需求。这里发生了什么?使用该Pod上的kubectl describe,咱们能够看到该Pod没法调度,由于工做节点没有足够的CPU来知足全部CPU请求。因为咱们如今有4个副本,这比640m / 1000m的基本状态多了400m的CPU请求,所以只能在该节点上安排3/4个副本。

kubectl describe pod/resource-consumer-55c57bc84c-986lk

image-13.png

咱们还能够看到因为挂起的pod触发了放大。在等待新节点出现以后,另外一个kubectl describe显示pod最终被调度在新节点上。

image-14.png

kubectl get events --field-selector=involvedObject.name=resource-consumer-55c57bc84c-986lk -o=custom-columns=FIRST_TIMESTAMP:.firstTimestamp,TYPE:.type,REASON:.reason,MESSAGE:.message

image-15.png

从以上内容能够看出,CA迅速作出反应,要求AWS扩展实例组-但仅在pod未能首先调度好以后。

Cooling Down

若是咱们等待对resource-consumer的请求中的durationSec指定的持续时间,咱们将看到resource-consumer回落到其原始资源使用状况。 CA会注意到这一点,并在默认的冷却时间10分钟后请求缩减规模。这对于节省成本相当重要。能够经过CA配置来调整冷却时间。

使用Cerebral抢占式自动缩放

清理并从新开始

确保咱们从头开始的最简单方法是简单地删除kops集群并从新建立它。要删除它,请运行如下命令:

kops --state=s3://bucket-name delete cluster autoscaling-experiment.k8s.local --yes

如今,只需从新建立测试设置,从建立kops集群开始,到配置HPA后结束。

部署Cerebral

在脑存储库中能够找到许多示例清单。首先,咱们须要应用一些必备清单,这些清单定义一些自定义资源定义,一个Cerebral的服务账户以及一些RBAC规则:

kubectl apply -f https://raw.githubusercontent.com/containership/cerebral/v0.4.0-alpha/examples/common/00-prereqs.yaml

咱们还必须像之前同样使用AWS凭证应用相同的secret。咱们能够下载示例secret清单并进行适当的编辑:

curl -O  https://raw.githubusercontent.com/containership/cerebral/master/examples/engines/aws/00-secret-cerebral-aws.yaml

# Edit OO-secret-cerebral-aws.yaml to fill in valid values 

kubectl apply -f OO-secret-cerebral-aws.yaml

接下来,让咱们部署Cerebral operator,它做为Kubernetes部署运行:

kubectl apply -f https://raw.githubusercontent.com/containership/cerebral/v0.4.0-alpha/examples/engines/aws/10-deployment-cerebral-aws.yaml

要向Cerebral注册AWS自动缩放引擎,须要一个AutoscalingEngine资源:

kubectl apply -f https://raw.githubusercontent.com/containership/cerebral/master/examples/engines/aws/20-autoscaling-engine-aws.yaml

最后,让咱们向Cerebral注册Kubernetes MetricsBackend:

kubectl apply -f https://raw.githubusercontent.com/containership/cerebral/v0.4.0-alpha/examples/metrics_backends/kubernetes/00-metrics-backend-kubernetes.yaml

若是一切顺利,日志应该看起来很健康,咱们应该看到有关引擎和后端成功注册的消息:

kubectl -n kube-system logs -lapp.kubernetes.io/name=cerebral

image-16.png

配置 Autoscaling Groups and Policies

既然Cerebral已启动并在Kubernetes指标后端已注册并运行AWS引擎的状况下运行,咱们能够将重点转移到定义一个自动扩展组和扩展该组的策略。

Cerebral存储库中提供了示例AutoscalingGroups以及示例AutoscalingPolicies。可是,让咱们在此处建立更特定于咱们的测试设置的组和策略。

首先,让咱们定义一个AutoscalingPolicy,该策略使用在上一步中定义的kubernetes指标后端收集CPU分配指标以进行自动缩放决策。咱们将每15秒轮询一次指标后端,并在30秒内进行抽样。若是CPU分配大于或等于80%的时间超过该采样周期,则Cerebral将按一个节点扩展:

image-30.jpg

如今应用它:

kubectl apply -f cpu-example-policy.yaml

接下来,让咱们定义AutoscalingGroup,以使minNodes和maxNodes与kops定义的AWS AutoscalingGroup相匹配。这对于避免意外行为很重要。选择用于选择属于该组的节点的标签选择器,以匹配咱们在kops配置中分配给工做组的标签,而咱们刚刚定义的策略将附加到该组:

image-31.jpg

如今应用它:

kubectl apply -f kops-group.yaml

有了这些简单的清单,一旦CPU分配超出阈值,Cerebral如今就能够自动缩放Kubernetes集群。

使用Cerebral 进行集群扩缩演示

彻底按照咱们在Kubernetes Cluster Autoscaler演示中所作的同样,让咱们​​向resource-consumer发出请求以使其消耗更多的CPU以模拟需求高峰的开始:

curl --data "millicores=60&durationSec=600"  $RESOURCE_CONSUMER_ADDRESS/ConsumeCPU

如预期的那样,第二个副本将出现并在几分钟后开始运行:

image-17.png

和之前同样,这会将工做节点池上的CPU请求总数提升到80%以上。Cerebral注意到了这一点,在咱们在AutoscalingPolicy中配置的短暂采样周期以后,触发了放大事件。咱们能够在Cerebral日志中看到这一点:

image-18.png

您还会在日志中注意到,引擎会忽略全部后续缩放请求,由于自动缩放组已进入了咱们定义的冷却期。这为新节点的创建提供了时间,并有助于避免对云提供商的伸缩请求进行大幅调整。

在短期内,AWS会启动新节点,并能够用于调度:

kubectl get events --field-selector=involvedObject.name=ip-172-20-37-156.ec2.internal -o=custom-columns=FIRST_TIMESTAMP:.firstTimestamp,REASON:.reason,MESSAGE:.message![image-19.png](/img/bVbCXem)

image-19.png

如您所见,在触发放大以前,咱们没必要等待任何pod处于“待处理”状态。违反定义的CPU资源请求阈值后,就会触发放大事件。换句话说,Cerebral抢先调度另外一个节点,以知足Pod调度需求。

Cooling Down

在增长的需求减小以后缩减规模以节省成本一样容易。
只需编辑AutoscalingPolicy便可添加一个缩减策略,一旦资源请求低于定义的阈值,该策略就会触发。

重点

当在咱们的测试场景中增长负载时,Kubernetes Cluster Autoscaler(CA)和Cerebral都可以成功地扩展集群(向该集群添加节点)。当发现负载正在增长时,Cerebral可以使用用户定义的CPU阈值抢先扩大规模。可是,Kubernetes CA必须等待,直到没法调度Pod。

这只是使用Cerebral优于Kubernetes CA的一个很是具体的例子。Cerebral的真正力量在于其灵活性和可扩展性。例如,在先前的实验中,若是负载瞬间增长到最高点,则Cerebral将没法抢先缩放,而且两个自动缩放器之间的结果将很是类似。可是,与Kubernetes CA不一样,Cerebral能够配置为使用自定义指标/事件后端来触发不一样指标的缩放(例如,push ,应用程序队列深度达到某个阈值等)。

借助Cerebral,操做员能够以对其系统有意义的方式配置自动缩放。因为基于CRD的方法,他们还能够轻松地将此功能转移到其余云提供商。