Linux里的容器被OOM killed的两种情况

生产上遇到过几次容器实例被OOM的现象,总结一下LInux OOM的两种触发条件。我的虚拟机是ubuntu 24.0.4版本,分配4G内存,在我的虚拟机上复现这两种case。

一 宿主机物理内存不够

当linux上所有应用程序的内存需求加起来超出了物理内存(包括 swap)的容量,内核(OOM killer)必须杀掉一些进程才能腾出空间保障系统正常运行。oom_score分数最高的进程在这个时候会被杀掉。

用来每隔一秒分配100MB RSS物理内存的程序

#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>#define BLOCK_SIZE (100*1024*1024)int main(int argc, char **argv)
{int thr, i;char *p1;for (i = 0; ; i++) {p1 = malloc(BLOCK_SIZE);memset(p1, 0x00, BLOCK_SIZE);printf("set to %d Mbytes\n", i * 100);sleep(1);}return 0;
}

Dockerfile

FROM ubuntu:24.04COPY ./mem-alloc/mem_alloc /CMD ["/mem_alloc", "2000"]

Makefile

all: imagemem_alloc: mem-alloc/mem_alloc.cgcc -o mem-alloc/mem_alloc mem-alloc/mem_alloc.c
image: mem_allocdocker build -t registry/mem_alloc:v1 .
clean:rm mem-alloc/mem_alloc -fdocker stop mem_alloc;docker rm mem_alloc;docker rmi registry/mem_alloc:v1

执行sudo make后,启动容器,不指定内存上限,故意让这个docker吃掉所有的宿主机的内存

sudo docker run --privileged -it  registry/mem_alloc:v1 /bin/bash

容器内执行

root@4c81480d3366:/# echo 1 > /sys/fs/cgroup/memory.oom.group 
root@96bd973a3a59:/# ./mem_alloc 1000
set to 0 Mbytes
set to 100 Mbytes
set to 200 Mbytes
set to 300 Mbytes
set to 400 Mbytes
set to 500 Mbytes

观察docker stats 的输出,容器消耗完所有虚拟机的内存后,被杀死
请添加图片描述
执行dmesg

[86949.786621] oom-kill:constraint=CONSTRAINT_NONE,nodemask=(null),cpuset=docker-96bd973a3a598d2fe5dfda4213cbb2ea028b0a4c3922fb50830daa12a9a4ecba.scope,mems_allowed=0,global_oom,task_memcg=/system.slice/docker-96bd973a3a598d2fe5dfda4213cbb2ea028b0a4c3922fb50830daa12a9a4ecba.scope,task=mem_alloc,pid=13545,uid=0
[86949.786647] Out of memory: Killed process 13545 (mem_alloc) total-vm:6556108kB, anon-rss:3656448kB, file-rss:128kB, shmem-rss:0kB, UID:0 pgtables:12968kB oom_score_adj:0
[86949.788874] Tasks in /system.slice/docker-96bd973a3a598d2fe5dfda4213cbb2ea028b0a4c3922fb50830daa12a9a4ecba.scope are going to be killed due to memory.oom.group set
[86949.788889] Out of memory: Killed process 13518 (bash) total-vm:4296kB, anon-rss:0kB, file-rss:0kB, shmem-rss:0kB, UID:0 pgtables:60kB oom_score_adj:0
[86949.789235] Out of memory: Killed process 13545 (mem_alloc) total-vm:6556108kB, anon-rss:3656448kB, file-rss:128kB, shmem-rss:0kB, UID:0 pgtables:12968kB oom_score_adj:0
[86951.427580] docker0: port 1(veth1e6a35b) entered disabled state
[86951.427667] vethce0aa4c: renamed from eth0
[86951.445966] docker0: port 1(veth1e6a35b) entered disabled state
[86951.446626] veth1e6a35b (unregistering): left allmulticast mode
[86951.446705] veth1e6a35b (unregistering): left promiscuous mode
[86951.446707] docker0: port 1(veth1e6a35b) entered disabled state

这个容器实例因为RSS使用了3.6G,宿主机的所有可用物理内存,导致被宿主机killed掉。

K8s配置最佳实践

生产环境的容器的内存的limit和request配置一样,不要超卖,一旦宿主机的物理内存不够,一定会有容器被宿主机kill掉。

二 docker里的进程使用的内存超过了cgroup的限制

容器实例使用的内存如果超过了cgroup(control group)的限制,会被内核直接杀掉

其他不变,容器启动命令增加内存限制的参数-m 2000m --memory-swap 2000m

sudo docker run  -m 2000m --memory-swap 2000m  --privileged -it  registry/mem_alloc:v1 /bin/bash

容器内执行

root@4c81480d3366:/# echo 1 > /sys/fs/cgroup/memory.oom.group 
root@96bd973a3a59:/# ./mem_alloc 1000
set to 0 Mbytes
set to 100 Mbytes
set to 200 Mbytes
set to 300 Mbytes
set to 400 Mbytes
set to 500 Mbytes

观察docker stats 的输出,容器的使用内存达到cgroup的限制后,被杀掉
请添加图片描述
使用dmesg,查看内核日志

[88880.963934] oom-kill:constraint=CONSTRAINT_MEMCG,nodemask=(null),cpuset=docker-38bdd956b75425c816afa4f5d3071bc4b175065cf405414c41a23ebf44e5f2fa.scope,mems_allowed=0,oom_memcg=/system.slice/docker-38bdd956b75425c816afa4f5d3071bc4b175065cf405414c41a23ebf44e5f2fa.scope,task_memcg=/system.slice/docker-38bdd956b75425c816afa4f5d3071bc4b175065cf405414c41a23ebf44e5f2fa.scope,task=mem_alloc,pid=13890,uid=0
[88880.963948] Memory cgroup out of memory: Killed process 13890 (mem_alloc) total-vm:2050332kB, anon-rss:2042752kB, file-rss:128kB, shmem-rss:0kB, UID:0 pgtables:4116kB oom_score_adj:0
[88880.967339] Tasks in /system.slice/docker-38bdd956b75425c816afa4f5d3071bc4b175065cf405414c41a23ebf44e5f2fa.scope are going to be killed due to memory.oom.group set
[88880.967351] Memory cgroup out of memory: Killed process 13859 (bash) total-vm:4296kB, anon-rss:384kB, file-rss:0kB, shmem-rss:0kB, UID:0 pgtables:48kB oom_score_adj:0
[88880.968337] Memory cgroup out of memory: Killed process 13890 (mem_alloc) total-vm:2050332kB, anon-rss:2042752kB, file-rss:128kB, shmem-rss:0kB, UID:0 pgtables:4116kB oom_score_adj:0
[88881.076584] docker0: port 1(veth0cb68cb) entered disabled state
[88881.076763] veth6ef9720: renamed from eth0
[88881.094585] docker0: port 1(veth0cb68cb) entered disabled state
[88881.096610] veth0cb68cb (unregistering): left allmulticast mode
[88881.096714] veth0cb68cb (unregistering): left promiscuous mode
[88881.096717] docker0: port 1(veth0cb68cb) entered disabled state

内核日志的关键词和上面的不一样,Memory cgroup out of memory, 有关键词cgroup

jvm参数配置最佳实践

jvm进程要控制好堆的大小,堆配置的过大,容易导致jvm整体内存超过了容器的限制值,进而被OS kill掉。堆的大小自适应容器的内存大小,建议配置65% 到 75%之间,MaxRAMPercentage和MinRAMPercentage建议配置一样,避免申请或释放内存消耗机器性能。(下面的几个参数在Java 8u191 +之后才支持, 不生效的话注意版本)

-XX:+UseContainerSupport 
-XX:InitialRAMPercentage=70.0  
-XX:MaxRAMPercentage=70.0 
-XX:MinRAMPercentage=70.0 

memory.oom.group 参数说明

/sys/fs/cgroup/memory.oom.group

A read-write single value file which exists on non-root cgroups. The default value is “0”.

Determines whether the cgroup should be treated as an indivisible workload by the OOM killer. If set, all tasks belonging to the cgroup or to its descendants (if the memory cgroup is not a leaf cgroup) are killed together or not at all. This can be used to avoid partial kills to guarantee workload integrity.

如果这个参数设置成1,那么当内存超过cgroup的限制,整个cgroup组里所有进程会被视为一个整体一起杀掉。如果设置成0,当内存不够用的时候,会杀掉cgroup分组里oom_score分数最高的那个进程。
为了实现容器整体被kill掉,上面的两个例子里,/sys/fs/cgroup/memory.oom.group 文件内容都需要手动改成1

参考资料


  1. https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v2.html.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/69260.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Windows本地部署DeepSeek-R1大模型并使用web界面远程交互

文章目录 前言1. 安装Ollama2. 安装DeepSeek-r1模型3. 安装图形化界面3.1 Windows系统安装Docker3.2 Docker部署Open WebUI3.3 添加Deepseek模型 4. 安装内网穿透工具5. 配置固定公网地址 前言 最近爆火的国产AI大模型Deepseek详细大家都不陌生&#xff0c;不过除了在手机上安…

低代码开发与传统开发:未来的技术路线选择

在科技飞速发展的当下&#xff0c;软件开发技术日新月异&#xff0c;低代码开发与传统开发作为两种重要的开发模式&#xff0c;正站在未来技术路线选择的十字路口&#xff0c;引发了众多企业和开发者的关注。它们各自有着独特的优势和适用场景&#xff0c;究竟该如何抉择&#…

二、0-1搭建springboot+vue3前后端分离-登录页面

项目仓库地址&#xff1a;zgw-admin: 从0-1搭建一个springbootvue3的项目&#xff0c;这是源码 本次主要是为了&#xff1a; a.写登录页面 b.element plus组件是否能正常使用 c.页面调用ts是否正常&#xff0c;无参和有参的函数 首页的图片&#xff1a; 页面效果 1、引入…

Spring Task之Cron表达式

&#x1f31f; Spring Task高能预警&#xff1a;你以为的Cron表达式可能都是错的&#xff01;【附实战避坑指南】 开篇暴击&#xff1a;为什么你的定时任务总在凌晨3点翻车&#xff1f; “明明设置了0 0 2 * * ?&#xff0c;为什么任务每天凌晨3点执行&#xff1f;” —— 来…

web-JSON Web Token-CTFHub

前言 在众多的CTF平台当中&#xff0c;作者认为CTFHub对于初学者来说&#xff0c;是入门平台的不二之选。CTFHub通过自己独特的技能树模块&#xff0c;可以帮助初学者来快速入门。具体请看官方介绍&#xff1a;CTFHub。 作者更新了CTFHub系列&#xff0c;希望小伙伴们多多支持…

【FPGA】 MIPS 12条整数指令【2】

目录 实现slt 仿真 代码 完整代码 ID.v DataMem.v define.v EX.v IF.v InstMem.v MEM.v MIPS.v RegFile.v Soc.v soc_tb.v 实现slt 仿真 ori r1,r0,1100h ori r2,r0,0020h ori r3,r0,ff00h ori r4,r0,ffffh addi r5,r0,ffff slt r6,r5,r4 slt r6,r4,r…

C基础寒假练习(6)

一、终端输入行数&#xff0c;打印倒金字塔 #include <stdio.h> int main() {int rows;printf("请输入倒金字塔的行数: ");scanf("%d", &rows);for (int i rows; i > 0; i--) {// 打印空格for (int j 0; j < rows - i; j) {printf(&qu…

【C# 】图像资源的使用

在C#中&#xff0c;图像资源的使用方式方法主要依赖于你所使用的框架和库。以下是几种常见的使用图像资源的方法&#xff1a; Windows Forms 直接加载图像&#xff1a; 使用System.Drawing.Image.FromFile()方法可以直接从文件系统加载图像。 Image image Image.FromFile(&qu…

OpenGL学习笔记(六):Transformations 变换(变换矩阵、坐标系统、GLM库应用)

文章目录 向量变换使用GLM变换&#xff08;缩放、旋转、位移&#xff09;将变换矩阵传递给着色器坐标系统与MVP矩阵三维变换绘制3D立方体 & 深度测试&#xff08;Z-buffer&#xff09;练习1——更多立方体 现在我们已经知道了如何创建一个物体、着色、加入纹理。但它们都还…

OSPF基础(1):工作过程、状态机、更新

OSPF基础 1、技术背景&#xff08;与RIP密不可分&#xff0c;因为RIP中存在的问题&#xff09; RIP中存在最大跳数为15的限制&#xff0c;不能适应大规模组网周期性发送全部路由信息&#xff0c;占用大量的带宽资源以路由收敛速度慢以跳数作为度量值存在路由环路可能性每隔30秒…

python爬虫--简单登录

1&#xff0c;使用flask框架搭建一个简易网站 后端代码app.py from flask import Flask, render_template, request, redirect, url_for, sessionapp Flask(__name__) app.secret_key 123456789 # 用于加密会话数据# 模拟用户数据库 users {user1: {password: password1}…

如何在React中使用Redux进行状态管理?

在现代前端开发中&#xff0c;React已成为构建用户界面的流行选择。然而&#xff0c;随着应用规模的不断增长&#xff0c;管理组件之间的状态变得愈加复杂。为了解决这一问题&#xff0c;Redux 作为一种状态管理工具应运而生。本文将详细介绍如何在React中集成和使用Redux来进行…

HTML中的图片标签详解及路径使用【学术投稿-第五届环境资源与能源工程国际学术会议(ICEREE 2025)】

官网&#xff1a;www.iceree.org 会议时间&#xff1a;2025年2月21-23日 会议地点&#xff1a;中国-昆明 简介 第五届环境资源与能源工程国际学术会议&#xff08;ICEREE 2025&#xff09;将于2025年2月21日至23日在中国昆明隆重举行。主要围绕“能源工程和能源技术”、“环…

react的antd表格自定义图标

将原版的加号换成箭头 自定义图标 安装图标包&#xff1a; npm install --save ant-design/icons 引入&#xff1a; import { RightOutlined, DownOutlined } from ant-design/icons; 参数是一个函数 <Table columns{columns} dataSource{data} indentSize{20}expandIc…

【回溯+剪枝】单词搜索,你能用递归解决吗?

文章目录 79. 单词搜索解题思路&#xff1a;回溯&#xff08;深搜&#xff09; 剪枝 79. 单词搜索 79. 单词搜索 ​ 给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 …

Redis企业开发实战(二)——点评项目之商户缓存查询

目录 一、缓存介绍 二、缓存更新策略 三、如何保证redis与数据库一致性 1.解决方案概述 2.双写策略 3.双删策略 3.1延迟双删的目的 4.数据重要程度划分 四、缓存穿透 (一)缓存穿透解决方案 (二)缓存穿透示意图 五、缓存雪崩 (一)缓存雪崩解决方案 (二)缓存雪崩…

maven如何不把依赖的jar打包到同一个jar?

spring boot项目打jar包部署&#xff1a; 经过以下步骤&#xff0c; 最终会形成maven依赖的多个jar&#xff08;包括lib下添加的&#xff09;、 我们编写的程序代码打成一个jar&#xff0c;将程序jar与 依赖jar分开&#xff0c;便于管理&#xff1a; success&#xff1a; 最终…

Mac 部署Ollama + OpenWebUI完全指南

文章目录 &#x1f4bb; 环境说明&#x1f6e0;️ Ollama安装配置1. 安装[Ollama](https://github.com/ollama/ollama)2. 启动Ollama3. 模型存储位置4. 配置 Ollama &#x1f310; OpenWebUI部署1. 安装Docker2. 部署[OpenWebUI](https://www.openwebui.com/)&#xff08;可视化…

一次报警了解:direct path read、enq: KO - fast object checkpoint

背景 今天突然接到订单超时报警&#xff0c;数据库的状态确实惊出一身冷汗&#xff0c;查看系统日志正常&#xff0c;数据库日志正常&#xff0c;load 1-3之间&#xff0c;Session 连接200左右&#xff0c;未发现有负载。于是生成一个ASH报告&#xff0c;感觉比平时要慢很多&am…

Flink2支持提交StreamGraph到Flink集群

最近研究Flink源码的时候&#xff0c;发现Flink已经支持提交StreamGraph到集群了&#xff0c;替换掉了原来的提交JobGraph。 新增ExecutionPlan接口&#xff0c;将JobGraph和StreamGraph作为实现。 Flink集群Dispatcher也进行了修改&#xff0c;从JobGraph改成了接口Executio…