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

参考

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐