K8S OOM killer机制

当kubelet没来得及触发pod驱逐,使得节点内存耗尽时,将触发节点上的OOM killer机制;

Linux上有个机制叫OOM killer(Out Of Memory killer),这个机制会在系统内存耗尽的情况下发挥作用,即根据一定的算法规则,选择性的杀死一些进程,以释放部分内存,让系统继续稳定运行。

如何选择杀死哪个进程

当发生oomkill时,OOM killer给进程打分,得到oom_score,然后优先把oom_score最大的进程先杀死;

oom_score怎么计算获得呢?oom_score=oom_score_adj+进程内存占用大小;

而oom_score_adj则是可以人工给每个进程设置的,从而让用户通过设置进程的oom_score_adj值来影响OOM killer杀死进程的选择;

当oom_score_adj的值设置为-1000时,表示该进程将不会被OOM killer杀死,但如果设置的值不是-1000,那这个进程还是会参与打分,会受oom_score_adj以及进程内存占用大小的影响,需要注意的是,即使oom_score_adj的值设置的很小,比如-999,但当你的进程占用内存很大时,该进程同样有很大的概率会被杀死;

pod中容器进程的oom_score_adj

  • 对于Guaranteed级别的pod,其oom_score_adj的值被设置为-998
  • 对于Best-Effort级别的pod,其oom_score_adj的值被设置为1000
  • 对于Burstable级别的pod,其oom_score_adj的取值为2到999

怎么避免OOM Killer杀死某个业务进程?

  1. 将进程oom_score_adj的值设置为-1000;
  2. 关闭OOM killer机制;
设置oom_score_adj

在Linux系统中,oom_score_adj是一个文件,其路径通常位于/proc/[pid]/oom_score_adj,其中[pid]是进程的ID。通过修改这个文件,可以调整特定进程的OOM(Out of Memory)killer评分。这个评分影响OOM killer在选择哪个进程杀死时的决策。oom_score_adj的值范围从-1000到1000,负值会降低进程被OOM killer选中的概率,而正值则会增加。

在Kubernetes环境中,通常不需要手动设置oom_score_adj,因为kubelet会自动为容器设置适当的值,基于Pod的QoS(服务质量)等级。但是,如果你需要手动设置或调整容器内进程的oom_score_adj值,可以通过以下方法:

1. 直接在容器内设置

如果你有权限访问容器内部,可以直接在容器内修改oom_score_adj文件。例如,要为容器内的某个进程设置oom_score_adj值为500,可以执行以下命令:

复制代码
echo 500 > /proc/[pid]/oom_score_adj

替换[pid]为实际的进程ID。

2. 使用Security Context设置

在Kubernetes中,可以通过Pod的Security Context来设置特定的安全选项,包括oom_score_adj。以下是一个示例,展示如何在Pod定义中设置oom_score_adj

复制代码
apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  securityContext:
    oomScoreAdj: 500
  containers:
  - name: mycontainer
    image: myimage

在这个示例中,oomScoreAdj设置为500,这将应用于Pod内的所有容器。

3. 使用Node Feature Discovery

对于更复杂的场景,比如需要根据节点特性动态设置oom_score_adj,可以使用Node Feature Discovery项目。这个项目可以帮助你根据节点的硬件特性来设置特定的参数。

注意事项

  • 修改oom_score_adj可能会影响系统的稳定性,因为过高的值会增加进程被OOM killer选中的风险。
  • 在生产环境中,建议谨慎使用,并充分测试以确保不会对系统稳定性造成负面影响。
  • Kubernetes的自动oom_score_adj设置是基于Pod的QoS等级的,通常不需要手动干预。
关闭OOM killer机制

在Linux系统中,OOM(Out of Memory)killer是一个保护机制,用于在系统内存不足时自动选择并终止消耗内存最多的进程,以防止系统因内存耗尽而完全崩溃。尽管在某些情况下,您可能想要关闭这个机制,但请注意,这样做会增加系统因内存不足而变得不稳定或崩溃的风险。

如果您确实需要临时或永久地关闭OOM killer,可以通过以下方法:

1. 临时关闭OOM killer

可以通过向/proc/sys/vm/panic_on_oom文件写入值0来临时关闭OOM killer:

复制代码
echo 0 > /proc/sys/vm/panic_on_oom

这个设置在系统重启后会恢复默认值。

2. 永久关闭OOM killer

要永久关闭OOM killer,您需要编辑/etc/sysctl.conf文件(或对应的发行版配置文件),并添加或修改以下行:

复制代码
vm.panic_on_oom = 0

然后,应用更改:

复制代码
sysctl -p

这将使更改永久生效,即使在系统重启后。

3. 通过启动参数关闭

也可以在Linux内核启动参数中添加panic_on_oom=0来关闭OOM killer。这通常在/etc/default/grub(对于使用GRUB的系统)或相应的启动配置文件中设置。修改后,需要更新GRUB配置并重启系统:

复制代码
echo 'kernel_param="panic_on_oom=0"' >> /etc/default/grub
update-grub
reboot

注意事项

  • 关闭OOM killer可能会导致系统在内存不足时变得不稳定或无法预测,因为没有任何机制来自动终止进程以释放内存。
  • 在某些情况下,如实时或嵌入式系统,可能需要关闭OOM killer以避免意外的进程终止。
  • 在大多数服务器和桌面环境中,建议保持OOM killer启用,因为它是保护系统免受内存耗尽影响的重要机制。
相关推荐
李匠20243 小时前
C++GO语言微服务之Dockerfile && docker-compose②
c++·容器
斤斤计较4 小时前
Docker 环境安装(2025最新版)
运维·docker·容器
小锋学长生活大爆炸4 小时前
【教程】Docker方式本地部署Overleaf
运维·docker·容器
Hfc.4 小时前
ubuntu20.04系统搭建k8s1.28集群-docker作为容器运行时
ubuntu·kubernetes
欧先生^_^4 小时前
Docker 的各种网络模式
网络·docker·容器
开源架构师4 小时前
JVM 与云原生的完美融合:引领技术潮流
jvm·微服务·云原生·性能优化·serverless·内存管理·容器化
掘金者说4 小时前
docker系列-DockerDesktop报错信息(Windows Hypervisor is not present)
运维·docker·容器
金刚猿8 小时前
openfeign 拦截器实现微服务上下文打通
微服务·云原生·架构
lcw_lance8 小时前
技术中台-核心技术介绍(微服务、云原生、DevOps等)
微服务·云原生·devops
alden_ygq11 小时前
Kubernetes Horizontal Pod Autosscaler(HPA)核心机制解析
云原生·容器·kubernetes