Dokcer 容器如何限制内存
我们知道docker使用Linux内核的 CGroup 来实现限制容器的资源使用(CPU,内存), 然而 CGroup 功能是到2007年才加入 Linux2.6.24 内核的,一些可以从运行时环境收集信息的应用程序再 CGroup 之前就已经存在了。所以在容器中执行 top
free
ps
等一些命令其实是显示了容器所在宿主机上的信息。
容器的资源限制可以在 docker run 中通过配置来实现,但是这依赖系统内核的支持,可以通过 docker info 来查看,如果有一下输出:
WARNING: No swap limit support
那就请查看你系统的相关文档来开启。
Memory 资源
在 Linux 系统中,系统内核为了保障系统运行,但系统中剩余的内存不足以维持系统的正常运行,系统内核就会根据 OOM priority 来 kill 掉进程以释放内存,这就会引发 OOME 或 Out of Memory Exception 错误。Docker 会尝试着调整 Docker daemon 的 OOM priority 来尽可能地避免被内核 kill 掉,但是容器的进程就没有这个能力了。
Option | Description |
---|---|
-m, --memory="" | 内存限制,格式是数字加单位,单位可以为 b,k,m,g。最小为 4M |
--memory-swap="" | 容器的内存能 swap 到硬盘的大小,只有在设置了 -m 的情况下,才有意义; 这个值的大小= memory + swap,更多详情请见下方。 |
--memory-reservation | 内存的软性限制。格式同上 |
--oom-kill-disable | 是否阻止 OOM killer 杀死容器,默认不阻止。 |
--oom-score-adj | 容器被 OOM killer 杀死的优先级,范围是[-1000, 1000],默认为 0 |
--memory-swappiness | 用于设置容器的虚拟内存控制行为。值为 0~100 之间的整数 |
--kernel-memory | 核心内存限制。格式同上,最小为 4M |
--memory-swap
配置详情:
--memory-swap
设置的前提是要先设置了 --memeory
, 一下的讨论均是假设于设置了有效的 memory,而且宿主机的内核必须开启了支持 swap limit 的设置;
- 如果
--memory-swap
为 0 或者不设置,swap = 2 * memory 的大小。比如,docker rum -m 2G
设置了一个容器最大允许使用的内存是 2G,那么 swap 最大能使用的大小为 4G。 - 如果
--memory-swap
为 1, 则不允许容器使用 swap。
Docker容器中Java应用的内存如何分配
Docker Java 应用的内存应该是 JVM 的 Heaper内存 + Metaspace的内存。
默认在没有通过 JAVA_OPTS
指定 JVM maximum heap size 的情况下,它默认为操作系统内存的1/4。
自从docker 1.7版本之后,Docker 把容器的 local cgroup 以只读的方式挂在到容器的内部文件系统上,这样我们可以在容器内部读取这个限制的值, 我们可以通过修改容器的启动脚本来实现自动计算:
#!/bin/bash
# local cgroup
limit_in_bytes=$(cat /sys/fs/cgroup/memory/memory.limit_in_bytes)
limit_in_megabytes=$(expr $limit_in_bytes \/ 1048576)
heap_size=$(expr $limit_in_megabytes - $RESERVED_MEGABYTES)
JAVA_OPTS="-Xmx${heap_size}m $JAVA_OPTS"
java $JAVA_OPTS -jar xxx.jar
- 另外, 从 Java9 开始, 在没有通过
JAVA_OPTS
指定 JVM maximum heap size 的情况下,默认为容器启动时指定的--memory
1/4 的大小。详情见:https://blogs.oracle.com/java-platform-group/java-se-support-for-docker-cpu-and-memory-limits
网友评论