了解OOM杀手日志

我在Docker容器中运行一些进程,并使用这个容器的内存限制。 有时Docker容器中的某些进程被OOM杀手杀死。 我在syslog文件中看到:

beam.smp invoked oom-killer: gfp_mask=0xd0, order=0, oom_score_adj=0 beam.smp cpuset=/ mems_allowed=0 CPU: 0 PID: 20908 Comm: beam.smp Not tainted 3.13.0-36-generic #63~precise1-Ubuntu Hardware name: Xen HVM domU, BIOS 4.2.amazon 05/23/2014 ffff880192ca6c00 ffff880117ebfbe8 ffffffff817557fe 0000000000000007 ffff8800ea1e9800 ffff880117ebfc38 ffffffff8174b5b9 ffff880100000000 000000d08137dd08 ffff880117ebfc38 ffff88010c05e000 0000000000000000 Call Trace: [<ffffffff817557fe>] dump_stack+0x46/0x58 [<ffffffff8174b5b9>] dump_header+0x7e/0xbd [<ffffffff8174b64f>] oom_kill_process.part.5+0x57/0x2d4 [<ffffffff81075295>] ? has_ns_capability_noaudit+0x15/0x20 [<ffffffff8115b709>] ? oom_badness.part.4+0xa9/0x140 [<ffffffff8115ba27>] oom_kill_process+0x47/0x50 [<ffffffff811bee4c>] mem_cgroup_out_of_memory+0x28c/0x2b0 [<ffffffff811c122b>] mem_cgroup_oom_synchronize+0x23b/0x270 [<ffffffff811c0ac0>] ? memcg_charge_kmem+0xf0/0xf0 [<ffffffff8115be08>] pagefault_out_of_memory+0x18/0x90 [<ffffffff81747e91>] mm_fault_error+0xb9/0xd3 [<ffffffff81766267>] ? __do_page_fault+0x317/0x570 [<ffffffff81766495>] __do_page_fault+0x545/0x570 [<ffffffff8101361d>] ? __switch_to+0x16d/0x4d0 [<ffffffff810a5d3d>] ? set_next_entity+0xad/0xd0 [<ffffffff8175df1e>] ? __schedule+0x38e/0x700 [<ffffffff817664da>] do_page_fault+0x1a/0x70 [<ffffffff81762648>] page_fault+0x28/0x30 Task in /docker/a4d47fb7bbc8a2bbc172bd26085c4509364b1b7eec61439669e08e281b181a0b killed as a result of limit of /docker/a4d47fb7bbc8a2bbc172bd26085c4509364b1b7eec61439669e08e281b181a0b memory: usage 229600kB, limit 262144kB, failcnt 5148 memory+swap: usage 524288kB, limit 524288kB, failcnt 19118 kmem: usage 0kB, limit 18014398509481983kB, failcnt 0 Memory cgroup stats for /docker/a4d47fb7bbc8a2bbc172bd26085c4509364b1b7eec61439669e08e281b181a0b: cache:0KB rss:229600KB rss_huge:8192KB mapped_file:0KB writeback:3336KB swap:294688KB inactive_anon:114980KB active_anon:114620KB inactive_file:0KB active_file:0KB unevictable:0KB [ pid ] uid tgid total_vm rss nr_ptes swapents oom_score_adj name [ 9537] 0 9537 8740 712 21 1041 0 my_init [13097] 0 13097 48 3 3 16 0 runsvdir [13098] 0 13098 42 4 3 19 0 runsv [13100] 0 13100 42 4 3 38 0 runsv [13101] 0 13101 42 4 3 17 0 runsv [13102] 0 13102 42 4 3 4 0 runsv [13103] 0 13103 42 4 3 39 0 runsv [13104] 0 13104 4779 243 15 60 0 cron [13105] 0 13105 8591 601 22 1129 0 ruby [13107] 0 13107 20478 756 43 560 0 syslog-ng [13108] 0 13108 11991 642 28 1422 0 ruby [20826] 0 20826 4467 249 14 63 0 run [20827] 0 20827 1101 144 8 29 0 huobi [20878] 0 20878 3708 172 13 48 0 run_erl [20879] 0 20879 249481 57945 321 72955 0 beam.smp [20969] 0 20969 1846 83 9 27 0 inet_gethost [20970] 0 20970 3431 173 12 33 0 inet_gethost [20977] 0 20977 1101 127 8 25 0 sh [20978] 0 20978 1074 125 8 23 0 memsup [20979] 0 20979 1074 68 7 23 0 cpu_sup [ 5446] 0 5446 8462 217 22 81 0 cron [ 5451] 0 5451 1101 127 8 26 0 sh [ 5453] 0 5453 1078 68 8 22 0 sleep [10898] 0 10898 8462 217 22 81 0 cron [10899] 0 10899 8462 216 22 80 0 cron [10900] 0 10900 1101 127 7 26 0 sh [10901] 0 10901 1101 127 8 25 0 sh [10902] 0 10902 1078 68 7 22 0 sleep [10903] 0 10903 1078 68 8 22 0 sleep Memory cgroup out of memory: Kill process 20911 (beam.smp) score 1001 or sacrifice child Killed process 20977 (sh) total-vm:4404kB, anon-rss:0kB, file-rss:508kB 

我知道beam.smp进程非常积极地消耗内存资源。 所以log beam.smp invoked oom-killer第一行beam.smp invoked oom-killer确实有道理。

但是我对最后两行日志感到困惑。 它表示Kill process 20911 (beam.smp) ,但在这个cgroup里面不存在PID为20911的进程(转储到日志的进程列表)。 最后一行说Killed process 20977 (sh) (这个PID在cgroup中出现)。 我们即将杀死beam.smp ,但最后还是杀了sh 。 这是什么意思?

OOM杀手决定杀死另一个进程。

该消息确实表明:

 Kill process 20911 .... or sacrifice child 

它决定用这个过程产生的shell脚本20977杀死这个孩子。

如果您希望Linux始终vm.oom_kill_allocating_task导致内存不足的任务,请将sysctl vm.oom_kill_allocating_task设置为1。


从内核文档 :

这可以启用或禁用在内存不足情况下杀死OOM触发任务。

如果设置为零,OOM杀手将扫描整个任务列表并根据启发式select一个任务来杀死。 这通常会select一个无赖的内存占用任务,当遇难时释放大量的内存。

如果这被设置为非零,那么OOM杀手简单地杀死触发内存不足情况的任务。 这避免了昂贵的任务列表扫描。

如果select了panic_on_oom,则优先于oom_kill_allocating_task中使用的任何值。

默认值是0。