Kubernetes中的自动缩放

编者注:这篇文章是 系列深入文章 Kubernetes 1.3的新功能

使用Kubernetes的客户比以往任何时候都可以更快地响应最终用户的请求,并更快地交付软件。但是,当构建的服务比您计划的要受欢迎并且用尽计算时,会发生什么?在 Kubernetes 1.3,我们很自豪地宣布我们有一个解决方案:自动缩放。上 Google Compute Engine (GCE)和 Google容器引擎 (GKE)(即将推出 AWS ),Kubernetes会在需要时立即自动扩展集群,然后在不需要时自动缩减集群以节省资金。

自动缩放的好处

为了更好地了解自动缩放可在哪些地方提供最大价值,我们从一个示例开始。想象一下,您有一个24/7的生产服务,其负载随时间变化,在美国白天白天很忙,而晚上则相对较低。理想情况下,我们希望集群中的节点数和部署中的Pod数能够动态调整以适应最终用户的需求。新的“群集自动缩放”功能以及“水平荚自动缩放器”可以自动为您处理此问题。

在GCE上设置自动缩放

以下说明适用于GCE。对于GKE,请查看可用的集群操作手册中的“自动缩放”部分 这里.

在开始之前,我们需要有一个活动的GCE项目,并且已启用Google Cloud Monitoring,Google Cloud Logging和Stackdriver。有关项目创建的更多信息,请阅读我们的 入门指南。我们还需要下载Kubernetes项目的最新版本(版本 v1.3.0 或更高版本)。

首先,我们在群集自动缩放器打开的情况下设置了群集。群集中的节点数量将从2个开始,并自动扩展到最多5个。要实现此目的,我们将导出以下环境变量:

export NUM\_NODES=2

export KUBE\_AUTOSCALER\_MIN\_NODES=2

export KUBE\_AUTOSCALER\_MAX\_NODES=5

export KUBE\_ENABLE\_CLUSTER\_AUTOSCALER=true

并通过运行以下命令启动集群:

./cluster/kube-up.sh

kube-up.sh脚本与Cluster Autoscaler附加组件一起创建集群。如果存在可能在新节点上调度的挂起的Pod,则自动缩放器将尝试将新节点添加到群集。

让我们看看我们的集群,它应该有两个节点:

$ kubectl get nodes

NAME                           STATUS                     AGE

kubernetes-master              Ready,SchedulingDisabled   2m

kubernetes-minion-group-de5q   Ready                      2m

kubernetes-minion-group-yhdx   Ready                      1m

运行并公开PHP-Apache服务器

为了演示自动缩放,我们将使用基于php-apache服务器的自定义docker映像。可以找到图片 这里。它定义 index.php 该页面执行一些CPU密集型计算。

首先,我们将开始运行该映像的部署并将其作为服务公开:

$ kubectl运行 php-apache \   

  --image=gcr.io/google\_containers/hpa-example \

  --requests=cpu=500m,memory=500M --expose --port=80  

service "php-apache" createddeployment "php-apache" created

现在,我们将等待一段时间,并验证部署和服务均已正确创建并正在运行:

$ kubectl get deployment

NAME         DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE

php-apache   1         1         1            1           49s



$ kubectl get pods  
NAME                          READY     STATUS    RESTARTS   AGE

php-apache-2046965998-z65jn   1/1       Running   0          30s

现在,我们可以通过使用服务地址调用wget来检查php-apache服务器是否正常工作:

$ kubectl运行 -i --tty service-test --image=busybox /bin/sh  
Hit enter for command prompt  
$ wget -q -O- http://php-apache.default.svc.cluster.local

OK!

启动水平Pod自动缩放器

现在部署正在运行,我们将为其创建一个Horizo​​ntal Pod Autoscaler。要创建它,我们将使用kubectl autoscale命令,如下所示:

$ kubectl autoscale deployment php-apache --cpu-percent=50 --min=1 --max=10

这定义了一个水平Ppod自动缩放器,该缩放器维护1至10个Pod副本,这些副本由我们在这些说明的第一步中创建的php-apache部署控制。粗略地说,水平自动缩放器将增加和减少副本数量(通过部署),以使所有Pod的平均CPU利用率保持50%(因为每个Pod要求500毫核)。 kubectl运行,这意味着平均CPU使用率为250毫核。看到 这里 有关算法的更多详细信息。

我们可以通过运行以下命令检查自动定标器的当前状态:

$ kubectl get hpa

NAME         REFERENCE                     TARGET    CURRENT   MINPODS   MAXPODS   AGE

php-apache   Deployment/php-apache/scale   50%       0%        1         20        14s

请注意,由于我们没有向服务器发送任何请求,因此当前CPU消耗为0%(“ CURRENT”列显示了由相应复制控制器控制的所有Pod的平均值)。

提高负荷

现在,我们将看到自动缩放器(集群自动缩放器和Horizo​​ntal Pod自动缩放器)对服务器负载增加的反应。我们将开始对服务器的两个无限查询循环(请在不同的终端中运行它们):

$ kubectl运行 -i --tty load-generator --image=busybox /bin/sh  
Hit enter for command prompt  
$ while true; do wget -q -O- http://php-apache.default.svc.cluster.local; done

我们需要等待一分钟(大约一分钟),以便统计数据传播。然后,我们将检查Horizo​​ntal Pod Autoscaler的状态:

$ kubectl get hpa

NAME         REFERENCE                     TARGET    CURRENT   MINPODS   MAXPODS   AGE

php-apache   Deployment/php-apache/scale   50%       310%      1         20        2m



$ kubectl get deployment php-apache

NAME              DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE

php-apache        7         7         7            3           4m

Horizo​​ntal Pod Autoscaler已将我们部署中的Pod数量增加到7个。现在,检查所有Pod是否都在运行:

jsz@jsz-desk2:~/k8s-src$ kubectl get pods

php-apache-2046965998-3ewo6        0/1       Pending   0          1m

php-apache-2046965998-8m03k        1/1       Running   0          1m

php-apache-2046965998-ddpgp        1/1       Running   0          5m

php-apache-2046965998-lrik6        1/1       Running   0          1m

php-apache-2046965998-nj465        0/1       Pending   0          1m

php-apache-2046965998-tmwg1        1/1       Running   0          1m

php-apache-2046965998-xkbw1        0/1       Pending   0          1m

如我们所见,一些吊舱正在等待处理。让我们描述一个未决豆荚,以获取未决状态的原因:

$ kubectl describe pod php-apache-2046965998-3ewo6

Name: php-apache-2046965998-3ewo6

Namespace: default

...

Events:

  FirstSeen From SubobjectPath Type Reason Message



  1m {default-scheduler } Warning FailedScheduling pod (php-apache-2046965998-3ewo6) failed to fit in any node

fit failure on node (kubernetes-minion-group-yhdx): Insufficient CPU

fit failure on node (kubernetes-minion-group-de5q): Insufficient CPU



  1m {cluster-autoscaler } Normal TriggeredScaleUp pod triggered scale-up, mig: kubernetes-minion-group, sizes (current/new): 2/3

由于系统中没有CPU,因此该Pod处于挂起状态。我们看到有一个与该广告连播关联的TriggeredScaleUp事件。这意味着pod触发了Cluster Autoscaler的反应,并且新节点将添加到集群中。现在,我们等待反应(大约3分钟)并列出所有节点:

$ kubectl get nodes

NAME                           STATUS                     AGE

kubernetes-master              Ready,SchedulingDisabled   9m

kubernetes-minion-group-6z5i   Ready                      43s

kubernetes-minion-group-de5q   Ready                      9m

kubernetes-minion-group-yhdx   Ready                      9m

如我们所见,群集自动缩放器添加了一个新节点kubernetes-minion-group-6z5i。让我们确认所有的Pod现在都在运行:

$ kubectl get pods

NAME                               READY     STATUS    RESTARTS   AGE

php-apache-2046965998-3ewo6        1/1       Running   0          3m

php-apache-2046965998-8m03k        1/1       Running   0          3m

php-apache-2046965998-ddpgp        1/1       Running   0          7m

php-apache-2046965998-lrik6        1/1       Running   0          3m

php-apache-2046965998-nj465        1/1       Running   0          3m

php-apache-2046965998-tmwg1        1/1       Running   0          3m

php-apache-2046965998-xkbw1        1/1       Running   0          3m

添加节点后,所有php-apache pod都在运行!

停止加载

我们将通过停止用户负载来完成示例。我们将终止两个无限的while循环,将循环发送请求到服务器并验证结果状态:

$ kubectl get hpa

NAME         REFERENCE                     TARGET    CURRENT   MINPODS   MAXPODS   AGE

php-apache   Deployment/php-apache/scale   50%       0%        1         10        16m



$ kubectl get deployment php-apache

NAME              DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE

php-apache        1         1         1            1           14m

如我们所见,在当前情况下,CPU利用率降至0,副本数降至1。

删除Pod后,大多数群集资源均未使用。向下扩展群集可能要比向上扩展花费更多的时间,因为“群集自动缩放器”可确保确实不需要该节点,以便短时间的不活动(由于Pod升级等)不会触发节点删除(请参见 集群自动缩放器文档)。大约10到12分钟后,您可以验证集群中的节点数是否已下降:

$ kubectl get nodes

NAME                           STATUS                     AGE

kubernetes-master              Ready,SchedulingDisabled   37m

kubernetes-minion-group-de5q   Ready                      36m

kubernetes-minion-group-yhdx   Ready                      36m

由于群集自动缩放器删除了节点kubernetes-minion-group-6z5i,因此群集中的节点现在又增加了两个。

其他用例

如我们所展示的,结合使用水平Pod Autoscaler和Cluster Autoscaler来动态调整Pod数量以适应负载非常容易。

但是,只要集群负载出现异常,单独使用Cluster Autoscaler也会很有帮助。例如,在周末或晚上可能不需要与开发或持续集成测试相关的集群。批处理群集可能会有一段时间,所有作业都结束了,新作业只会在几个小时内开始。拥有无能为力的机器是浪费金钱。

在所有这些情况下,Cluster Autoscaler都可以减少未使用的节点数量并节省大量资金,因为您只需为运行Pod所需的这些节点付费。它还可以确保您始终具有足够的计算能力来运行任务。

-Google软件工程师Jerzy Szczepkowski和Marcin Wielgus