Kla*_*ger 6 memory out-of-memory docker
我写了一个简短的java程序来分配内存:
package com.company;
import java.util.ArrayList;
import java.util.List;
public class Main {
public static final int SIZE_NATIVE_LONG_IN_BYTE = 8;
public static void main(String[] args) {
Integer memoryConsumptionInMiB = Integer.parseInt(args[0]);
List<long[][]> foo = new ArrayList<long[][]>();
int i = 0;
while (true) {
System.out.println(i++);
foo.add(new long[(1024 / SIZE_NATIVE_LONG_IN_BYTE * 1024)][memoryConsumptionInMiB]);
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后我尝试在具有几个不同参数的 docker 容器中运行它:
这就是我运行程序的方式(如果是 3):
(编辑:上传了上述类准备好的图像)
docker run -it --oom-kill-disable -m 512m kazesberger/alpine-java-memory-tester java -classpath . com.company.Main 10 (~Megabytes allocated per iteration)
Run Code Online (Sandbox Code Playgroud)
我的期望是:
实际结果:
所以你看,我的实际目标并不是真正压制 oomKiller 实现其目的。我的目标是让容器内的进程无法分配它们不允许的内存。
先决条件/版本: swapoff -a
docker --version Docker 版本 17.11.0-ce-rc4,内部版本 587f1f0
docker run -it kazesberger/alpine-java-memory-tester java -version openjdk 版本“1.8.0_111-internal”
你的期望是不正确的。--oom-kill-disable不禁用虚拟内存过量使用,如果无法分配请求的页面,则会导致malloc失败。mmap相反,该选项映射到通过 sysfs ( ) 公开的cgroup v1 功能/sys/fs/cgroup/memory/docker/<id>/memory.oom_control,并导致请求超出限制的内存的任务被阻塞,直到内存被释放或限制发生变化。
--oom-kill-disable需要 cgroup v1。因此,第一个要求是您的 docker 安装使用 cgroup v1:
$ docker system info | grep -i Cg
Cgroup Driver: cgroupfs
Cgroup Version: 1
Run Code Online (Sandbox Code Playgroud)
如果是这样的话,--oom-kill-disable应该可以使用。您可以确认 cgroup 选项是由 docker 使用 sysfs 设置的:
$ cat /sys/fs/cgroup/memory/docker/<id>/memory.oom_control
oom_kill_disable 1
under_oom 1
oom_kill 0
Run Code Online (Sandbox Code Playgroud)
如果oom_kill_disable未设置,则说明您的 docker 版本未能设置该选项。
under_oom表示已达到限制并且任务正在等待可用内存。
proc 文件系统可用于确认任务确实在等待可用内存:
$ cat /proc/<pid>/task/<tid>/stack
[<0>] __switch_to+0xbc/0xd4
[<0>] mem_cgroup_oom_synchronize+0xf0/0x158
[<0>] pagefault_out_of_memory+0x44/0x1b8
[<0>] do_page_fault+0x254/0x388
[<0>] do_translation_fault+0x54/0x74
[<0>] do_mem_abort+0x58/0xb4
[<0>] el0_ia+0x54/0x68
[<0>] el0_sync_handler+0x15c/0x1c4
[<0>] el0_sync+0x180/0x1c0
Run Code Online (Sandbox Code Playgroud)
在我的测试安装(Docker 版本 20.10.12,构建 e91ed57,Linux 5.10.76)中,我通过更新强制 docker 使用 cgroup v1,settings.json如下所示:
{
"deprecatedCgroupv1": true
}
Run Code Online (Sandbox Code Playgroud)
使用 cgroup v2,启动容器会触发以下警告:
WARNING: Your kernel does not support OomKillDisable. OomKillDisable discarded.
Run Code Online (Sandbox Code Playgroud)
cgroup v2 不提供oom_kill_disable等效项。
您想要的是 cgroup 级别的行为vm.overcommit_memory = 2(或0作为妥协)。在主机级别进行设置以禁用过度使用会导致您预期的行为:
$ docker run -it -m 512m test java -Xms32g -Xmx32g Main
OpenJDK 64-Bit Server VM warning: INFO: os::commit_memory(0x0000fff785400000, 11453202432, 0) failed; error='Not enough space' (errno=12)
#
# There is insufficient memory for the Java Runtime Environment to continue.
# Native memory allocation (mmap) failed to map 11453202432 bytes for committing reserved memory.
# An error report file with more information is saved as:
# //hs_err_pid1.log
Run Code Online (Sandbox Code Playgroud)
不幸的是,据我所知,截至目前该设施还不存在。
| 归档时间: |
|
| 查看次数: |
840 次 |
| 最近记录: |