Wie geht Docker mit OOM-Killer- und Speicherbeschränkungen um?


7

Ich habe einen Docker-Container, der eine einfache Java-Anwendung (jgroups-based) über ein Bash-Skript startet. Der Java-Prozess ist durch Xmx auf 128 m begrenzt, der Container darf 256 m verwenden (Swap ist deaktiviert). Leider sehe ich mich von Zeit zu Zeit den folgenden OOM-Nachrichten gegenüber:

Jul 07 02:43:54 ip-10-1-2-125 kernel: oom_kill_process: 16 callbacks suppressed
Jul 07 02:43:54 ip-10-1-2-125 kernel: java invoked oom-killer: gfp_mask=0x2400040, order=0, oom_score_adj=0
Jul 07 02:43:54 ip-10-1-2-125 kernel: java cpuset=0ead341e639c2f2bd27a38666aa0834c969e8c7e6d2fb21516a2c698adce8d5f mems_allowed=0
Jul 07 02:43:54 ip-10-1-2-125 kernel: CPU: 0 PID: 26686 Comm: java Not tainted 4.4.0-28-generic #47-Ubuntu
Jul 07 02:43:54 ip-10-1-2-125 kernel: Hardware name: Xen HVM domU, BIOS 4.2.amazon 05/12/2016
Jul 07 02:43:54 ip-10-1-2-125 kernel:  0000000000000286 000000006ffe9d71 ffff8800bb3c7c88 ffffffff813eb1a3
Jul 07 02:43:54 ip-10-1-2-125 kernel:  ffff8800bb3c7d68 ffff880033aea940 ffff8800bb3c7cf8 ffffffff812094fe
Jul 07 02:43:54 ip-10-1-2-125 kernel:  000000000000258c 000000000000000a ffffffff81e66760 0000000000000206
Jul 07 02:43:54 ip-10-1-2-125 kernel: Call Trace:
Jul 07 02:43:54 ip-10-1-2-125 kernel:  [<ffffffff813eb1a3>] dump_stack+0x63/0x90
Jul 07 02:43:54 ip-10-1-2-125 kernel:  [<ffffffff812094fe>] dump_header+0x5a/0x1c5
Jul 07 02:43:54 ip-10-1-2-125 kernel:  [<ffffffff811913b2>] oom_kill_process+0x202/0x3c0
Jul 07 02:43:54 ip-10-1-2-125 kernel:  [<ffffffff811fd304>] ? mem_cgroup_iter+0x204/0x390
Jul 07 02:43:54 ip-10-1-2-125 kernel:  [<ffffffff811ff363>] mem_cgroup_out_of_memory+0x2b3/0x300
Jul 07 02:43:54 ip-10-1-2-125 kernel:  [<ffffffff81200138>] mem_cgroup_oom_synchronize+0x338/0x350
Jul 07 02:43:54 ip-10-1-2-125 kernel:  [<ffffffff811fb660>] ? kzalloc_node.constprop.48+0x20/0x20
Jul 07 02:43:54 ip-10-1-2-125 kernel:  [<ffffffff81191a64>] pagefault_out_of_memory+0x44/0xc0
Jul 07 02:43:54 ip-10-1-2-125 kernel:  [<ffffffff8106b2c2>] mm_fault_error+0x82/0x160
Jul 07 02:43:54 ip-10-1-2-125 kernel:  [<ffffffff8106b778>] __do_page_fault+0x3d8/0x400
Jul 07 02:43:54 ip-10-1-2-125 kernel:  [<ffffffff8106b7c2>] do_page_fault+0x22/0x30
Jul 07 02:43:54 ip-10-1-2-125 kernel:  [<ffffffff81829838>] page_fault+0x28/0x30
Jul 07 02:43:54 ip-10-1-2-125 kernel: Task in /docker/0ead341e639c2f2bd27a38666aa0834c969e8c7e6d2fb21516a2c698adce8d5f killed as a result of limit of /docker/0ead341e639c2f2bd27a38666aa0834c96
Jul 07 02:43:54 ip-10-1-2-125 kernel: memory: usage 262144kB, limit 262144kB, failcnt 6868
Jul 07 02:43:54 ip-10-1-2-125 kernel: memory+swap: usage 0kB, limit 9007199254740988kB, failcnt 0
Jul 07 02:43:54 ip-10-1-2-125 kernel: kmem: usage 0kB, limit 9007199254740988kB, failcnt 0
Jul 07 02:43:54 ip-10-1-2-125 kernel: Memory cgroup stats for /docker/0ead341e639c2f2bd27a38666aa0834c969e8c7e6d2fb21516a2c698adce8d5f: cache:96KB rss:262048KB rss_huge:135168KB mapped_file:16
Jul 07 02:43:54 ip-10-1-2-125 kernel: [ pid ]   uid  tgid total_vm      rss nr_ptes nr_pmds swapents oom_score_adj name
Jul 07 02:43:54 ip-10-1-2-125 kernel: [26659]     0 26659     1127       20       7       3        0             0 sh
Jul 07 02:43:54 ip-10-1-2-125 kernel: [26665]     0 26665     1127       20       7       3        0             0 run.sh
Jul 07 02:43:54 ip-10-1-2-125 kernel: [26675]     0 26675   688639    64577     204       7        0             0 java
Jul 07 02:43:54 ip-10-1-2-125 kernel: Memory cgroup out of memory: Kill process 26675 (java) score 988 or sacrifice child
Jul 07 02:43:54 ip-10-1-2-125 kernel: Killed process 26675 (java) total-vm:2754556kB, anon-rss:258308kB, file-rss:0kB
Jul 07 02:43:54 ip-10-1-2-125 docker[977]: Killed

Wie Sie sehen können, ist RSS meiner App nur etwa 64 Millionen . Aus irgendeinem Grund beträgt der RSS-Wert der cgroup 256 Millionen (einschließlich 128 Millionen großer Seiten).

Ist das eine Art Betriebssystem-Cache? Wenn ja, warum spült OOM sie nicht, bevor die Apps der Benutzer beendet werden?


Docker-Version ist 1.11,
OS

Antworten:


4

Oh! Ich habe vergessen, die Antwort zu posten.

Das Problem oben ist mit meinem Java-Prozess, es hat nichts mit Docker zu tun. Ich dachte fälschlicherweise, dass der OOM-Bericht RSS in KB druckt. Das ist falsch - OOM-Bericht druckt die Anzahl der Seiten, die normalerweise jeweils 4 KB dauern .

In meinem Fall benötigt pid 26675 64577 Seiten für RSS, was (64577 * 4K) 258'308 KByte entspricht. Durch Hinzufügen von 2 Bash-Prozessen erhalten wir die Grenze der aktuellen CGroup - 262144kB.

Die weitere Analyse muss sich also im JVM-Feld befinden: Heap- / Metaspace-Analysen, native Speicherverfolgung, Threads usw.


1

Nicht der gesamte Java-Speicher befindet sich auf dem Heap. Vor Java 8 gab es das Permgen, von dem einige nach Metaspace gezogen sind. Sie haben auch einen Stapel (möglicherweise 1 MB) für jeden Thread und den Code für die JVM. Es scheint, dass Ihr Container zu klein ist.

Es gibt Tunables für Permgen und Stack Sizing. Metaspace wächst so stark wie erforderlich. Es gibt Demonstrationsprogramme, mit denen der Metaspace auf große Größen erweitert werden kann.

Studieren Sie das Speichermodell für Java, bevor Sie die Größe Ihres Containers ändern. Die JVM selbst schlägt mit einem Zustand "Nicht genügend Speicher" fehl, wenn der zugewiesene Speicher zu klein ist. Threads schlagen fehl, wenn die Stapelgröße zu klein ist.


1
Ja, es ist klar. Wie Sie jedoch sehen können, beträgt der RSS-Wert von jvm (der den gesamten vom jvm-Prozess zugewiesenen Speicher enthält) nur 64577 KB. Also, das Problem ist nicht hier :(
mikhail
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.