Bootstrap

Kubernetes Pod OOM 和 CPU 限制

Kubernetes OOM and CPU Throttling | Sysdig

介绍

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

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

通过限制和请求,您可以配置 pod 如何分配内存和 CPU 资源,以防止资源匮乏并调整云成本。

如果节点没有足够的资源, Pod 可能会通过抢占或节点压力被驱逐。当进程出现内存不足 (OOM) 时,它会被终止,因为它没有所需的资源。如果 CPU 消耗高于实际限制,进程将开始受到限制。

但是,如何主动监控 Kubernetes Pods 与 OOM 和 CPU 节流的接近程度?

 

Kubernetes OOM

Pod 中的每个容器都需要内存才能运行。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

此退出代码 137 表示该进程使用的内存超过允许量,必须终止。

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

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

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

Kubernetes OOM 图

内存过量使用

限制可能高于请求,因此所有限制的总和可能高于节点容量。这称为过度使用,非常常见。实际上,如果所有容器使用的内存多于请求的内存,则可能会耗尽节点中的内存。这通常会导致一些 pod 死亡,以释放一些内存。

监控 Kubernetes OOM

在 Prometheus 中使用节点导出器时,有一个名为的指标node_vmstat_oom_kill。跟踪 OOM 终止发生的时间很重要,但您可能希望在事件发生之前提前了解并了解此类事件。

相反,您可以检查某个进程与 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

Kubernetes CPU 限制

CPU 限制是一种当进程即将达到某些资源限制时速度减慢的行为。

与内存情况类似,这些限制可能是:

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

想想下面的类比。我们有一条高速公路,车流量很大,其中:

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

这里的节流表现为交通堵塞:最终,所有进程都会运行,但一切都会变慢。

Kubernetes 中的 CPU 进程

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

Kubernetes 共享 CPU 系统

如果 CPU 可以处理所有当前进程,则无需采取任何措施。如果进程占用的 CPU 超过 100%,则需要分配份额。与任何 Linux 内核一样,Kubernetes 使用 CFS(完全公平调度程序)机制,因此拥有更多份额的进程将获得更多的 CPU 时间。

与内存不同,Kubernetes 不会因为限制而杀死 Pod。

Kubernetes 节流图

您可以在 /sys/fs/cgroup/cpu/cpu.stat 中检查 CPU 统计信息

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_totalcontainer_cpu_cfs_periods_total。通过这两个,您可以轻松计算所有 CPU 周期中的节流百分比。

最佳实践

注意限制和要求

限制是设置节点中资源最大上限的一种方法,但需要谨慎处理,因为最终可能会导致进程被限制或终止。

做好驱逐准备

通过设置非常低的请求,您可能会认为这将为您的进程授予最低限度的 CPU 或内存。但kubelet首先会驱逐那些使用率高于请求的 Pod,因此您将这些 Pod 标记为最先被杀死的!

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

节流是一个无声的敌人

通过设置不切实际的限制或过度使用,您可能不会意识到您的进程受到限制,并且性能受到影响。主动监控您的 CPU 使用率并了解容器和命名空间中的实际限制。

 

总结

这是有关 Kubernetes CPU 和内存资源管理的速查表。它总结了当前文章以及同一系列中的以下文章:

;