Ubuntu 限制Docker容器上的内存';行不通

Ubuntu 限制Docker容器上的内存';行不通,ubuntu,docker,cgroups,Ubuntu,Docker,Cgroups,我正在Ubuntu13.04(Raring Ringtail)之上运行Docker的最新版本: 但当我启动容器时 root@docker:~# docker run -m=1524288 -i -t ubuntu /bin/bash root@7b09f638871a:/# free -m total used free shared buffers cached Mem: 1992 608

我正在Ubuntu13.04(Raring Ringtail)之上运行Docker的最新版本:

但当我启动容器时

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
我看不到任何类型的限制,我的内核启用了cgroups内存限制:

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

我在这里遗漏了什么明显的东西?

free
不会显示它,因为这是通过cgroup强制执行的。相反,您可以在主机(容器外部)上使用
/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
要查看内存耗尽情况,您可以运行比分配的内存要多的程序,例如:

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
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
[583.447974]Pid:1954,comm:python3污染:gfo3.8.0-33-generic#48~precise1ubuntu
[583.447980]呼叫跟踪:
[583.447998][]转储头+0x83/0xbb
[583.448108][]oom_kill_过程。第6部分+0x55/0x2cf
[  583.448124]  [] ? 具有音频+0x15/0x20的功能
[  583.448137]  [] ? 内存组iter+0x1b1/0x200
[583.448150][]oom\u kill\u进程+0x4d/0x50
[583.448171][]内存组出内存+0x1f6/0x241
[583.448187][]内存组句柄+0x13f/0x24a
[  583.448200]  [] ? mem_cgroup_边距+0xad/0xb0
[  583.448212]  [] ? mem_cgroup_charge_common+0xa0/0xa0
[583.448224][]成员组费用+0x143/0x170
[583.448236][]成员组尝试费用+0x105/0x350
[583.448249][]成员-集团-费用-公用+0x57/0xa0
[583.448261][]成员组新页面费用+0x2a/0x30
[583.448275][]匿名页面。isra.35+0xa3/0x2f0
[583.448288][]处理私人故障+0x209/0x230
[583.448301][]处理mm故障+0x2a0/0x3e0
[583.448320][]页面错误+0x1af/0x560
[  583.448341]  [] ? vfsub_read_+0x30/0x40[aufs]
[  583.448358]  [] ? aufs_读取+0x107/0x140[aufs]
[  583.448371]  [] ? vfs_读取+0xb0/0x180
[583.448384][]执行页面错误+0xe/0x10
[583.448396][]页面错误+0x28/0x30
[583.448405]由于/lxc/0f742445f8397ee7928c56bcd5c05ac29dcc6747c6d1c3bdda80d8e688fae949的限制,/lxc/0f742445f8397ee7928c56bcd5c05ac29dcc6747c6d1c3bdda80d8e688fae949中的任务被终止
[583.448412]内存:使用量416kB,限制512kB,失败342
我将链接到这篇文章,强调容器内存的使用。以下是总结,对Docker进行了一些修改,以代替通用LXC:

启动具有内存限制的容器:

$ sudo docker run -m 512M -it ubuntu /bin/bash
root# apt-get update && apt-get install -y build-essential
使用以下内容在容器内创建文件
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);
}
打开新终端以监视容器内存使用情况:

$ 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
启动容器中的内存消耗

$ ./foo
现在注意你的容器。注意:当内存不足时,malloc将开始失败,但在其他情况下,容器将不受影响。通常情况下,容器内的软件会因mallocs故障而崩溃,但具有弹性的软件将继续运行

最后注意:Docker的
-m
标志不单独计算交换和RAM。如果您使用
-m 512M
,那么其中的一些512将是交换的,而不是RAM。如果只需要RAM,则需要直接使用LXC选项(这意味着您需要使用LXC执行驱动程序而不是libcontainer来运行Docker):


使用swap作为总容量的一部分与不使用swap之间有一个显著的区别——使用swap时,foo程序的容量快速达到~450MB,然后慢慢消耗剩余的内存,而对于我来说,使用RAM时,它会立即跳到511MB。使用swap,当我进入容器时,容器的内存消耗被标记为~60 MB——这基本上是被计算为“使用”的交换。如果不进行交换,当我进入容器时,我的内存使用量小于10 MB。

如果您使用的是较新版本的Docker,则查找该信息的位置是
/sys/fs/cgroup/memory/Docker//memory。以字节为单位进行限制

docker run --memory="198m" redis
docker ps --no-trunc` # to get the container long_id
313105b341eed869bcc355c4b3903b2ede2606a8f1b7154e64f913113db8b44a

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

开关
-m
工作(设置硬内存限制),并接受人类可读的
k | m | g
内存单元

您可以使用
docker inspect
来验证它对“
内存”
键是否具有所需的效果:

$ 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,
您还可以设置burstable限制,即内存请求/保留/保证的最小值(这不会保护主机不崩溃,但会保护容器化应用程序不耗尽内存,直到达到物理限制):


谢谢,现在我明白了;因此,最好的方法是检查cgroup内存以查看当前使用情况。您可以在此处阅读有关
cgroup
内存度量的更多信息,尤其是
memory.stat
伪文件。非常感谢。如果上述方法对您不起作用,那么在Ubuntu上配置它会有更多的细节,这可能是因为您的Docker使用了“本机”
libcontainer
驱动程序(现在是默认的)而不是
lxc
。在这种情况下,,容器内存统计和限制位于
/sys/fs/cgroup/memory/docker//memory.stat
/sys/fs/cgroup/memory/docker//memory.limit_in_bytes
docker stats
还提供了一个交互式界面,显示了限制和当前使用的容器资源,我正试图收集和docker工作。但是,Collectd会发布整个系统(主机)的RAM使用情况,而不是docker受限内存。我想知道这个选项是否有帮助,但是在运行docker时,如果使用
--lxc conf=“lxc.cgroup.memory.limit_in_bytes=512M”
我最终得到了
标志,但没有定义:--lxc conf
错误。知道如何解决这个问题吗?答案很好!,顺便说一句,我想你错过了前面代码示例行中的
run
cimmand
sudo docker*run*-m 512M-it ubuntu/bin/bash
Thank@gsalgadotoedo fixed。接下来,我看到了虚拟服务器上的停靠应用程序与裸金属盒之间的一些有趣区别。例如,OOM将杀死运行Java的虚拟化ubuntu服务器中的Java
# 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
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
$ 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,
$ 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,