18

Kubernetes: 通过移除CPU限制实现服务加速

 3 years ago
source link: http://dockone.io/article/10888
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.
neoserver,ios ssh client

August 31, 2020 8

kubernetes • infrastructure

在Buffer公司,我们从2016年就开始使用Kubernetes。我们一直使用kops管理我们在AWS云上k8s ( Kubernetes)集群,它有大约60个节点,运行大约1500个容器。我们在向微服务体系结构的过渡过程中充满了尝试和错误,即变使用k8s的几年之后,我们仍在探索它的秘密,本篇文章将讨论一个我们认为不错的实践经验,即CPU使用限制。

CPU使用限制和节流

包括谷歌在内的一些大公司都强烈推荐在应用环境中设置CPU使用限制。因为不设置CPU限制的典型危害就是节点中运行的容器可能耗尽所有可用的CPU资源,从而触发一连串严重的连锁事件反应,例如导致kubelet 之类的关键进程无响应等。因此,从理论上讲,设置CPU限制来保护节点的做法是至关重要的。

CPU使用限制是容器在给定时间段内可以使用的最大CPU时间(默认为100ms)。这个人工指定的限制是不允许被超过的。Kubernetes采用一种称为CFS配额的机制来控制容器CPU使用不会超越这个限制值。这也意味着CPU使用将被人为地限制,从而导致容器在高计算情况下发生性能下降(如延迟更大)。

如果不设置CPU限制将会发生什么?

我们很不幸地经历了这个问题。运行在每个节点上负责管理节点POD容器的kubelet进程变得不响应,整个节点变成NotReady状态,节点内的POD容器被调度到其他节点,并在新节点中再次触发新的问题事件。

发现CPU节流和延迟问题

在容器的运行过程中,通常要检查的一个关键指标是CPU节流,这指标表明容器被节流的CPU时间。有趣的是,我们在过程中发现无论CPU使用率是否接近限制,很多容器都执行了节流动作,以下是我们主要API的一个案例:

byyqemE.png!mobile

如图所示:CPU限制被设置为800微核(0.8核),峰值使用率最多为200微核(0.2核)。数据对比发现,我们认为还有足够的CPU资源可以让服务使用。是否真是推论的这样呢?接下来再看看这个:

QzMRV3u.png!mobile

如图所示,我们可以发现,即使CPU使用率低于限制值,甚至最大CPU使用远没有接近CPU限制,也服务也出现了CPU节流情况。

在讨论节流如何导致服务性能下降和延迟的问题,我们找到了部分资源( github问题zanado 会话 , omio 推送 ,通过查阅资料,我们发现与之相关的 Linux内核TLDR进程存在一个bug,它通过非必要的CPU限制功能制约了容器的资源使用。这个进程的详细信息,建议查阅Dave Chiluk的 伟大的演讲书面版本

删除CPU限制(谨慎操作)

我们内部经过多次长时间的讨论,最终决定取消用户关键路径上的所有直接或间接服务的CPU限制。这决定并不轻松,因为这个决定关系到我们向来都很重视的集群稳定性。我们曾经经历过集群不稳定的情况,即某些服务使用了太多的资源,并影响了同节点中运行的所有其他服务。但与当时情况不同的是,这次我们更清楚我们服务的资源需求,并制定了一个很好好的策略来推行它。

UBvEreB.png!mobile

如何保证删除CPU使用限制后的节点安全

  • 隔离“无CPU限制”服务

我们过去看到某些节点变成 “notReady”状态,主要是因为节点内的有些服务占用了太多资源。因此,我们决定将这些高消耗的服务放在特定的节点(污染节点)上,从而让这些服务就不会影响到所有“边界清晰”的节点。我们采用更好控制措施,更容易地发现存在问题的节点,从而标识出污染节点,并对超限使用的服务添加缓冲措施来提升服务的可靠性。实现过程请查看 文档

rEFF7nr.png!mobile

  • 正确分配的CPU和内存

我们的主要担忧是服务消耗了太多的资源,从而导致节点没有响应。通过使用Datadog工具,使我们对集群中运行的所有服务具有非常好的观察力,所以我对希望去除限制的每个服务,开展了几个月的资源使用分析。我按照服务所请求CPU资源的1.2倍,设置了服务的最大CPU使用。这将确保在K8S不尝试调度同一节点中的任何其他服务的情况下,为节点上的服务分配了足够的资源。

Nfa6vy.png!mobile

从图中可以看到CPU峰值使用率为242m CPU核心(0.242 CPU核心)。我们只需将最大CPU使用的设置数字提高一点即可。同时还可以注意到,由于服务是面向用户的,因此CPU峰值使用率与峰值流量时间是相互匹配的。

对内存的请求和使用情况也执行同样的操作策略。为了提升服务的安全性,在容器内资源使用率过高时,可以使用POD的自动水平伸缩功能来创建新的POD,Kubernetes将自动将新建的「POD调度到资源充足的节点中。除此之外,我们还建议为集群设计资源使用告警,或者使用节点的自动伸缩功能为资源不够的集群自动添加计算节点。

上述策略所带来的缺点是降低了节点内的“容器密度”,即在单个节点中运行的容器数量会少一些。在低流量期间,可能会出现大量的“闲置块”。即便如此,您还可能遇到一些CPU使用率过高的情况,但是节点自动伸缩功能可以解决这种类型的问题。

  • 结果

经过几周的试验,我很高兴发布非常棒的结果,我们已经看到了我们所调整的全部服务在延迟方面的显著改进,数据如下图所示:

vy6ju2q.png!mobile

其中,我们的主登陆页面(buffer.com)服务提升最大,服务响应速度提高了22倍。

QbAzq2j.png!mobile

Linux内核bug的修复情况

确认这个bug已经被修复,并被合并到运行4.19或更高版本的Linux内核中。然而,截止到2020年9月2日,我们阅读Kubernetes的问题资料时,仍然可以看到多个Linux项目还在引用这个问题,所以猜测某些Linux发行版仍然存在这个bug,并且正在修复集成中。

如果您节点所用的内核版本低于4.19,那建议升级到最新的Linux发行版。并且在任何情况下,都应该尝试删除CPU限制来验证是否存在任何CPU或内存限制。以下为各种托管的Kubernetes服务或Linux发行版的修复情况:

Debian:最新版本已经修复,发布日期为2020年8月,部分更早版本可能已经被修补;

Ubuntu:最新版本Ubuntu Focal Fosa 20.04已经修复;

EKS自2019年12月修复;

kops:从2020年6月修复,kops 1.18+将使用Ubuntu 20.04作为默认系统映像;

GKE(Google云):不确定,猜测可能已经修复.

附:具备日期不完成肯定,欢迎实践信息反馈。同时,BUG修复是否解决了节流问题?我不确定这个问题是否完全解决了。我将尝试对修复过的内核版本进行验证,并根据实践情况相应更新这篇文章。如果有人做了,也很期待结果分享。

要点总结

如果你在Linux下运行Docker容器(无论是Kubernetes/Mesos/Swarm),你的容器都可能会因为CPU节流限制而导致性能表现不佳。

升级软件发行版的最新版本,以期望bug被修复。

消除CPU限制是解决这个问题的一个解决方案,但存在高风险,应该格外小心,建议先升级内核和调节性能监视器。

如果删除了CPU限制,需仔细监控节点的CPU和内存使用情况,并确保CPU资源请求可以得到满足。

推荐采用POD的水平伸缩功能,如果资源使用率很高,可以利用Kubernetes自动创POD,并调度到资源充足的节点上。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK