letra - ubuntu font
Limitar la memoria en un contenedor acoplable no funciona (3)
Enlazando a esta agradable publicación sobre el uso de la memoria del contenedor. Aquí está el resumen, modificado un poco para que funcione en la ventana acoplable en lugar de LXC genérico:
Inicie el contenedor con un límite de memoria:
$ sudo docker -m 512M -it ubuntu /bin/bash
root# apt-get update && apt-get install -y build-essential
Crea un archivo foo.c
dentro del contenedor con la siguiente
#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);
}
Compila el archivo
gcc -o foo foo.c
Abra una nueva terminal para monitorear el uso de la memoria del contenedor:
$ 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
Comience el consumo de memoria en el contenedor
$ ./foo
Ahora mire su contenedor al máximo. Nota: Cuando se ha agotado la memoria, Malloc comienza a fallar, pero, de lo contrario, el contenedor se deja en paz. Normalmente, el software dentro del contenedor se bloqueará debido a la falla de Mallocs, pero el software que es resistente continuará operando
Nota final: el indicador -m de Docker no cuenta swap y ram por separado. Si usa -m 512M
entonces parte de ese 512 será swap, no RAM. Si solo quieres RAM, necesitarás usar las opciones LXC directamente (lo que significa que necesitarás ejecutar docker con el controlador de ejecución LXC en lugar de 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 max RAM (e.g. 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
Hay una diferencia notable entre usar swap como parte del total y no - con el intercambio del programa foo arriba alcanzando ~ 450M rápidamente y luego lentamente consume el resto, mientras que con solo RAM salta inmediatamente a 511M para mí. Con swap, el consumo de memoria del contenedor se marca a ~ 60M tan pronto como ingrese al contenedor; esto es básicamente el intercambio contado como "uso". Sin intercambio, mi uso de memoria es <10M cuando ingreso al contenedor
Ejecutando la última versión de docker encima de ubuntu 13.04
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
Pero cuando comienzo el contenedor
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
No veo ninguna limitación de ningún tipo, y mi kernel tiene habilitado el límite de memoria de cgroups:
kernel /boot/vmlinuz-3.8.0-33-generic ro console=tty0 root=/dev/xvda1 cgroup_enable=memory swapaccount=1
¿Qué cosa obvia me falta aquí?
Si está utilizando una versión más nueva de Docker, el lugar para buscar esa información es /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
free
no se mostrará ya que esto se aplica a través de cgroups. En cambio, en el host (fuera del contenedor) puede verificar usando /sysfs
y la memoria del 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
Para ver que se queda sin memoria, puede ejecutar algo que utilizará más memoria de la que asigna, por ejemplo:
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
En dmesg
deberías ver el contenedor y el proceso asesinados:
[ 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