web-dev-qa-db-fra.com

Limiter la mémoire sur un conteneur Docker ne fonctionne pas

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?

37
Disco

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
46
user146416

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.

22
Hamy

Exécutez la commande: docker stats pour voir les limites de mémoire que vous avez spécifiées appliquées aux conteneurs.

1
issprof

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
1
Komu