【发布时间】:2021-02-25 22:09:41
【问题描述】:
我们正在运行一个 kubernetes 环境,并且我们的 pod 遇到了内存问题。 pod 只运行一个容器,而这个容器负责全天运行各种实用程序作业。
问题是这个 pod 的内存使用量随着时间的推移而缓慢增长。此 pod 有 6 GB 的内存限制,最终,内存消耗会增长到非常接近 6GB。
我们的许多实用程序作业都是用 Java 编写的,当 JVM 为它们启动时,它们需要 -Xms256m 才能启动。然而,由于 pod 的内存随着时间的推移而增长,最终它达到了没有 256MB 可用空间来启动 JVM 的地步,Linux oom-killer 杀死了 java 进程。这是我在dmesg 看到的情况:
[Thu Feb 18 17:43:13 2021] Memory cgroup stats for /kubepods/burstable/pod4f5d9d31-71c5-11eb-a98c-023a5ae8b224/921550be41cd797d9a32ed7673fb29ea8c48dc002a4df63638520fd7df7cf3f9: cache:8KB rss:119180KB rss_huge:0KB mapped_file:0KB swap:0KB inactive_anon:0KB active_anon:119132KB inactive_file:8KB active_file:0KB unevictable:4KB
[Thu Feb 18 17:43:13 2021] [ pid ] uid tgid total_vm rss nr_ptes swapents oom_score_adj name
[Thu Feb 18 17:43:13 2021] [ 5579] 0 5579 253 1 4 0 -998 pause
[Thu Feb 18 17:43:13 2021] [ 5737] 0 5737 3815 439 12 0 907 entrypoint.sh
[Thu Feb 18 17:43:13 2021] [13411] 0 13411 1952 155 9 0 907 tail
[Thu Feb 18 17:43:13 2021] [28363] 0 28363 3814 431 13 0 907 dataextract.sh
[Thu Feb 18 17:43:14 2021] [28401] 0 28401 768177 32228 152 0 907 java
[Thu Feb 18 17:43:14 2021] Memory cgroup out of memory: Kill process 28471 (Finalizer threa) score 928 or sacrifice child
[Thu Feb 18 17:43:14 2021] Killed process 28401 (java), UID 0, total-vm:3072708kB, anon-rss:116856kB, file-rss:12056kB, shmem-rss:0kB
根据我一直在做的研究,here for example,随着各种缓存的增长,Linux 上的内存消耗随着时间的推移而增长似乎是正常的。据我了解,当新进程(例如我的 java 进程)开始运行时,也应该释放缓存的内存。
我的主要问题是:是否应该释放这个 pod 的内存以便这些 java 进程运行?如果是这样,我是否可以采取任何步骤来开始调试为什么这可能无法正确发生?
除了这个担忧之外,我还一直在尝试找出导致内存增长的原因。我能够将其缩小到每 15 分钟运行一次的某个工作。我注意到,每次运行后,Pod 的已用内存都会增加约 .1 GB。
我能够通过在每次执行作业之前和之后运行这个命令(在容器内)来解决这个问题:
cat /sys/fs/cgroup/memory/memory.usage_in_bytes | numfmt --to si
从那里我缩小了内存似乎持续增长的那段 bash 代码。该代码如下所示:
while [ "z${_STATUS}" != "z0" ]
do
RES=`$CURL -X GET "${TS_URL}/wcs/resources/admin/index/dataImport/status?jobStatusId=${JOB_ID}"`
_STATUS=`echo $RES | jq -r '.status.status' || exit 1`
PROGRES=`echo $RES | jq -r '.status.progress' || exit 1`
[ "x$_STATUS" == "x1" ] && exit 1
[ "x$_STATUS" == "x3" ] && exit 3
[ $CNT -gt 10 ] && PrintLog "WC Job ($JOB_ID) Progress: $PROGRES Status: $_STATUS " && CNT=0
sleep 10
((CNT++))
done
[ "z${_STATUS}" == "z0" ] && STATUS=Success || STATUS=Failed
这段代码乍一看对我来说似乎无害,所以我不知道从哪里开始。
我非常感谢任何帮助,我这几天一直在努力解决这个问题。
【问题讨论】:
-
minimal reproducible example 会有所帮助;豆荚里有什么?您的所有 pod 是否都有适当的资源请求,以便它们不会被安排在完整节点上? JVM 会经常使用你给它的内存,那么如果你给它一个更可控的内存限制,你的应用程序是否正常运行?
-
你用的是什么版本的jvm? jvm 8 及以下不知道容器提供的内存,可能会占用所有系统内存medium.com/faun/docker-sizing-java-application-326d39992592
-
能否如 Malathi 所述提供您的 Pod 清单文件和 jvm 版本?
-
大家好,感谢您的回复。我确实阅读了它们,但幸运的是我最终解决了我的问题。如果您想知道这个问题的解决方案,请随时阅读我的答案。谢谢!
标签: bash docker kubernetes memory jvm