内存在 Kubernetes pod 上超时导致 JVM 无法启动
Memory builds up overtime on Kubernetes pod causing JVM unable to start
我们运行正在使用 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 分钟 运行s 的特定工作。我注意到每次 运行 之后,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
这段代码乍一看似乎无害,所以我不知道从哪里开始。
非常感谢任何帮助,几天来我一直在努力弄清这个问题的真相。
我最终确实弄清了这个问题,所以我想我会 post 在这里找到我的解决方案。我在原来的 post 中提到,我将我的问题缩小到我在上面的问题中 post 编辑的 while 循环。每次有问题的作业 运行,while 循环可能会迭代 10 次。 while 循环完成后,我注意到每次使用的内存都增加了 100MB。
凭直觉,我觉得循环中的 CURL
命令可能是罪魁祸首。事实上,事实证明 CURL
正在耗尽我的内存并且出于某种原因没有释放它。而不是循环和 运行 以下 CURL 命令:
RES=`$CURL -X GET "${TS_URL}/wcs/resources/admin/index/dataImport/status?jobStatusId=${JOB_ID}"`
我用一个简单的 python 脚本替换了这个命令,该脚本利用 requests
模块来检查我们的工作状态。
我仍然不确定为什么 CURL 是这种情况下的罪魁祸首。在 运行 CURL --version
之后,似乎正在使用的基础库是 libcurl/7.29.0
。也许该库版本中存在一个错误,导致内存管理出现一些问题,但这只是一个猜测。
无论如何,从使用 python 的 requests
模块代替 CURL
已经解决了我的问题。
我们运行正在使用 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 分钟 运行s 的特定工作。我注意到每次 运行 之后,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
这段代码乍一看似乎无害,所以我不知道从哪里开始。
非常感谢任何帮助,几天来我一直在努力弄清这个问题的真相。
我最终确实弄清了这个问题,所以我想我会 post 在这里找到我的解决方案。我在原来的 post 中提到,我将我的问题缩小到我在上面的问题中 post 编辑的 while 循环。每次有问题的作业 运行,while 循环可能会迭代 10 次。 while 循环完成后,我注意到每次使用的内存都增加了 100MB。
凭直觉,我觉得循环中的 CURL
命令可能是罪魁祸首。事实上,事实证明 CURL
正在耗尽我的内存并且出于某种原因没有释放它。而不是循环和 运行 以下 CURL 命令:
RES=`$CURL -X GET "${TS_URL}/wcs/resources/admin/index/dataImport/status?jobStatusId=${JOB_ID}"`
我用一个简单的 python 脚本替换了这个命令,该脚本利用 requests
模块来检查我们的工作状态。
我仍然不确定为什么 CURL 是这种情况下的罪魁祸首。在 运行 CURL --version
之后,似乎正在使用的基础库是 libcurl/7.29.0
。也许该库版本中存在一个错误,导致内存管理出现一些问题,但这只是一个猜测。
无论如何,从使用 python 的 requests
模块代替 CURL
已经解决了我的问题。