Kubernetes的Memory溢出和CPU 限流问题

后端 潘老师 6个月前 (11-13) 203 ℃ (0) 扫码查看

本文主要讲解Kubernetes的Memory溢出和CPU 限流问题,我们来一起学习一下吧!

前言

在使用Kubernetes时,内存不足(OOM)错误和CPU限制是云应用程序中资源处理的主要问题。为什么会这样呢?

云应用程序中的CPU和内存需求越来越重要,因为它们与云成本直接相关。

通过Limits和Request,我们可以配置pod应该如何分配内存和CPU资源,以防止资源耗尽并提升云成本。

如果节点没有足够的资源,pod可能会通过抢占或节点压力被驱逐,当进程耗尽内存(OOM)时,因为没有可用的资源,则会被操作系统强制kill掉,如果CPU消耗高于实际限制,则将开始对进程进行限制。

那么,本文来讲解一下如何监控Kubernetes Pods对OOM和CPU限制

Kubernetes OOM

Pod中的每个Container都需要内存才能运行,Kubernetes的限制是在Pod定义或Deployment定义中为每个容器设置的,

在当下所有UNIX系统中都有一种机制为了防止内存超出,来强制终止进程的运行,这种机制下会将该进程标记为 错误137 或者 OOMKilled 。

比如:

State:          Running
      Started:      Thu, 10 Oct 2019 11:14:13 +0200
    Last State:     Terminated
      Reason:       OOMKilled
      Exit Code:    137
      Started:      Thu, 10 Oct 2019 11:04:03 +0200
      Finished:     Thu, 10 Oct 2019 11:14:11 +0200

Exit Code 137表示进程使用的内存超过了允许的数量,必须终止该进程

这是Linux中的一个特性,内核为系统中运行的进程设置一个oom_score值。此外,它允许设置一个名为oom_score_adj的值,Kubernetes使用该值来保障服务质量。它还具有一个OOM Killer,它将审查进程并终止那些使用过多内存的进程。

注意,在Kubernetes中,进程可以达到以下任何一个限制:

  • 在容器上设置的Kubernetes限制
  • 在命名空间上设置的Kubernetes ResourceQuota
  • 这个节点的实际内存大小

内存超卖

限制可以比请求的实际更高,因此所有限制的总和可以超过节点容量,这被称为超卖,这是虚拟化技术中比较常见的一种实现,但是实际上,如果所有容器使用的内存都比请求的内存多,它可能会耗尽节点中的内存。这通常会导致某些 Pod 死亡以释放一些内存

监控Kubernetes OOM

在Prometheus中使用节点导出器时,有一个名为node_vmstat_oom_kill的指标。跟踪OOM kill发生的时候很重要,但你可能想提前知道这样的事件发生之前的情况。

相反,你可以检查一个进程离Kubernetes限制有多近:

在Prometheus中使用node-expoter时,有一个metric为node_vmstat_oom_kill,在追查OOM被kill时的时候,这个指标很重要,但如果我们希望在事件发生之前就能看到它,可以通过检查进程离Kubernetes Limit的差距多大:

(sum by (namespace,pod,container)
(rate(container_cpu_usage_seconds_total{container!=""}[5m])) / sum by 
(namespace,pod,container)
(kube_pod_container_resource_limits{resource="cpu"})) > 0.8

Kubernetes CPU限制

CPU Throttling是一种当进程即将达到某些资源限制时减慢进程的行为,与内存的情况类似,这些限制可能是:

  • 在容器上设置的Kubernetes Limit。
  • 在命名空间上设置的Kubernetes ResourceQuota。
  • 节点的实际内存大小。

想想下面的类比。我们有一条交通拥堵的高速公路:

  • CPU就是路。
  • 车辆代表了这个过程,其中每辆车都有不同的尺寸。
  • 多通道代表有多个核心。
  • 请求将是一条专用道路,比如自行车道。

CPU限流在这里被表示为交通堵塞: 所有进程都会运行,但是运行的过程会变的缓慢。

Kubernetes中的CPU进程

CPU在Kubernetes中通过共享来处理。每个CPU核心被划分为1024个共享,然后使用Linux内核的cgroups(控制组)特性在运行的所有进程之间进行分配。

如果 CPU 能够处理所有当前的进程,则不需要任何操作。如果进程使用的CPU超过100%,那么就会使用共享。与所有Linux内核一样,Kubernetes使用CFS(完全公平调度器)机制,因此拥有更多共享的进程将获得更多CPU时间。

与内存不同,Kubernetes不会因为CPU限流而杀死pod

可以通过如下命令来检查CPU状态: /sys/fs/cgroup/cpu/cpu.stat

CPU 超卖

正如我们在限制和请求文章中看到的,当我们想要限制进程的资源消耗时,设置限制或请求是很重要的。不过,要注意设置的总请求不要大于实际的CPU大小,因为这意味着每个容器都应该有一定数量的CPU。

监控Kubernetes CPU限流

你可以检查一个进程离Kubernetes的限制有多近:

(sum by (namespace,pod,container)(rate(container_cpu_usage_seconds_total
{container!=""}[5m])) / sum by (namespace,pod,container)
(kube_pod_container_resource_limits{resource="cpu"})) > 0.8

如果我们想要跟踪集群中发生的节流量,cadvisor提供了container_cpu_cfs_throttled_periods_total和container_cpu_cfs_periods_total。有了这两个,您就可以很容易地计算出所有CPU周期内的节流百分比。

最佳实践

小心Limits和requests

Limits 是对节点中的资源设置最大上限的一种方法,但是需要小心配置Limits,因为最终可能导致进程受限或终止。

为驱逐做好准备

通过设置非常低的请求,您可能会认为这将为您的进程授予最小的CPU或内存。但是kubelet将首先驱逐那些使用率高于请求优先的pod,所以你将它们标记为第一个被杀死的!

如果您需要保护特定的Pod免受抢占(当kube-scheduler需要分配一个新的Pod时),请为最重要的进程分配优先级类。

CPU限流是一个无声的敌人

通过设置不切实际的限制或过度提交,您可能没有意识到您的进程正在受到限制,并且性能受到影响。主动监视CPU使用情况,并了解容器和名称空间中的实际限制。

以上就是Kubernetes的Memory溢出和CPU 限流的全部内容,你学会了吗?


版权声明:本站文章,如无说明,均为本站原创,转载请注明文章来源。如有侵权,请联系博主删除。
本文链接:https://www.panziye.com/back/11175.html
喜欢 (0)
请潘老师喝杯Coffee吧!】
分享 (0)
用户头像
发表我的评论
取消评论
表情 贴图 签到 代码

Hi,您需要填写昵称和邮箱!

  • 昵称【必填】
  • 邮箱【必填】
  • 网址【可选】