工作学习笔记-oom killer详解

本文详细介绍了Linux操作系统中的OOM Killer机制,当系统内存不足时如何选择并终止内存消耗过多的进程。内容涵盖OOM Killer的工作原理、选择进程的依据、实战案例以及常见GFP内存分配掩码的解析。通过对oom_adj、oom_score_adj和oom_score的分析,帮助理解哪些进程可能被杀死。
摘要由CSDN通过智能技术生成


前言

本篇文章一起探讨下oom-killer相关问题


一、oom-killer是什么?

在 Linux 操作系统中,OOM Killer(Out-Of-Memory Killer)是一个内核机制,用于在系统内存不足时选择并终止消耗过多内存的进程,以便释放内存并保持系统的正常运行。
当系统内存不足以满足进程的需求时,Linux 内核会试图通过交换部分内存页到交换空间(swap space)或者使用页面回收技术(比如删除长时间不活动的页面)来释放内存。然而,如果这些方法仍然无法满足系统的内存需求,内核就会触发 OOM Killer。

二、oom杀死进程的原理

OOM Killer 的工作原理是扫描系统中的进程,评估它们各自的内存使用情况,并选择一个最适合终止的进程来释放内存。通常情况下,OOM Killer 会选择那些消耗大量内存但对系统整体影响较小的进程作为终止目标。然而,并非所有进程都能被终止,因为有些进程可能是关键的系统进程或者用户态进程,终止它们可能会导致系统崩溃或数据丢失。
在系统触发 OOM Killer 后,内核会记录相关信息,如触发 OOM 条件的进程、OOM Killer 杀死的进程等,以便后续分析和故障排除。

三、什么进程会被oom杀死

每个进程的/proc/PID/oom_adj、oom_score_adj和oom_score记录着进程分数
oom_adj、oom_score_adj和oom_score:用来控制进程打分(分数越高,就先杀谁)

四、实战

在这里插入图片描述
如上如flb-pipline进程就被干掉了
后面的gfp-mask代表表示进程请求内存时使用的 GFP(Get Free Pages)掩码。GFP 掩码用于指定内核在内存分配时应该遵循的一系列规则和属性。不同的 GFP 掩码代表了不同的内存分配类型和属性。以下是常见的 GFP 掩码类型及其含义:

GFP_KERNEL:该掩码用于普通的内核内存分配请求。当进程需要从内核中分配内存时,通常会使用该掩码。这种分配可以等待,因此内核可能会尝试通过回收内存或交换内存页来满足请求。

GFP_ATOMIC:该掩码用于请求不可阻塞的、原子级别的内存分配。这种分配是非阻塞的,因此如果没有可用内存,内核将立即返回失败,而不是等待。通常用于处理中断上下文或者在内核关键路径上。

GFP_DMA:该掩码用于请求可用于 DMA(直接内存访问)的内存。DMA 内存通常要求物理地址连续,因此需要使用特定的内存分配方法。

GFP_HIGHUSER:该掩码用于请求高优先级用户内存。这种分配通常用于用户空间应用程序,例如驱动程序或用户态工具,这些应用程序需要较低的延迟和可预测的内存分配性能。

GFP_NOIO:该掩码用于请求不会导致 IO 操作的内存分配。这种分配通常用于处理 IO 系统调用或者在不能阻塞 IO 的上下文中。

GFP_NOFS:该掩码用于请求不会引发文件系统操作的内存分配。这种分配通常用于在文件系统代码中防止递归调用导致的死锁。

GFP_NOFAIL:该掩码用于请求不会失败的内存分配。如果无法分配所需内存,则内核会尝试使用 OOM Killer 终止其他进程以释放内存。

GFP_THISNODE:该掩码用于请求在当前 NUMA 节点上分配内存。

这些是常见的 GFP 掩码类型,每种类型都代表了不同的内存分配需求和属性。在触发 OOM Killer 后,系统日志中的 gfp_mask 将指示触发 OOM 条件的进程使用的 GFP 掩码,以及它们的内存分配属性。


order= 代表内核在尝试进行内存分配时所请求的页面数量的对数。这个参数通常用于跟踪触发 OOM 的具体内存分配请求的大小。

在 Linux 内核中,内存分配通常以页为单位进行,每个页的大小取决于系统的配置,通常为 4KB 或 8KB。当内核尝试进行内存分配时,它通常会请求一定数量的连续页面来满足请求。order= 参数指定了请求页面数量的对数,即请求页面的数量等于 2 的 order 次方。

例如,如果系统日志中记录了 order=2,则表示内核尝试进行的内存分配请求的页面数量为 2 的平方,即 4 个页面。这意味着内核试图一次性分配连续的 4 个页面来满足特定的内存分配需求


在这里插入图片描述
oom后有calltrace和meminfo信息,用来查看具体哪个部分用了较多的内存
在这里插入图片描述
从上图我们可以看出这些信息:
1、这也不是系统级别的oom,而是cgroup级别的
2、这个k8s的cgroup组限制了内存使用为204800,这个组内进程的rss 用了203168,cache 1148…(后面还有各种类型内存占用我就不打了)
3、最终结果就是他们进程内存占用超过了他们设置的内存上限204800
综上所述,这个就需要从应用侧来看,进程占用这么多合不合理,合理的话就要调大cgroup memory.limit限制,从系统角度来说,这个cgroup组都不是系统管理的,应该是又k8s应用方设置的,基本都是k8s上层做了限制,然后对应的管理软件在自己建立了cgroup组管理。
在这里插入图片描述
在这里插入图片描述

总结

oom相关问题持续更新,以后有相关oom问题会继续记录在这里

Docker提供了一个选项来设置容器不被操作系统杀死,该选项称为"oom-kill-disable"。oom-kill-disable是一个用于禁用内存超限时杀死容器的选项。 当容器内存使用量超出其可用内存的限制时,操作系统会触发一个内存超限(OOM)事件。通常情况下,为了从OOM事件中恢复,操作系统会选择杀死占用内存较大的进程(包括容器)来释放内存资源。 如果我们想禁止Docker容器在OOM事件中被杀死,我们可以使用"oom-kill-disable"选项。这个选项可以在运行容器时通过命令行或Docker Compose文件进行设置,具体的使用方法如下: 1. 在使用命令行运行容器时,添加"--oom-kill-disable"选项,例如: ``` docker run --oom-kill-disable <容器名称或ID> ``` 2. 在Docker Compose文件中,为容器配置"oom_kill_disable"字段并设置为true,例如: ```yaml services: myservice: oom_kill_disable: true ``` 注意,禁用容器的OOM事件可能导致主机操作系统的整体性能下降,甚至会影响到其他容器的正常运行。因此,在使用"oom-kill-disable"选项时需要仔细评估容器内存使用及主机资源的情况,确保系统的稳定性和可用性。 最后,需要注意的是,对于大多数情况来说,允许操作系统根据OOM事件决定杀死容器是合理的做法,因为这有助于保持系统的可用性和可靠性,并防止整个系统由于单个容器的内存消耗过大而崩溃。所以,在设置"oom-kill-disable"选项时,需要慎重考虑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值