J'utilise la dernière version de Docker sur Ubuntu 13.04 (Raring Ringtail):
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
Mais quand je démarre le conteneur,
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
Je ne vois aucune limitation d'aucune sorte, et mon noyau a la limite de mémoire cgroups activée:
kernel /boot/vmlinuz-3.8.0-33-generic ro console=tty0 root=/dev/xvda1 cgroup_enable=memory swapaccount=1
Quelle chose évidente me manque ici?
free
ne l'affichera pas car il est appliqué via cgroups. Au lieu de cela sur l'hôte (en dehors du conteneur), vous pouvez vérifier en utilisant /sysfs
et la mémoire de 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
Pour le voir manquer de mémoire, vous pouvez exécuter quelque chose qui utilisera plus de mémoire que vous allouez - par exemple:
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
Dans dmesg
, vous devriez voir le conteneur et le processus tués:
[ 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
Je fais un lien vers ce Nice post sur le stress de l'utilisation de la mémoire du conteneur. Voici le résumé, modifié un peu pour fonctionner pour Docker au lieu de LXC générique:
Lancez un conteneur avec une limite de mémoire:
$ Sudo docker run -m 512M -it ubuntu /bin/bash
root# apt-get update && apt-get install -y build-essential
Créez un fichier, foo.c
, à l'intérieur du conteneur avec les éléments suivants:
#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);
}
Compilez le fichier:
gcc -o foo foo.c
Ouvrez un nouveau terminal pour surveiller l'utilisation de la mémoire du conteneur:
$ 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
Démarrer la consommation de mémoire dans le conteneur
$ ./foo
Regardez maintenant votre conteneur au maximum. Remarque: Lorsque vous manquez de mémoire, le démarrage de malloc échoue, mais sinon le conteneur est laissé seul. Normalement, le logiciel à l'intérieur du conteneur se bloque en raison des mallocs défaillants, mais le logiciel résilient continuera de fonctionner.
Note finale: Docker -m
L'indicateur ne compte pas l'échange et RAM séparément. Si vous utilisez -m 512M
alors certains de ces 512 seront échangés, pas de RAM. Si vous voulez seulement RAM vous devrez utiliser directement les options LXC (ce qui signifie que vous devrez exécuter Docker avec le pilote d'exécution LXC au lieu 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 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
Il y a une différence notable entre l'utilisation de swap dans le total et non - avec swap le programme foo ci-dessus atteint ~ 450 Mo rapidement et consomme ensuite lentement le reste, alors qu'avec seulement RAM il saute immédiatement à 511 Mo pour moi. Avec swap, la consommation de mémoire du conteneur est marquée à ~ 60 Mo dès que j'entre dans le conteneur - c'est essentiellement le swap qui est compté comme "utilisation". Sans swap, ma consommation de mémoire est inférieure à 10 Mo lorsque je entrez dans le conteneur.
Exécutez la commande: docker stats
pour voir les limites de mémoire que vous avez spécifiées appliquées aux conteneurs.
Si vous utilisez une version plus récente de Docker, l’endroit où rechercher ces informations est /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