【问题标题】:Kubernetes pods restart issue anomalyKubernetes Pod 重启问题异常
【发布时间】:2018-07-23 08:08:05
【问题描述】:

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

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

为了调试这个,我在 pod 中启动了一个 newrelic 代理和应用程序,发现了下图:

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

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

但是当我描述 pod 并查找最后一个状态时,它显示“原因:错误”和“退出代码:137”

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

当我登录到我的工作节点并检查 docker 容器的状态时,我可以看到该应用程序的最后一个容器,状态为 Exited,并显示“Container exits with non-zero exit code 137”

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

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

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

我不确定为什么我的 pod 会一次又一次地重新启动,这是 k8s 的行为还是我的基础架构中的某些恶作剧。这迫使我再次将我的应用程序从 Container 移动到 VM,因为这会导致 5xx 计数增加。

编辑:将内存增加到 12GB 后,我遇到了 OOM。

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

需要帮助!

【问题讨论】:

  • 你能从 pod 中获取进程,看看是什么消耗了内存吗?
  • 只有java!
  • 您的应用程序是重盘消费者吗?我对此有类似的问题,并且所有内容(在我的情况下)都指向内核的文件缓存。如果你做一个 top pods 会告诉你 k8s 如何查看你的 pods 内存使用情况。

标签: docker linux-kernel kubernetes newrelic datadog


【解决方案1】:

一些较旧的 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

【讨论】:

    【解决方案2】:

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

    【讨论】:

    • 9Gib 的反应如何?它应该小于 6,因为我的 Xmx 值为 6
    【解决方案3】:

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

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

    【讨论】:

    • 对此我不确定。虽然我在启用 JVM Native memory stats 后对此进行了测试,发现 XMX 仅适用于 Heap 和其他内存消耗因素,如 Eden 内存或完整的 RSS 内存远高于 XMX。我已经接近结论,但仍然无法找出一些情况,其中每件事情看起来都很正常,但 pod 会重新启动。
    • 您好 Vaibhav,如果您发现任何结论,请您提及结论。我也遇到了类似的问题
    • @DeepakJain 经过大量调查,我们发现我们的应用程序本身行为异常。我们调整了很多 JVM 参数并使用 java 启动命令传递它们。我们也改变了 JVM 垃圾回收机制。
    猜你喜欢
    • 2016-08-22
    • 2017-07-31
    • 1970-01-01
    • 1970-01-01
    • 2020-03-23
    • 2020-03-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多