Kubernetes Pod OOMKilled诊断
介绍
OOMKilled
错误表示容器或pod
已被终止,因为它使用的内存多于分配的内存。OOMKilled
,通常称为Exit Code 137
,是一种源自Linux
的错误。OOM
(Out of Memory Manager
)是Linux
系统上的一种工具,可以按进程跟踪内存使用情况。如果系统即将耗尽内存,OOM Killer
将启动并开始杀死进程,以释放内存并避免崩溃。OOM Killer
的目的是通过杀死尽可能少的进程来释放尽可能多的RAM
。Kubernetes
允许pod
限制其容器在主机上可以使用的资源量。Pod
可以设置内存限制,即容器允许使用的最大内存量,以及内存请求,即容器应该消耗的最小内存量。
Kubernetes存在两种导致Pod OOMKilled的场景:
-
Container Limit Reached
- 如果容器使用的内存超过其内存限制,则容器将以
OOMKilled
状态终止。
- 如果容器使用的内存超过其内存限制,则容器将以
-
Limit Overcommit
- 如果所有容器或节点上所有
Pod
的总内存使用量超过某个阈值,则可能会终止一个或多个Pod
。
- 如果所有容器或节点上所有
OOMKilled:Container Limit Reached
- 这是迄今为止在
pod
中可能发生的最基本的内存错误。与Limit Overcommit
错误会影响节点上的RAM
总量不同,如果正常达到Container Limit
,它只会影响一个pod
。当Kubernetes
发现一个pod
使用的内存超过了配置的限制时(即超过了资源申请的Limit),该pod
将被杀死并显示错误OOMKilled — Container Limit Reached
。 - 在大多数情况下,这会导致容器死亡,一个
Pod
变得不健康,并且Kubernetes
重新启动该Pod
。发生这种情况时,请查看应用程序日志以了解为什么pod
使用的内存超出了预期。这可能是由于各种因素造成的,包括流量增加或长期运行的Kubernetes
任务使用了比平时更多的内存。 - 如果在整个查询过程中发现程序按预期运行但只需要额外的内存来执行,可能需要增加请求和限制值。
- 额外补充一点,Kubernetes中的livenessProbe如果探活失败也会触发Pod被杀死。
OOMKilled:Limit Overcommit
- 当
pod
限制的总和大于节点上的可用内存时,可能会发生OOMKilled
:Limit Overcommit
错误。Kubernetes
不会分配需要比节点可用RAM
更多的pod
。另一方面,Limit可能高于Request。因此,所有Limit的总和可能超过节点容量。这被称为Limit Overcommit(过度承诺),即超卖,这是一种非常常见的情况。 - 实际上,如果所有容器消耗的内存都比Request的多,那么节点的内存就会被耗尽。释放一些内存经常会导致一些
pod
死亡。 所以一个拥有8 GB
内存的节点,Kubernetes
可能会运行8
个容器,内存Request值为1 GB
。如果这些容器的内存Limit为1.5 GB
,则某些pod
的使用量可能会超过最小值,从而导致节点内存不足并强制杀死某些pod
。
诊断
-
通过kubectl describe pod [name]可以查看pod死亡的具体原因。
-
查看
pod
的最近历史事件,并尝试找出触发OOMKilled
错误的原因,因为只有两个常见原因:- 由于容器 限制,该
pod
已终止。 pod
由于节点上的过度使用而终止。
- 由于容器 限制,该
解决
如果 Pod 由于容器限制而终止
- 检查您的应用程序是否真的需要更多内存。如果应用程序面临增加的负载,它可能需要比最初提供的更多的内存。在这种情况下,请在
pod
规范中增加容器的内存限制以纠正错误。 如果内存使用量意外增加并且似乎与应用程序需求无关,则应用程序可能会遇到内存泄漏。在这种情况下,调试应用程序并找到内存泄漏的来源。增加应用程序中的内存限制将消耗更多资源。
如果 Pod 因节点过度使用而终止
- 如果
Pod
的内存请求值小于节点上可用的内存,则允许Pod
在节点上调度,这可能导致过度使用。您需要确定Kubernetes
为何杀死pod
,然后调整限制值和内存请求以确保节点没有过度使用。 - 您需要持续监控您的环境,了解
pod
和容器的内存行为,并检查您的设置以全面诊断和解决Kubernetes
内存问题。