今天遇到一个cgroup
资源限制时,内存限制不起作用的问题。一开始,对进程的cgroup
设置最大内存限制为10M
,但运行了几分钟以后,内存明显飙上去了,甚至达到了20多M。
情景还原
在memory.limit_in_bytes
中设置如下:10485760
表示的是字节数,也就是等于 1024 * 1024 * 10 = 10M
。
运行一段时间后,查看实际使用的内存,memory.usage_in_bytes
文件中数值如下:
可以看到,确实拿捏得死死的,看起来似乎内存限制成功了,没有什么问题。
可是当使用top
命令去查看的时候,却发现已经内存消耗已高达23M
左右,这明显不正常。
使用前台监控界面查看,得到的是同样的结果:
可见,虽然设置了cgroup
,而且看起来似乎是生效了,但实际上并没有限制住。
问题排查
因为该程序的资源限制是利用agent
代理程序去做的,并非人为去操作,所以一开始怀疑该进程没有加入cgroup
资源限制策略,查看之后排除了这一可能性。
第一步查到进程PID以及其相应的线程ID,如下所示:
然后查看tasks
里面加入的进程号,如下:
可以看到,该进程所有的进程和线程号都被加入到了cgroup
中。因此,并不是这个引起的。
然后就想到会不会是使用了swap
内存,可以看到,8G的swap
内存已经被使用了24M
,看起来有点像。
为了验证这一猜想,我把进程先给停掉了,然后查看swap
内存使用情况:
可以看到,flow
进程停掉之后,swap
内存一下子从24M
降到了20K
,看样子就是这个东西搞的鬼。
于是我查看了一下memory.swappiness
,这个数值居然达到了30,看来是这个问题没跑了。
问题解决
知道了问题所在,解决也就比较简单了。首先第一步,把memory.swappiness
设为0
。
$ echo 0 > memory.swappiness
然后重新启动进程,这次成功了,当内存刚刚达到10M,直接就被kill
掉了。
但实际上,我并不希望这个进程就如此简单粗暴的被杀掉,考虑到memory.oom_control
可以设置内存达到限制后的处理措施,oom_kill_disable
为0
代表内存超过限制就杀掉进程,oom_kill_disable
为1
则代表继续等待,当有内存释放时,继续申请内存。总而言之,就是不会把进程杀掉。
所以,将oom_kill_disable
设置为1
后重启程序,该问题得以解决。
总结
cgroup
是Linux
系统内核提供的一种资源限制的策略,使用起来十分方便。鼎鼎大名的Docker
容器就是基于此技术,平时工作中对这种技术缺乏钻研和积累,只知道简单的使用,并没有深入研究每个参数到底代表什么,其内部原理又是什么,所以才有了遇到这种问题耗时耗力的情况。
比如memory.swappiness
中从数值代表什么意思,为啥设置为0
之后cgroup
就起作用了?原来的30
又代表什么?
通过查资料后,了解到memory.swappiness
中的数值其实并不是确切的数值,而是代表了进程使用swap
空间的一个权重,该数值范围从0-100
。100
表示积极使用swap
,0
表示优先使用内存。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。