J'ai compris que docker run -m 256m --memory-swap 256m
limitera un conteneur afin qu'il puisse utiliser au plus 256 Mo de mémoire et aucun échange. S'il alloue plus, alors un processus dans le conteneur (pas "le conteneur") sera tué. Par exemple:
$ Sudo docker run -it --rm -m 256m --memory-swap 256m \
stress --vm 1 --vm-bytes 2000M --vm-hang 0
stress: info: [1] dispatching hogs: 0 cpu, 0 io, 1 vm, 0 hdd
stress: FAIL: [1] (415) <-- worker 7 got signal 9
stress: WARN: [1] (417) now reaping child worker processes
stress: FAIL: [1] (421) kill error: No such process
stress: FAIL: [1] (451) failed run completed in 1s
Apparemment, l'un des travailleurs alloue plus de mémoire que ce qui est autorisé et reçoit un SIGKILL
. Notez que le processus parent reste actif.
Maintenant, si l'effet de -m
est d'invoquer le tueur OOM si un processus alloue trop de mémoire, que se passe-t-il lors de la spécification de -m
et--oom-kill-disable
? L'essayer comme ci-dessus a le résultat suivant:
$ Sudo docker run -it --rm -m 256m --memory-swap 256m --oom-kill-disable \
stress --vm 1 --vm-bytes 2000M --vm-hang 0
stress: info: [1] dispatching hogs: 0 cpu, 0 io, 1 vm, 0 hdd
(waits here)
Dans un autre Shell:
$ docker stats
CONTAINER CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
f5e4c30d75c9 0.00% 256 MiB / 256 MiB 100.00% 0 B / 508 B 0 B / 0 B 2
$ top
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
19391 root 20 0 2055904 262352 340 D 0.0 0.1 0:00.05 stress
Je vois le docker stats
affiche une consommation de mémoire de 256 Mo et top
affiche une RES
de 256 Mo et une VIRT
de 2000 Mo. Mais qu'est-ce que cela veut vraiment dire? Qu'adviendra-t-il d'un processus à l'intérieur du conteneur qui essaie d'utiliser plus de mémoire que ce qui est autorisé? En ce sens, il est contraint par -m
?
Si je comprends bien les docs--oom-kill-disable
n'est pas contraint par -m
mais en fait l'exige:
Par défaut, le noyau tue les processus dans un conteneur si une erreur de mémoire insuffisante (MOO) se produit. Pour modifier ce comportement, utilisez l'option --oom-kill-disable. Ne désactivez le module de suppression OOM que sur les conteneurs où vous avez également défini l'option de mémoire -m/-. Si l'indicateur -m n'est pas défini, cela peut entraîner un manque de mémoire de l'hôte et nécessiter l'arrêt des processus système de l'hôte pour libérer de la mémoire.
Un développeur a déclaré en 2015 que
L'hôte peut manquer de mémoire avec ou sans l'indicateur -m défini. Mais cela n'a pas non plus d'importance car --oom-kill-disable ne fait rien à moins que -m ne soit passé.
En ce qui concerne votre mise à jour, que se passe-t-il lorsque OOM-killer
est désactivé et pourtant la limite de mémoire est atteinte ( article OOM intéressant ), je dirais que les nouveaux appels à malloc
et ceux-ci échoueront comme décrit ici = mais cela dépend aussi de la configuration du swap et de la mémoire disponible des hôtes. Si ton -m
la limite est supérieure à la mémoire réelle disponible, l'hôte commencera à tuer les processus, dont l'un pourrait être le démon docker (qu'ils essaient d'éviter en en changeant sa priorité OOM ).
Les documentation du noya (cgroup/memory.txt
) dire
Si OOM-killer est désactivé, les tâches sous cgroup se bloqueront/s'endormiront dans la mémoire OOM-waitqueue de cgroup lorsqu'elles demanderont une mémoire responsable
Pour l'implémentation réelle (que Docker utilise également) des groupes de contrôle, vous devez vérifier le code source .
Le travail du "tueur oom" sous Linux est de sacrifier un ou plusieurs processus afin de libérer de la mémoire pour le système lorsque tout le reste échoue. OOM killer n'est activé que si l'hôte a une surcharge de mémoire activée
Le réglage de --oom-kill-disable
définira le paramètre cgroup pour désactiver le tueur oom pour ce conteneur spécifique lorsqu'une condition spécifiée par -m
est rencontré. Sans le -m
flag, oom killer sera hors de propos.
L'indicateur -m ne signifie pas d'arrêter le processus lorsqu'il utilise plus de xmb de RAM, c'est seulement que vous vous assurez que le conteneur Docker ne consomme pas toute la mémoire de l'hôte, ce qui peut forcer le noyau à tuer son processus. Avec l'indicateur -m, le conteneur n'est pas autorisé à utiliser plus d'une quantité donnée de mémoire utilisateur ou système.
Lorsque le conteneur atteint le MOO, il ne sera pas tué, mais il peut se bloquer et rester à l'état défunt. Par conséquent, les processus à l'intérieur du conteneur ne peuvent pas répondre tant que vous n'intervenez pas manuellement et ne redémarrez pas ou ne tuez pas le conteneur. J'espère que cela aidera à clarifier vos questions.
Pour plus de détails sur la façon dont le noyau agit sur les MOO, consultez la page Gestion des MOO Linux et Limitations de la mémoire Docker.