cgroup 内存泄露问题排查记录
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了cgroup 内存泄露问题排查记录相关的知识,希望对你有一定的参考价值。
参考技术A 出现内存泄漏的主机为集群机器,运行时间约5天,内存使用超90%,其上运行 集群管理软件 和 docker并执行测试脚本反复启停容器。长时间运行后,集群主机内存占用逐渐增加,出现应用 OOM 现象。
而实际查看时发现主机内存总占用高,但应用实际占用内存低或未见显著异常。
可以看到内存占用 83.6% ,而实际top显示的内存占用最高也才 0.6% 没有占用内存过高的应用。
内存占用除了用户应用占用还有内核占用,遂查看内核内存占用。
使用linux文件系统接口查看
可以看到占用超高的项目为 slab 内核占用:
继续查看内核详细占用,按照缓存大小进行排序
可以看到此处:
kmalloc-2048,kmalloc-4096,kernfs_node_cache,kmalloc-1024,kmalloc-192,kmalloc-512 均占用较高,对比了正常主机,已经严重超过正常值。
如果是内核缓存过高则可以尝试进行内核缓存释放:
但执行上述操作后,内存占用依旧无显著下降,也符合上面看到的 SUnreclaim: 2447108 kB //slab 不可回收内存大小 。这部分内存不能被释放。
kmalloc 为内核进行分配的内存,参考价值较大的为 kernfs_node_cache 占用高,遂搜索该项是作何作用。
很明显,该现象为内核占用严重超标,于是在搜索时加入了 memory leak 关键字,很快发现了该 Issues docker-run --memory slab cache leak on centos7
该 issue 表示 centos7 在反复运行 docker run --rm --memory 1g hello-world 时存在明显的内核内存占用升高,且无法被释放。且现象和当前现象一致。
最终指向内kernel c group内存泄露问题 slab leak causing a crash when using kmem control group
大致原因是在 3.10 内核上如果使用了 kmem limit 参数,会导致cgroup回收时无法释放部分已分配内存。至于更深入的了解,还需要其他时间,先解决目前的问题。
原因大概确定,为了再次确定这个问题,如果能够通过上述手段复则可以确定是该问题。
在一台仅运行docker的机器上执行上述语句,查看 slab 内存占用,可以看见内存占用明显上升。且最终表现和已有环境上的问题一致,总内存占用高,用户态内存占用低,内核内存占用高且无法被释放。
既然是内核问题,且知道了明确复现路径,则可以通过两种方式进行解决:
最终,进过测试后,选择了更换内核版本,将使用 Ubuntu 18.04 作为新的操作系统。
Linux内核使用层次化内存管理的方法,每一层解决不同的问题,从下至上的关键部分如下:
slab是Linux操作系统的一种内存分配机制。其工作是针对一些经常分配并释放的对象,如进程描述符等,这些对象的大小一般比较小,如果直接采用伙伴系统来进行分配和释放,不仅会造成大量的内碎片,而且处理速度也太慢。而slab分配器是基于对象进行管理的,相同类型的对象归为一类(如进程描述符就是一类),每当要申请这样一个对象,slab分配器就从一个slab列表中分配一个这样大小的单元出去,而当要释放时,将其重新保存在该列表中,而不是直接返回给伙伴系统,从而避免这些内碎片。slab分配器并不丢弃已分配的对象,而是释放并把它们保存在内存中。当以后又要请求新的对象时,就可以从内存直接获取而不用重复初始化。
Slab导致的占用内存过高,Slab可以对可回收缓存手动释放,操作如下:
其中drop_caches的4个值有如下含义:
#工程经验分享# 内存泄露排查
这里简单记录下ubuntu下进行程序内存消耗的检测,以及对于内存泄露的排查方法。
//获取系统当前可用内存
int GetSysMemInfo()
int mem_free = -1; //空闲的内存 = 总内存 - 使用了的内存
int mem_total = -1; //当前系统可用总内存
int mem_buffers = -1; //缓存区的内存大小
int mem_cached = -1; //缓存区的内存大小
char name[20];
FILE *fp;
char buf1[128], buf2[128], buf3[128], buf4[128], buf5[128];
int buff_len = 128;
fp = fopen("/proc/meminfo", "r");
if(fp == NULL)
printf("GetSysMemInfo() error! file not exist\\n");
return -1;
if(NULL == fgets(buf1, buff_len, fp) ||
NULL == fgets(buf2, buff_len, fp) ||
NULL == fgets(buf3, buff_len, fp) ||
NULL == fgets(buf4, buff_len, fp) ||
NULL == fgets(buf5, buff_len, fp))
printf("GetSysMemInfo() error! fail to read!\\n");
fclose(fp);
return -1;
fclose(fp);
sscanf(buf1, "%s%d", name, &
以上是关于cgroup 内存泄露问题排查记录的主要内容,如果未能解决你的问题,请参考以下文章