Kubernetes Pod 重启问题异常。

4
我的Java微服务运行在托管在AWS EC2实例上的k8s集群中。
我有大约30个微服务(包括Nodejs和Java 8),运行在一个K8s集群中。我面临一个挑战,我的Java应用程序Pod会意外重启,导致应用程序5xx计数增加。
为了调试这个问题,我在Pod中启动了一个Newrelic代理,同时与应用程序一起运行,并发现以下图形:

enter image description here

我可以看到,我的Xmx值为6GB,而我的使用量最大只有5.2GB。

这清楚地表明JVM没有超过Xmx值。

但是当我描述Pod并查看最后一个状态时,它显示“原因:错误”,并带有“退出代码:137”。

enter image description here

进一步调查后,我发现我的Pod平均内存使用率一直接近其限制。(分配了9Gib,使用了约9Gib)。我无法理解为什么Pod的内存使用率如此之高,即使我只运行了一个进程(JVM),而且还将其限制在6Gib Xmx。

enter image description here

当我登录到我的工作节点并检查docker容器的状态时,我可以看到该应用程序的最后一个容器处于Exited状态,并显示“容器以非零退出码137退出”。
我可以看到工作节点内核日志如下:

enter image description here

这表明内核正在终止我在容器内运行的进程。

我可以看到我的工作节点上有很多空闲内存。

enter image description here

我不确定为什么我的Pod会一遍又一遍地重启,这是Kubernetes的行为还是基础设施中的某些欺骗行为。这迫使我再次将应用程序从容器移动到虚拟机上,因为这导致5xx计数增加。
编辑:在将内存增加到12GB后,我遇到了OOM问题。

enter image description here

我不确定为什么由于OOM而导致POD被终止,尽管JVM的xmx仅为6 GB。

需要帮助!


你能从 Pod 中获取进程以查看哪些进程正在消耗内存吗? - Crou
这是仅限于Java! - Vaibhav Jain
你的应用程序是否占用大量磁盘空间?我也遇到了类似的问题,所有迹象(在我的情况下)都指向内核文件缓存。如果你运行 top pods 命令,它会显示 k8s 如何查看你的 pod 内存使用情况。 - Guillermo Coscarelli
3个回答

3

一些旧版的Java(Java 8 u131版本之前)无法识别自己正在容器中运行。因此,即使您使用-Xmx指定了JVM的最大堆大小,JVM也会根据主机的总内存设置最大堆大小,而不是容器可用的内存。当进程尝试分配超过其限制(在pod / deployment规范中定义)的内存时,您的容器将被OOMKilled。

当在K8集群本地运行Java应用程序时,这些问题可能不会出现,因为pod内存限制和本地计算机内存总量之间的差异不大。但是,当您在具有更多可用内存的节点上进行生产环境运行时,JVM可能会超过容器内存限制并且将被OOMKilled。

从Java 8(u131版本)开始,可以使JVM“容器感知”,以便它识别由容器控制组(cgroups)设置的约束条件。

对于Java 8(从U131版本)和Java9,可以将这些实验标志设置为JVM:

-XX:+UnlockExperimentalVMOptions 
-XX:+UseCGroupMemoryLimitForHeap

它将根据容器cgroups内存限制设置堆大小,该限制在pod/deployment规范的容器定义部分中定义为“资源:限制”。Java 8仍然可能存在JVM离堆内存增加的情况,因此您可能需要监视它,但是总体而言,这些实验性标志也必须处理它。

Java 10开始,这些实验性标志是新默认值,并可通过使用此标志启用/禁用:

 -XX:+UseContainerSupport 
 -XX:-UseContainerSupport

1

由于您将Pod的最大内存使用限制为9Gi,所以当内存使用量达到9Gi时,它将自动终止。


它怎么达到了9Gib?我的Xmx值为6,应该小于6。 - Vaibhav Jain

0
在GCloud App Engine中,您可以指定最大的CPU使用阈值,例如0.6。这意味着如果CPU达到100%的0.6 - 60%,则会生成一个新实例。
我没有遇到过这样的设置,但是可能:Kubernetes POD/Deployment具有类似的配置参数。这意味着,如果POD的RAM达到100%的0.6,则终止POD。在您的情况下,这将是9GB的60%=约5GB。只是一些思考的食物。

我对此不确定。虽然我已经启用了JVM本机内存统计并进行了测试,发现XMX仅适用于堆和其他消耗内存的因素,如伊甸园内存或完整的RSS内存远高于XMX。我接近结论,但仍无法弄清楚一些情况,即使一切似乎正常,Pod也会重新启动。 - Vaibhav Jain
1
嗨,Vaibhav,你能否提及一下你是否得出了结论。我也遇到了类似的问题。 - Deepak Jain
@DeepakJain 经过大量调查,我们发现我们的应用程序本身表现异常。我们调整了许多JVM参数,并将它们与Java启动命令一起传递。我们还更改了JVM垃圾收集机制。 - Vaibhav Jain

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接