天天看点

Docker 资源限制之内存

<a href="http://people.seas.harvard.edu/~apw/stress/" target="_blank">stress</a>

通过如下 Dockerfile 构建简单的测试镜像

<a href="https://docs.docker.com/engine/reference/run/#runtime-constraints-on-resources" target="_blank">Runtime constraints on resources</a>

目前 Docker 支持内存资源限制选项

Whether to disable OOM Killer for the container or not.

Kernel memory limit (format: <code>&lt;number&gt;[&lt;unit&gt;]</code>). Number is a positive integer. Unit can be one of <code>b</code>, <code>k</code>, <code>m</code>, or <code>g</code>. Minimum is 4M.

kernel memory 没有特殊需求,则无需额外设置

Memory soft limit (format: <code>&lt;number&gt;[&lt;unit&gt;]</code>). Number is a positive integer. Unit can be one of <code>b</code>, <code>k</code>, <code>m</code>, or <code>g</code>.

Size of <code>/dev/shm</code>. The format is <code>&lt;number&gt;&lt;unit&gt;</code>. number must be greater than 0. Unit is optional and can be <code>b</code> (bytes), <code>k</code> (kilobytes), <code>m</code> (megabytes), or <code>g</code>(gigabytes). If you omit the unit, the system uses bytes. If you omit the size entirely, the system uses <code>64m</code>.

根据实际需求设置,这里不作过多的介绍

Tune a container’s memory swappiness behavior. Accepts an integer between 0 and 100.

Total memory limit (memory + swap, format: <code>&lt;number&gt;[&lt;unit&gt;]</code>). Number is a positive integer. Unit can be one of <code>b</code>, <code>k</code>, <code>m</code>, or <code>g</code>.

Memory limit (format: <code>&lt;number&gt;[&lt;unit&gt;]</code>). Number is a positive integer. Unit can be one of <code>b</code>, <code>k</code>, <code>m</code>, or <code>g</code>. Minimum is 4M.

<code>-m</code>, <code>--memory=""</code>

<code>--memory-swap=""</code>

<code>--memory-swappiness=""</code>

<code>--shm-size=""</code>

<code>--memory-reservation=""</code>

<code>--kernel-memory=""</code>

<code>--oom-kill-disable=false</code>

默认启动一个 container,对于容器的内存是没有任何限制的。

<code>docker run -it --rm -m 100M --memory-swap -1 ubuntu-stress:latest /bin/bash</code>

指定限制内存大小并且设置 memory-swap 值为 -1,表示容器程序使用内存受限,而 swap 空间使用不受限制(宿主 swap 支持使用多少则容器即可使用多少。如果 <code>--memory-swap</code> 设置小于 <code>--memory</code>则设置不生效,使用默认设置)。

使用 <code>docker stats</code> 查看当前容器内存资源使用:

通过 <code>top</code> 实时监控 stress 进程内存占用:

也可以通过如下命令获取 stress 进程的 swap 占用:

<code>docker run -it --rm -m 100M ubuntu-stress:latest /bin/bash</code>

按照官方文档的理解,如果指定 <code>-m</code> 内存限制时不添加 <code>--memory-swap</code> 选项,则表示容器中程序可以使用 100M 内存和 100M swap 内存。默认情况下,<code>--memory-swap</code> 会被设置成 memory 的 2倍。

We set memory limit(300M) only, this means the processes in the container can use 300M memory and 300M swap memory, by default, the total virtual memory size <code>--memory-swap</code> will be set as double of memory, in this case, memory + swap would be 2*300M, so processes can use 300M swap memory as well.

如果按照以上方式运行容器提示如下信息:

To enable memory and swap on system using GNU GRUB (GNU GRand Unified Bootloader), do the following:

<code>$ sudo update-grub</code>

<code>GRUB_CMDLINE_LINUX="cgroup_enable=memory swapaccount=1"</code>

Log into Ubuntu as a user with sudo privileges.

Edit the /etc/default/grub file.

Set the GRUB_CMDLINE_LINUX value as follows:

Save and close the file.

Update GRUB.

Reboot your system.

<code>docker stats</code> 和 top 获取资源占用情况:

<code>docker run -it -m 100M --memory-swap 400M ubuntu-stress:latest /bin/bash</code>

根据实际测试可以理解,<code>-m</code> 为物理内存上限,而 <code>--memory-swap</code> 则是 memory + swap 之和,当压测值是 <code>--memory-swap</code> 上限时,则容器中的进程会被直接 OOM kill。

swappiness 可以认为是宿主 <code>/proc/sys/vm/swappiness</code> 设定:

<code>--memory-swappiness=0</code> 表示禁用容器 swap 功能(这点不同于宿主机,宿主机 swappiness 设置为 0 也不保证 swap 不会被使用):

<code>docker run -it --rm -m 100M --memory-swappiness=0 ubuntu-stress:latest /bin/bash</code>

<code>--memory-reservation ...</code> 选项可以理解为内存的软限制。如果不设置 <code>-m</code> 选项,那么容器使用内存可以理解为是不受限的。按照官方的说法,memory reservation 设置可以确保容器不会长时间占用大量内存。

但是如果是以下的这种没有对容器作任何资源限制的情况,添加 <code>--oom-kill-disable</code> 选项就比较 危险 了:

因为此时容器内存没有限制,并且不会被 oom kill,此时系统则会 kill 系统进程用于释放内存。

Kernel memory is fundamentally different than user memory as kernel memory can’t be swapped out. The inability to swap makes it possible for the container to block system services by consuming too much kernel memory. Kernel memory includes:

stack pages

slab pages

sockets memory pressure

tcp memory pressure

这里直接引用 Docker 官方介绍,如果无特殊需求,kernel-memory 一般无需设置,这里不作过多说明。

<code>github.com/opencontainers/runc/libcontainer/cgroups/fs/memory.go</code>

附测试:

查看宿主对应 container cgroup 对应值:

本文转自 zbill 51CTO博客,原文链接:http://blog.opskumu.com/docker-memory-limit.html,如需转载请自行联系原作者