一文搞懂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 。

比如:

yaml 复制代码
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的差距多大:

vbnet 复制代码
(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的限制有多近:

vbnet 复制代码
(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使用情况,并了解容器和名称空间中的实际限制

相关推荐
2401_857622666 小时前
SpringBoot框架下校园资料库的构建与优化
spring boot·后端·php
2402_857589366 小时前
“衣依”服装销售平台:Spring Boot框架的设计与实现
java·spring boot·后端
哎呦没8 小时前
大学生就业招聘:Spring Boot系统的架构分析
java·spring boot·后端
_.Switch8 小时前
Python Web 应用中的 API 网关集成与优化
开发语言·前端·后端·python·架构·log4j
杨哥带你写代码9 小时前
足球青训俱乐部管理:Spring Boot技术驱动
java·spring boot·后端
AskHarries10 小时前
读《show your work》的一点感悟
后端
A尘埃10 小时前
SpringBoot的数据访问
java·spring boot·后端
yang-230710 小时前
端口冲突的解决方案以及SpringBoot自动检测可用端口demo
java·spring boot·后端
Marst Code10 小时前
(Django)初步使用
后端·python·django
代码之光_198010 小时前
SpringBoot校园资料分享平台:设计与实现
java·spring boot·后端