28

一个损失巨大的错误(关于Kubernetes和GKE)

 4 years ago
source link: http://dockone.io/article/9401
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

【编者的话】云计算时代,对于Kubernetes来说,规模化的扩展带来了方便,但是规模化带来的成本也是不容小觑的,如何更低成本更高效的使用Kubernetes集群,本文将揭晓答案。

不幸的是,标题并没有夸张。作为免责声明,我首先要补充一点,这是一个非常愚蠢的错误,显示了我在管理自动伸缩部署方面缺乏经验。然而,这一切都始于一个没有答案的问题,我觉得有义务分享我的经验来帮助其他人避免类似的陷阱。

使用100x n1-standard-1 (1 vCPU) VMs的Kubernetes集群与使用1x n1-standard-96 (vCPU 96)或使用6x n1-standard-16 VMs (vCPU 16)的Kubernetes集群有什么区别?

这个问题我在Kubernetes社区问过很多次,没有人给出建设性的答案。如果你对答案不确定,那么你可以从我的经验中学到一些东西(如果没有耐心可以直接跳到答案部分)。

前提(序)

某一天,我半夜醒来,决定降低我们的基础设施成本。

我们正在运行一个大型Kubernetes集群。当然,“大”是相对的。在我们的例子中,正常工作时间是600个vcpu。这个数字在高峰时间翻倍,在晚上的某些时候接近于0。

上个月的发票是3500美元。

BziaAz3.png!web

考虑到我们所获得的计算能力,这已经相当不错了,但是谷歌Kubernetes引擎(GKE)使成本管理变得非常简单:

  • 我们使用最便宜的数据中心(europe-west2 (London)就比europe-west4 (Netherlands)贵15%)
  • 我们为不同的部署使用不同的机器类型(偏重内存vs偏重CPU)
  • 我们使用水平Pod自动调度器(HPA)和自定义指标来扩展部署
  • 我们使用cluster-autoscaler来扩展节点池
  • 我们使用可抢占的vm

使用专门可抢占的vm使我们能够保持低成本。为了说明节省的费用,对于在europe-west4中托管的n1-standard-1机器类型,专属VM和可抢占VM之间的差异是26.73美元/月和8.03美元/月,这样成本就降低了3.25倍。当然,可抢占的vm有其局限性,你需要熟悉和克服这些局限性,但这是一个完全不同的主题。

有了以上所有的条件,我觉得我们正在做所有正确的事情来保持低成本。然而,我总是有一种挥之不去的感觉,觉得事情不对劲,不吐不快。

主要的红色标志

关于那种烦人的情况:

每个节点的平均CPU使用量很低(10%-20%),这似乎是不对的。

我的第一个想法是我错误地配置了 计算资源 。所需的资源完全取决于正在运行的程序。因此,最好的方法是在没有资源限制的情况下部署程序,观察程序在空闲/常规负载和峰值负载期间的行为,并根据观察到的值设置请求/限制资源。

我将通过单个部署“admdesl”的示例来说明我的错误。

我们的使用情况是,所需资源是零星分布的:

NAME                       CPU(cores)   MEMORY(bytes)

admdesl-5fcfbb5544-lq7wc   3m           112Mi

admdesl-5fcfbb5544-mfsvf   3m           118Mi

admdesl-5fcfbb5544-nj49v   4m           107Mi

admdesl-5fcfbb5544-nkvk9   3m           103Mi

admdesl-5fcfbb5544-nxbrd   3m           117Mi

admdesl-5fcfbb5544-pb726   3m           98Mi

admdesl-5fcfbb5544-rhhgn   83m          119Mi

admdesl-5fcfbb5544-rhp76   2m           105Mi

admdesl-5fcfbb5544-scqgq   4m           117Mi

admdesl-5fcfbb5544-tn556   49m          101Mi

admdesl-5fcfbb5544-tngv4   2m           135Mi

admdesl-5fcfbb5544-vcmjm   22m          106Mi

admdesl-5fcfbb5544-w9dsv   180m         100Mi

admdesl-5fcfbb5544-whwtk   3m           103Mi

admdesl-5fcfbb5544-wjnnk   132m         110Mi

admdesl-5fcfbb5544-xrrvt   4m           124Mi

admdesl-5fcfbb5544-zhbqw   4m           112Mi

admdesl-5fcfbb5544-zs75s   144m         103Mi

其中,平均5m的pod是“空闲”的:队列中有一个任务等待它们处理,但是我们正在等待某些(外部)条件清除后再继续。在这种特殊的部署情况下,这些pods每分钟将在空闲/活动状态之间多次改变,并在空闲状态中花费70%以上的时间。

一分钟后,相同的pods看起来就不一样了:

NAME                       CPU(cores)   MEMORY(bytes)

admdesl-5fcfbb5544-lq7wc   152m         107Mi

admdesl-5fcfbb5544-mfsvf   49m          102Mi

admdesl-5fcfbb5544-nj49v   151m         116Mi

admdesl-5fcfbb5544-nkvk9   105m         100Mi

admdesl-5fcfbb5544-nxbrd   160m         119Mi

admdesl-5fcfbb5544-pb726   6m           103Mi

admdesl-5fcfbb5544-rhhgn   20m          109Mi

admdesl-5fcfbb5544-rhp76   110m         103Mi

admdesl-5fcfbb5544-scqgq   13m          120Mi

admdesl-5fcfbb5544-tn556   131m         115Mi

admdesl-5fcfbb5544-tngv4   52m          113Mi

admdesl-5fcfbb5544-vcmjm   102m         104Mi

admdesl-5fcfbb5544-w9dsv   18m          125Mi

admdesl-5fcfbb5544-whwtk   173m         122Mi

admdesl-5fcfbb5544-wjnnk   31m          110Mi

admdesl-5fcfbb5544-xrrvt   91m          126Mi

admdesl-5fcfbb5544-zhbqw   49m          107Mi

admdesl-5fcfbb5544-zs75s   87m          148Mi

看到上面的内容,我认为有一个配置是有意义的,比如:

resources:

  requests:

    memory: '150Mi'

    cpu: '20m'

  limits:

    memory: '250Mi'

    cpu: '200m'

这意味着:

  • 闲置的pods消耗不超过20m
  • 活跃(健康)的pods在200m时达到峰值

然而,当我使用这个配置时,它使部署变得繁忙了。

admdesl-78fc6f5fc9-xftgr  0/1    Terminating                3         21m

admdesl-78fc6f5fc9-xgbcq  0/1    Init:CreateContainerError  0         10m

admdesl-78fc6f5fc9-xhfmh  0/1    Init:CreateContainerError  1         9m44s

admdesl-78fc6f5fc9-xjf4r  0/1    Init:CreateContainerError  0         10m

admdesl-78fc6f5fc9-xkcfw  0/1    Terminating                0         20m

admdesl-78fc6f5fc9-xksc9  0/1    Init:0/1                   0         10m

admdesl-78fc6f5fc9-xktzq  1/1    Running                    0         10m

admdesl-78fc6f5fc9-xkwmw  0/1    Init:CreateContainerError  0         9m43s

admdesl-78fc6f5fc9-xm8pt  0/1    Init:0/1                   0         10m

admdesl-78fc6f5fc9-xmhpn  0/1    CreateContainerError       0         8m56s

admdesl-78fc6f5fc9-xn25n  0/1    Init:0/1                   0         9m6s

admdesl-78fc6f5fc9-xnv4c  0/1    Terminating                0         20m

admdesl-78fc6f5fc9-xp8tf  0/1    Init:0/1                   0         10m

admdesl-78fc6f5fc9-xpc2h  0/1    Init:0/1                   0         10m

admdesl-78fc6f5fc9-xpdhr  0/1    Terminating                0         131m

admdesl-78fc6f5fc9-xqflf  0/1    CreateContainerError       0         10m

admdesl-78fc6f5fc9-xrqjv  1/1    Running                    0         10m

admdesl-78fc6f5fc9-xrrwx  0/1    Terminating                0         21m

admdesl-78fc6f5fc9-xs79k  0/1    Terminating                0         21m

每当一个新节点被加入/移出集群时都会发生这种情况(由于自动伸缩而经常发生这种情况)。

因此,我不断增加请求的pod资源,直到我完成以下配置:

resources:

  requests:

    memory: '150Mi'

    cpu: '100m'

  limits:

    memory: '250Mi'

    cpu: '500m'

通过这种配置,集群可以顺利地运行,但这意味着即使是空闲的pod也会预先分配比它们所需的更多的CPU时间。这就是每个节点的平均CPU使用量较低的原因。但是,我不知道解决方案是什么(减少请求的资源会导致繁忙的集群状态/中断),因此我为所有部署提供了一种慷慨的资源分配变体。

答案

回到我的问题:

使用100x n1-standard-1 (1 vCPU) VMs的Kubernetes集群与使用1x n1-standard-96 (vCPU 96)或使用6x n1-standard-16 VMs (vCPU 16)的Kubernetes集群有什么区别?

对于初学者来说,n1-standard-1和n1-standard-96之间没有单个vcpu的价格差异。因此,我认为使用具有较少vcpu的机器将使我能够更好地控制价格。

我考虑的另一个问题是集群自动伸缩的速度有多快,也就是说,如果突然出现激增,集群自动伸缩器为计划外的pod提供新节点的速度有多快。不过,这并不是我们所关心的问题- -我们对资源的需求是逐渐增加和减少的。

所以我用了1个vCPU节点,结果我在前提中已经描述过了。

回顾过去,这是一个明显的错误:使用单个vCPU在节点上分布pod,在空闲和活动状态之间的单个部署更改时,不允许有效地利用资源。换句话说,在同一台机器上的vcpu越多,就可以将许多pod打包得越紧,因为当一部分pod超出了它们所需的配额时,就有现成的资源可供使用。

有效的工作是:

  • 我切换到16-vCPU机器,因为它们提供了一种平衡的解决方案,可以在自动扩展集群时进行良好的资源控制,也可以在每台机器上提供足够的资源来实现对处于空闲/活动状态的pod的严格调度。
  • 我使用的资源配置请求仅比空闲状态所需的资源多一点点,但是有很大的限制。当大多数pods处于空闲状态时,它允许在同一台机器上调度多个pods,但仍然允许资源密集型突发事件。
  • 我切换到n2机器类型:n2机器更贵,但是它们有2.8 GHz的基频(与n1-*机器可用的~2.2 GHz相比)。我们正在利用更高的时钟频率来尽可能快地处理资源密集型任务,并将pod尽可能快地置于前面描述的空闲状态。

当前节点vCPU的平均使用率高达60%。这听起来是对的,需要一些时间才能得出节省了多少。然而,惊喜的是,今天我们使用的vcpu还不到昨天的一半。

作者:Gajus Kuizinas。

原文链接: Mistake that cost thousands (Kubernetes, GKE)

译者:Mr.lzc,软件研发工程师、DevOpsDays深圳组织者&志愿者,目前供职于华为,从事云存储工作,以Cloud Native方式构建云文件系统服务,专注于K8s、微服务领域。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK