加入收藏 | 设为首页 | 会员中心 | 我要投稿 南通站长网 (https://www.0513zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 云计算 > 正文

添加K8S CPU limit会减少服务性能?

发布时间:2022-04-25 09:18:02 所属栏目:云计算 来源:互联网
导读:众所周知,Kubernetes QOS 分为三个级别: Guaranteed:Pod 里的每个容器都必须有内存/CPU 限制和请求,而且值必须相等。如果一个容器只指明limit而未设定request,则request的值等于limit值。 Burstable:Pod 里至少有一个容器有内存或者 CPU 请求且不满足 G
  众所周知,Kubernetes QOS 分为三个级别:
 
  Guaranteed:Pod 里的每个容器都必须有内存/CPU 限制和请求,而且值必须相等。如果一个容器只指明limit而未设定request,则request的值等于limit值。
  Burstable:Pod 里至少有一个容器有内存或者 CPU 请求且不满足 Guarantee 等级的要求,即内存/CPU 的值设置的不同。
  BestEffort:容器必须没有任何内存或者 CPU 的限制或请求。
  谷歌的最佳实践告诉你,重要服务一定要配置 Guaranteed 的,这样在资源不足的时候可以保证你的重要服务不被驱逐。
 
  最佳实践要求你这样配置是从运维和后期运营的角度来说的,团队刚起步,不设置资源请求和限制的情况下基本可以正常工作,但随着团队和项目的增长,您将开始遇到稳定性问题。服务之间相互影响,这时候可能需要为服务添加限制,并且可以让您免于遇到许多令人头疼的问题。
 
  这里我们应该已经清楚,通过遵循最佳实践,使整个集群具有更大的灵活性和可靠性。但是当涉及到 CPU 限制时,事情就变得有趣了。CPU 是可压缩资源。如果您的应用开始达到 CPU 限制,Kubernetes 就会开始限制您的容器。这意味着 CPU 将受到人为限制,使您的应用程序性能可能更差!
 
  1. 为什么会这样呢?
  因为当你在容器编排器中设置硬 CPU 限制时,内核使用完全公平调度程序 (CFS) Cgroup来强制执行这些限制。CFS Cgroup 机制使用两个设置来管理 CPU 分配:配额和周期。当应用程序在给定时间段内使用超过其分配的 CPU 配额时,它会受到限制,直到下一个时间段。
 
  cgroup 的所有 CPU 指标都位于​​/sys/fs/cgroup/cpu,cpuacct/<container>​​. 配额和期间设置位于​​cpu.cfs_quota_us​​和中​​cpu.cfs_period_us​​。
 
  您还可以查看限制指标 cpu.stat。在里面 cpu.stat 你会发现:
 
  nr_periods– cgroup 任何线程可运行的周期数
  nr_throttled– 应用程序使用其全部配额并受到限制的可运行周期数
  throttled_time– 控制 cgroup 中各个线程的总时间

  2. 是否存在不必要的限制
  并没有这么简单,很多人反馈遭到了不必要的 cgroup 限制,甚至还没有 CPU 上限,这里有激烈的讨论:
 
  ​​​​https://github.com/kubernetes/kubernetes/issues/67577​​​​
  ​​​​https://github.com/kubernetes/kubernetes/issues/51135​​​​
  ​​​​https://github.com/kubernetes/kubernetes/issues/70585​​​​
  ​​​​https://github.com/kubernetes/kubernetes/pull/75682​​​​
  运行容器时要检查的关键指标是throttling. 这表明您的容器被限制的次数。我们发现很多容器无论 CPU 使用率是否接近极限都会受到限制。如下一个热心网友反馈的案例:
 
  在动画中可以看到 CPU 限制设置为800m(0.8 个核心,80% 的核心),峰值使用率最高为200m(20% 的核心)。看到之后,我们可能会认为我们有足够的 CPU 让服务在它节流之前运行,对吧?. 现在看看这个:
 
  即使 CPU 使用率低于 CPU 限制,您也会注意到发生了 CPU 限制。最大 CPU 使用率甚至没有接近 CPU 限制。
 
  限制就意味着服务性能下降和延迟增高。

  3. linux 内核是如何解决这个问题
  当且仅当每个 CPU 的过期时间与全局过期时间匹配时,预补丁代码才会在运行时过期​​cfs_rq->runtime_expires != cfs_b->runtime_expires​​。通过检测内核,我证明了这种情况在我的节点上几乎从未出现过。因此,那 1 毫秒永不过期。该补丁将此逻辑从基于时钟时间更改为周期序列计数,解决了内核中长期存在的错误。
  修改问题 5.4+ 主线内核的一部分。它们已被反向移植到许多可用的内核中:
 
  RHEL 7: 3.10.0–1062.8.1.el7+
  RHEL 8: 4.18.0–147.2.1.el8_1+
  Linux-stable: 4.14.154+, 4.19.84+, 5.3.9+
  Ubuntu: 4.15.0–67+, 5.3.0–24+
  Redhat Enterprise Linux:
  CoreOS: v4.19.84+
  该错误​​​​https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=763a9ec06c4​​​​已被修复并合并到运行 4.19 或更高版本的 Linux 发行版的内核中。
 
  但是,在阅读kubernetes issue时​​​​https://github.com/kubernetes/kubernetes/issues/67577​​​​,我们可以看到各种 Linux 项目一直在引用这个 issue,所以我猜一些 Linux 发行版仍然存在这个 bug,并且正在努力整合修复。
 
  如果你的 Linux 发行版的内核版本低于 4.19,我建议你为你的节点升级到最新的 Linux 发行版,但无论如何,你应该尝试移除 CPU 限制并查看是否有任何限制.
 
  4. 总结
  监控你的容器,是否因为 throttle 而导致的性能不佳,如果确实发生了,最好通过分批升级内核版本解决,如果无法升级,可以通过方式解决:
 
  解除限制(个人觉得这个并不是一个好主意)
  有性能要求的 Pod 调度到带特定污点的节点;
  对这些 Pod 删除 CPU 限制,可以考虑在 namespace 级别添加限制。
  增加资源
  另外 CPU throttle 节流主要是因为 CPU 限制较低。它的限制影响 Cgroup 的行为。因此,一个快速解决该问题的方法是根据监控将限值提高 10-25%,以确保降低峰值或完全避免峰值。
 
  自动扩容
  因为将 CPU 请求和限制设置为相同的值通常会给人们他们所期望的行为,解决此问题的简单方法是将 CPU 请求和限制设置为相同的值并添加 HPA。让 Pod 根据负载进行自动扩缩容。

(编辑:南通站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!