Ограничение памяти на контейнере Docker не работает
Я использую последнюю версию Docker поверх Ubuntu 13.04 (Raring Ringtail):
[email protected]:~# 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
Но когда я запускаю контейнер,
[email protected]:~# docker run -m=1524288 -i -t ubuntu /bin/bash
[email protected]:/# 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
Какую очевидную вещь я здесь упускаю?
Ответы
Ответ 1
free
не будет показывать это, так как это выполняется через cgroups. Вместо этого на хосте (вне контейнера) вы можете проверить, используя /sysfs
и память cgroup:
[email protected]:~$ docker run -m=524288 -d -t busybox sleep 3600
f03a017b174f
[email protected]:~$ 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
[email protected]:~$ docker ps | grep 0f742445f839
[email protected]:~$ 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
Ответ 2
Я ссылаюсь на этот хороший пост, посвященный использованию памяти контейнера. Вот резюме, немного измененное для работы с 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);
}
Скомпилируйте файл:
gcc -o foo foo.c
Откройте новый терминал для контроля использования памяти контейнера:
$ 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 начинает отказывать, но в противном случае контейнер остается один. Обычно программное обеспечение внутри контейнера падает из-за сбойных malloc, но программное обеспечение, которое устойчиво, продолжает работать.
Последнее замечание: флаг Docker -m
не учитывает обмен и ОЗУ отдельно. Если вы используете -m 512M
то часть этого 512 будет подкачкой, а не RAM. Если вам нужна только оперативная память, вам нужно будет использовать параметры LXC напрямую (что означает, что вам нужно будет запустить Docker с драйвером выполнения LXC вместо libcontainer):
# 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
Существует заметная разница между использованием подкачки как части общего и не - с программой swap foo выше, достигающей ~ 450 МБ, быстро, а затем медленно потребляющей остаток, тогда как при использовании только ОЗУ для меня она сразу же возрастает до 511 МБ. При свопе потребление памяти в контейнере отмечается на уровне ~ 60 МБ, как только я вхожу в контейнер - это, по сути, своп, который считается "использованием". Без подкачки мое использование памяти составляет менее 10 МБ при входе в контейнер.
Ответ 3
Если вы используете более новую версию 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
Ответ 4
Запустите команду: docker stats
чтобы увидеть ограничения памяти, которые вы указали для контейнеров.