Kubernetes pods重新启动异常问题

问题描述 投票:2回答:3

我的Java微服务在AWS EC2实例上托管的k8s集群中运行。

我在K8s集群中运行了大约30个微服务(nodejs和Java 8的良好组合)。我正面临一个挑战,我的Java应用程序pod意外重启,导致应用程序5xx计数增加。

为了调试这个,我在pod中启动了一个newrelic代理和应用程序,并找到了以下图表:

enter image description here

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

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

但是当我描述pod并查找最后一个状态时,它会显示“Reason:Error”,并显示“Exit code:137”

enter image description here

然后在进一步调查中我发现我的Pod平均内存使用量一直接近其极限。(分配的9Gib,使用~9Gib)。我无法理解为什么内存使用在Pod中如此之高,即使我只有一个进程在运行((JVM),而且也受到6Gib Xmx的限制。

enter image description here

当我登录到我的工作站节点并检查docker容器的状态时,我可以看到具有退出状态的该应用程序的最后一个容器,并说“容器退出时具有非零退出代码137”

我可以看到wokernode内核日志为:

enter image description here

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

我可以看到我的工作节点中有很多可用内存。

enter image description here

我不知道为什么我的pod会一次又一次地重启,这是k8s的行为或者我的基础设施中的一些欺骗行为。这迫使我将我的应用程序从Container再次移动到VM,因为这会增加5xx计数。

编辑:我增加内存到12GB后得到OOM。

enter image description here

我不确定为什么POD因为OOM而被杀死JVM xmx只有6 GB。

需要帮忙!

docker linux-kernel kubernetes newrelic datadog
3个回答
1
投票

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


1
投票

某些较旧的Java版本(在Java 8 u131发行版之前)无法识别它们是在容器中运行。因此,即使您使用-Xmx为JVM指定了最大堆大小,JVM也将根据主机的总内存而不是容器可用的内存来设置最大堆大小,然后当进程尝试分配超出其限制的内存时(在容器/部署规范中定义的容器正在获得OOMKilled。

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

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

对于Java 8(来自U131版本)和Java9,您可以将此实验标志设置为JVM:

-XX:+UnlockExperimentalVMOptions 
-XX:+UseCGroupMemoryLimitForHeap

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

从Java 10开始,这些实验标志是新的默认标志,并使用此标志启用/禁用:

 -XX:+UseContainerSupport 
 -XX:-UseContainerSupport

0
投票

在GCloud App Engine中,您可以指定最大值。 CPU使用率阈值,例如0.6。这意味着如果CPU达到100%的0.6% - 60% - 将生成一个新实例。

我没有遇到过这样的设置,但可能:Kubernetes POD / Deployment有类似的配置参数。意思是,如果POD的RAM达到100%的0.6,则终止POD。在你的情况下,这将是9GB = ~5GB的60%。只是一些思考的食物。

© www.soinside.com 2019 - 2024. All rights reserved.