docker - Kubernetes pods 重启问题异常

标签 docker linux-kernel kubernetes newrelic datadog

我的 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 并寻找最后一个状态时,它会显示“原因:错误”和“退出代码:137”

enter image description here

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

enter image description here

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

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

enter image description here

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

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

enter image description here

我不确定为什么我的 pod 一次又一次地重新启动,这是 k8s 的行为还是我的基础设施中的一些欺骗性行为。这迫使我再次将我的应用程序从容器移动到虚拟机,因为这会导致 5xx 计数增加。

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

enter image description here

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

需要帮忙!

最佳答案

一些较旧的 Java 版本(Java 8 u131 版本之前)无法识别它们正在容器中运行。因此,即使您使用 -Xmx 为 JVM 指定最大堆大小,JVM 也会根据主机的总内存而不是容器可用的内存来设置最大堆大小,然后当进程尝试分配超过其限制的内存时(在 pod/部署规范中定义)您的容器正在被 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

关于docker - Kubernetes pods 重启问题异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51474223/

相关文章:

Dockerfile:在仅将所需的文件复制到镜像之前,如何构建我的项目?

c - 为什么我的设备驱动程序不打印我输入的内容

elasticsearch - 使用Fluentd运送到Elasticsearch后,日志未按顺序显示

kubernetes - 将 Spring Boot 应用程序导入 Kubernetes

r - 运行 R 的 Docker 容器中的 "file ' .Renviron ' cannot be opened for reading"

memory-management - docker 容器对 CPU 和内存的运行时限制

docker - 多个Docker主机通信

linux - 在linux内核3.x模块中,我如何使用Kprobe来计算系统调用?

linux - 我们编译linux内核时生成的vmlinux文件有什么用

kubernetes - 如何正确连接 K8S 对象?