Docker避坑指南:为啥应用使用内存没有超,却还是被OOM?

上一篇 Docker内核技术原理(八)之Cgroup内存限制 文章中介绍了,如何通过cgroup现在容器内存占用。但在生产环境中却遇到一个问题:容器的内存占用RSS没有超,但却出现了OOM。如下图所示,最上面的绿线代码总的内存限制是7G,但RSS的才使用不到4G便出现了OOM,导致容器重启。

Docker避坑指南:为啥应用使用内存没有超,却还是被OOM?

细心的童鞋可能发现,我这里说应用内存占用使用的是RSS,但实际上,应用的使用的内存占用,除了RSS以外,操作系统内核态维护的pagecache也算到了应用总的内存占用了。关于RSS请参考我之前发的:如何查看一个进程的内存占用。关于page cache我后续文章再详聊,这里只要知道它是操作系统为了加速磁盘读写做了一层缓存。当容器里面的应用程序读写文件的时候,就会先读写缓存,然后再异步读写磁盘。

其实我们可以通过之前文章中介绍的cgroup监控分别查看cache和rss的内存占用。

#cat memory.stat     
cache 4194889728  
rss 44 

由于cache的是内核维护的,如果同一个文件被不同的程序读取了两次,只会缓存一次,那么这里就存在一个问题,这个缓存的内存占用算谁的?这里内核做了一个简单处理,谁先第一次读,就算谁的,这样先读文件的程序就会吃亏点,后读文件的进程就可以搭车蹭饭。但这只是统计的问题,无伤大雅。

Docker避坑指南:为啥应用使用内存没有超,却还是被OOM?

问题的关键在于,这部分内存的管理并非是cgroup控制的,我们知道page cache通过水位线、脏页比例结合LRU控制内存的申请和释放行为,并不受cgroup控制。当cgroup内存总限制的比较小的时候,而此时物理机内存比较充裕,会导致大量page cache驻留在内存中,应用可用的内存就变得非常少,很容易导致OOM。RSS内存不足的时候,也无法自动通过cgroup释放page cache。

我们后来在自己的生成环境做了两个设置才暂时解决了这个问题,第一是调低了水位线,控制page cache的内存占用,第二是每天凌晨的时候,会执行一次drop cache的动作,这个动作会对性能造成影响,建议在业务低峰期执行。具体命令如下:

# sync; echo 1 > /proc/sys/vm/drop_caches

在内核4.2版本后,增加了per-cgroup的脏页平衡,在进行脏页平衡时,同时计算全局的脏页比例和进程所在cgroup的内存脏页比例,只要超过其中的任意一个,就需要进行脏页回写。如下图所示:

Docker避坑指南:为啥应用使用内存没有超,却还是被OOM?

展开阅读全文

页面更新:2024-03-30

标签:内存   无伤大雅   水位   缓存   内核   磁盘   容器   进程   比例   操作系统   动作   环境   文件   指南   程序   文章   科技

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight 2020-2024 All Rights Reserved. Powered By 71396.com 闽ICP备11008920号-4
闽公网安备35020302034903号

Top