简体   繁体   English

限制 Docker 容器上的内存不起作用

[英]Limit memory on a Docker container doesn't work

I am running the last version of Docker on top of Ubuntu 13.04 (Raring Ringtail):我在 Ubuntu 13.04(Raring Ringtail)上运行最新版本的 Docker:

root@docker:~# docker version
Client version: 0.6.6
Go version (client): go1.2rc3
Git commit (client): 6d42040
Server version: 0.6.6
Git commit (server): 6d42040
Go version (server): go1.2rc3
Last stable version: 0.6.6

But when I start the container,但是当我启动容器时,

root@docker:~# docker run -m=1524288 -i  -t ubuntu /bin/bash
root@7b09f638871a:/# free -m
             total       used       free     shared    buffers     cached
Mem:          1992        608       1383          0         30        341
-/+ buffers/cache:        237       1755
Swap:         2047          0       2047

I don't see any limiting from any kind, and my kernel has the cgroups memory limit enabled:我没有看到任何类型的限制,并且我的内核启用了 cgroups 内存限制:

kernel /boot/vmlinuz-3.8.0-33-generic ro console=tty0 root=/dev/xvda1 cgroup_enable=memory swapaccount=1

What obvious thing am I missing here?我在这里错过了什么明显的东西?

free won't show it as this is enforced via cgroups. free不会显示它,因为这是通过 cgroups 强制执行的。 Instead on the host (outside the container) you can check using /sysfs and the cgroup memory:相反,在主机(容器外)上,您可以使用/sysfs和 cgroup 内存进行检查:

vagrant@precise64:~$ docker run -m=524288 -d  -t busybox sleep 3600
f03a017b174f
vagrant@precise64:~$ cat /sys/fs/cgroup/memory/lxc/f03a017b174ff1022e0f46bc1b307658c2d96ffef1dd97e7c1929a4ca61ab80f//memory.limit_in_bytes
524288

To see it run out of memory, you can run something that will use more memory than you allocate - for example:要查看内存不足,您可以运行一些使用比分配更多内存的东西 - 例如:

docker run -m=524288 -d -p 8000:8000 -t ubuntu:12.10  /usr/bin/python3 -m http.server
8480df1d2d5d
vagrant@precise64:~$ docker ps | grep 0f742445f839
vagrant@precise64:~$ docker ps -a | grep 0f742445f839
0f742445f839        ubuntu:12.10        /usr/bin/python3 -m    16 seconds ago       Exit 137                                blue_pig

In dmesg you should see the container and process killed:dmesg您应该看到容器和进程被杀死:

[  583.447974] Pid: 1954, comm: python3 Tainted: GF          O 3.8.0-33-generic #48~precise1-Ubuntu
[  583.447980] Call Trace:
[  583.447998]  [<ffffffff816df13a>] dump_header+0x83/0xbb
[  583.448108]  [<ffffffff816df1c7>] oom_kill_process.part.6+0x55/0x2cf
[  583.448124]  [<ffffffff81067265>] ? has_ns_capability_noaudit+0x15/0x20
[  583.448137]  [<ffffffff81191cc1>] ? mem_cgroup_iter+0x1b1/0x200
[  583.448150]  [<ffffffff8113893d>] oom_kill_process+0x4d/0x50
[  583.448171]  [<ffffffff816e1cf5>] mem_cgroup_out_of_memory+0x1f6/0x241
[  583.448187]  [<ffffffff816e1e7f>] mem_cgroup_handle_oom+0x13f/0x24a
[  583.448200]  [<ffffffff8119000d>] ? mem_cgroup_margin+0xad/0xb0
[  583.448212]  [<ffffffff811949d0>] ? mem_cgroup_charge_common+0xa0/0xa0
[  583.448224]  [<ffffffff81193ff3>] mem_cgroup_do_charge+0x143/0x170
[  583.448236]  [<ffffffff81194125>] __mem_cgroup_try_charge+0x105/0x350
[  583.448249]  [<ffffffff81194987>] mem_cgroup_charge_common+0x57/0xa0
[  583.448261]  [<ffffffff8119517a>] mem_cgroup_newpage_charge+0x2a/0x30
[  583.448275]  [<ffffffff8115b4d3>] do_anonymous_page.isra.35+0xa3/0x2f0
[  583.448288]  [<ffffffff8115f759>] handle_pte_fault+0x209/0x230
[  583.448301]  [<ffffffff81160bb0>] handle_mm_fault+0x2a0/0x3e0
[  583.448320]  [<ffffffff816f844f>] __do_page_fault+0x1af/0x560
[  583.448341]  [<ffffffffa02b0a80>] ? vfsub_read_u+0x30/0x40 [aufs]
[  583.448358]  [<ffffffffa02ba3a7>] ? aufs_read+0x107/0x140 [aufs]
[  583.448371]  [<ffffffff8119bb50>] ? vfs_read+0xb0/0x180
[  583.448384]  [<ffffffff816f880e>] do_page_fault+0xe/0x10
[  583.448396]  [<ffffffff816f4bd8>] page_fault+0x28/0x30
[  583.448405] Task in /lxc/0f742445f8397ee7928c56bcd5c05ac29dcc6747c6d1c3bdda80d8e688fae949 killed as a result of limit of /lxc/0f742445f8397ee7928c56bcd5c05ac29dcc6747c6d1c3bdda80d8e688fae949
[  583.448412] memory: usage 416kB, limit 512kB, failcnt 342

I am linking to this nice post on stressing container memory usage.我正在链接到这篇关于强调容器内存使用的好文章 Here's the summary, modified a bit to work for Docker instead of generic LXC:这是摘要,稍微修改以适用于 Docker 而不是通用的 LXC:

Launch a container with a memory limit:启动一个有内存限制的容器:

$ sudo docker run -m 512M -it ubuntu /bin/bash
root# apt-get update && apt-get install -y build-essential

Create a file, foo.c , inside the container with the following:在容器内创建一个文件foo.c ,内容如下:

#include <stdlib.h>
#include <stdio.h>

int main(void) {
    int i;
    for (i=0; i<65536; i++) {
        char *q = malloc(65536);
        printf ("Malloced: %ld\n", 65536*i);
    }
    sleep(9999999);
}

Compile the file:编译文件:

gcc -o foo foo.c

Open a new terminal to monitor the container memory usage:打开一个新的终端来监控容器内存使用情况:

$ cd /sys/fs/cgroup/memory/lxc/{{containerID}}
$ while true; do echo -n "Mem Usage (mb): " && expr `cat memory.usage_in_bytes` / 1024 / 1024; echo -n "Mem+swap Usage (mb): " && expr `cat memory.limit_in_bytes` / 1024 / 1024; sleep 1; done

Start the memory consumption in the container启动容器中的内存消耗

$ ./foo

Now watch your container max out.现在注意你的容器最大化。 Note: When you're out of memory, malloc's start to fail, but otherwise the container is left alone.注意:当内存不足时,malloc 会开始失败,否则容器就会被搁置。 Normally the software inside the container will crash due to the failing mallocs, but software that is resilient will continue to operate.通常容器内的软件会因为 malloc 失败而崩溃,但有弹性的软件会继续运行。

Final note: Docker's -m flag does not count swap and RAM separately.最后一点:Docker 的-m标志不会分别计算交换和 RAM。 If you use -m 512M then some of that 512 will be swap, not RAM.如果您使用-m 512M那么其中一些 512 将被交换,而不是 RAM。 If you want only RAM you will need to use LXC options directly (which means you will need to run Docker with the LXC execution driver instead of libcontainer):如果您只需要 RAM,则需要直接使用 LXC 选项(这意味着您需要使用 LXC 执行驱动程序而不是 libcontainer 运行 Docker):

# Same as docker -m 512m
sudo docker run --lxc-conf="lxc.cgroup.memory.limit_in_bytes=512M" -it ubuntu /bin/bash

# Set total to equal maximum RAM (for example, don't use swap)
sudo docker run --lxc-conf="lxc.cgroup.memory.max_usage_in_bytes=512M" --lxc-conf="lxc.cgroup.memory.limit_in_bytes=512M" -it ubuntu /bin/bash

There is a notable difference between using swap as part of the total and not - with swap the foo program above reaching ~450 MB quickly and then slowly consumes the remainder, whereas with only RAM it immediately jumps to 511 MB for me.使用交换作为总数的一部分与不使用交换之间存在显着差异 - 交换上面的 foo 程序快速达到约 450 MB,然后缓慢消耗剩余部分,而只有 RAM 时它立即跳到 511 MB 对我来说。 With swap the container's memory consumption is marked at ~60 MB as soon as I enter the container - this is basically the swap being counted as "usage".使用交换,一旦我进入容器,容器的内存消耗就会被标记为 ~60 MB - 这基本上是将交换计算为“使用”。 Without swap my memory usage is less than 10 MB when I enter the container.当我进入容器时,如果没有交换,我的内存使用量少于 10 MB。

运行命令: docker stats以查看您指定的应用于容器的内存限制。

If you are using a newer version of Docker, then the place to look for that information is /sys/fs/cgroup/memory/docker/<container_id>/memory.limit_in_bytes :如果您使用的是较新版本的 Docker,那么查找该信息的位置是/sys/fs/cgroup/memory/docker/<container_id>/memory.limit_in_bytes

docker run --memory="198m" redis
docker ps --no-trunc` # to get the container long_id
313105b341eed869bcc355c4b3903b2ede2606a8f1b7154e64f913113db8b44a
cat /sys/fs/cgroup/memory/docker/313105b341eed869bcc355c4b3903b2ede2606a8f1b7154e64f913113db8b44a/memory.limit_in_bytes
207618048 # in bytes

The -m switch does work (setting hard memory limit), and accepts human-readable k|m|g memory units. -m开关确实有效(设置硬内存限制),并接受人类可读的k|m|g内存单元。

You can use docker inspect to verify it has desired effect on the " Memory" key:您可以使用docker inspect来验证它对“ Memory"键是否具有预期效果:

$ docker run --rm -d --name ubuntu -m 8g ubuntu:focal && docker inspect ubuntu | grep Memory
            "Memory": 8589934592,
            "KernelMemory": 0,
            "KernelMemoryTCP": 0,
            "MemoryReservation": 0,
            "MemorySwap": -1,
            "MemorySwappiness": null,

$ docker run --rm -d --name ubuntu -m 16g ubuntu:focal && docker inspect ubuntu | grep Memory
            "Memory": 17179869184,
            "KernelMemory": 0,
            "KernelMemoryTCP": 0,
            "MemoryReservation": 0,
            "MemorySwap": -1,
            "MemorySwappiness": null,

You can also set burstable limits, ie memory requests / reservations / guaranteed minimums (that won't protect the host from crashing, but will protect the containerized app from running out of memory, until the physical limit is reached):您还可以设置突发限制,即内存请求/保留/保证最小值(这不会保护主机免于崩溃,但会保护容器化应用程序不会耗尽内存,直到达到物理限制):

$ docker run --rm -d --name ubuntu --memory-reservation 16g ubuntu:focal && docker inspect ubuntu | grep Memory
            "Memory": 0,
            "KernelMemory": 0,
            "KernelMemoryTCP": 0,
            "MemoryReservation": 17179869184,
            "MemorySwap": 0,
            "MemorySwappiness": null,

Debian GNU/Linux 10 (buster) Debian GNU/Linux 10(破坏者)

Docker 4.1.1码头工人 4.1.1

$ docker run -m 4g -it b5e1eb14396b /bin/bash 


$ cat /sys/fs/cgroup/memory/memory.limit_in_bytes
4294967296
#4.294967296 Gigabytes

But I was still running out of memory when installing packages and these commands show small (default?) memory.但是在安装软件包时我的内存仍然不足,并且这些命令显示内存很小(默认?)。 Swap didn't seem to work either.交换似乎也不起作用。

#inside container
$ free
              total        used        free      shared  buff/cache   available
Mem:        2033396      203060      784600       87472     1045736     1560928

# outside container
$ docker stats
CONTAINER ID   NAME             CPU %     MEM USAGE / LIMIT     MEM %     NET I/O         BLOCK I/O     PIDS
18bd88308490   gallant_easley   0.00%     1.395MiB / 1.939GiB   0.07%     1.62kB / 384B   1.95MB / 0B   1

Ughh.呃。 I forgot about those [user-friendly] resource limits in the Docker UI.我忘记了 Docker UI 中的那些 [用户友好] 资源限制。 It should warn you if you try to exceed them.如果您试图超过它们,它应该警告您。

在此处输入图片说明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM