Linux OOM Killer 杀死似乎有足够内存的 dockerized Java 进程

时间:2021-06-27 22:50:00

标签: java linux docker crash kill-process

我们有一个运行 Java Spring 应用程序的 docker 容器,以及运行 Postgres 和 Caddy 的其他容器。

这就是 Dockerfile 启动 Java 应用程序的方式。

ENTRYPOINT ["java", "-Xmx896m", "-jar", "springapplication.jar"]

从 JVM 的角度来看,可用内存量似乎远非零,不会成为问题,但我们几乎每天都会看到 Linux OOM Killer 在一台或另一台机器上杀死此 Java 进程。

sudo grep /var/log/kern.log* -ie kill
/var/log/kern.log:Jun 25 11:39:50 mk kernel: [27578.725827] VM Periodic Tas invoked oom-killer: gfp_mask=0x100cca(GFP_HIGHUSER_MOVABLE), order=0, oom_score_adj=0
/var/log/kern.log:Jun 25 11:39:50 mk kernel: [27578.725862]  oom_kill_process.cold+0xb/0x10
/var/log/kern.log:Jun 25 11:39:50 mk kernel: [27578.726086] oom-kill:constraint=CONSTRAINT_NONE,nodemask=(null),cpuset=06b40d3fc921f46fa21dfe5b177c62374542484788c7889227c64dc8950b5b75,mems_allowed=0,global_oom,task_memcg=/docker/06b40d3fc921f46fa21dfe5b177c62374542484788c7889227c64dc8950b5b75,task=java,pid=1330,uid=0
/var/log/kern.log:Jun 25 11:39:50 mk kernel: [27578.726224] Out of memory: Killed process 1330 (java) total-vm:2934160kB, anon-rss:644744kB, file-rss:0kB, shmem-rss:0kB, UID:0 pgtables:1632kB oom_score_adj:0

Java 代码在 oom-killer 执行其操作之前不久记录了以下内容。这些值来自在 docker 容器内运行的 JVM,该容器与其他 docker 容器共享服务器。

total memory: 124145664
free memory: 25273584
used memory: 98872080

这些是具有 1GB RAM 的 Ubuntu 20.x 机器。因此,在 kern.log 中,有一件令人费解的事情,它显示了 total-vm:2934160kB。我们如何在没有交换的 1GB 机器上拥有 2.9GB 的虚拟内存?

vmstat
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 2  0      0  88032  33016 276724    0    0    15    14  111  405  2  2 95  0  0
cat /proc/meminfo
MemTotal:        1004856 kB
MemFree:           88048 kB
MemAvailable:     234212 kB
Buffers:           33216 kB
Cached:           244140 kB
SwapCached:            0 kB
Active:           666068 kB
Inactive:         119660 kB
Active(anon):     519864 kB
Inactive(anon):     8532 kB
Active(file):     146204 kB
Inactive(file):   111128 kB
Unevictable:       18564 kB
Mlocked:           18564 kB
SwapTotal:             0 kB
SwapFree:              0 kB
Dirty:               100 kB
Writeback:             0 kB
AnonPages:        524940 kB
Mapped:           111680 kB
Shmem:             15836 kB
KReclaimable:      32876 kB
Slab:              81812 kB
SReclaimable:      32876 kB
SUnreclaim:        48936 kB
KernelStack:        4748 kB
PageTables:         6016 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:      502428 kB
Committed_AS:    2574580 kB
VmallocTotal:   34359738367 kB
VmallocUsed:       12896 kB
VmallocChunk:          0 kB
Percpu:              604 kB
HardwareCorrupted:     0 kB
AnonHugePages:         0 kB
ShmemHugePages:        0 kB
ShmemPmdMapped:        0 kB
FileHugePages:         0 kB
FilePmdMapped:         0 kB
CmaTotal:              0 kB
CmaFree:               0 kB
HugePages_Total:       0
HugePages_Free:        0
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:       2048 kB
Hugetlb:               0 kB
DirectMap4k:      110572 kB
DirectMap2M:      937984 kB
DirectMap1G:           0 kB

这是来自一台不同的、配置相同的机器,它没有任何此类 oom-killer 事件。但是 VmallocTotal 是一个可怕的数字。那是什么意思??那只是可寻址空间,还是实际上意味着内存使用情况?

我们最近开始使用 cron 作业在凌晨 4 点重新启动所有机器,并且在不到 8 小时后发生了上述崩溃,而在类似负载下的其他十几台机器没有发生此类事件。事实上,在上周之前,没有通过 cron 定期重启,机器可以在没有任何 oom-killer 事件的情况下运行数天。

似乎典型的内存泄漏会在某种程度上一致地影响所有机器,但这不是我们所看到的。每天大约有一台机器,而且它并不总是负载最重的机器。

这让我们陷入了一个缺乏专业知识的领域,所以我们真的不知道如何确定原因然后解决问题。我们不确定是否存在 Java 内存泄漏、Java 与其 docker 容器之间的错误配置,或者与 docker 或 Linux 相关的问题。

我们不愿意启用交换,因为这是一个低延迟的应用程序,所以交换几乎和崩溃一样糟糕。

欢迎提供任何见解。

0 个答案:

没有答案