我在 docker 容器内运行一些进程,并且我对此容器使用内存限制。有时 docker 容器内的某些进程会被 OOM killer 杀死。我在 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
进程非常消耗内存资源。所以日志的第一行beam.smp invoked oom-killer
确实有意义。
但是我对日志的最后两行感到困惑。它说Kill process 20911 (beam.smp)
,但是 PID 为 20911 的进程不存在于此 cgroup 中(进程列表也转储到日志中)。最后一行说Killed process 20977 (sh)
(并且此 PID 存在于 cgroup 中)。我们原本要杀死beam.smp
,但最终还是杀死了sh
。这是什么意思?
答案1
OOM 终止程序决定终止另一个进程。
该消息确实指出:
Kill process 20911 .... or sacrifice child
它决定杀死 pid 为 20977 的子进程(该子进程是由该进程生成的一个 shell 脚本)。
如果您希望 Linux 始终终止导致内存不足的任务,请将 sysctl 设置vm.oom_kill_allocating_task
为 1。
来自内核文档:
这将启用或禁用在内存不足的情况下终止触发 OOM 的任务。
如果将其设置为零,OOM 终止程序将扫描整个任务列表并根据启发式方法选择一个任务进行终止。这通常会选择一个占用大量内存的恶意任务,该任务在终止时会释放大量内存。
如果将其设置为非零,OOM 终止程序将直接终止触发内存不足情况的任务。这样可以避免昂贵的任务列表扫描。
如果选择了 panic_on_oom,它优先于 oom_kill_allocating_task 中使用的任何值。
默认值为 0。