容器无法启动:Java运行时环境内存不足,无法继续运行。

20

我们有一个运行在Java 8上的企业应用程序。部署环境是通过Bitbucket pipelines构建和更新的。我有一个显示环境高级架构的图形(点击查看)。我们有两个应用服务器,除了一些特定于应用程序的环境变量之外,它们运行相同的配置。

一切都很顺利,直到一个星期前,在成功运行pipeline后,其中一个服务器上的2个应用程序实例停止工作,并显示以下错误:

There is insufficient memory for the Java Runtime Environment to continue.
Cannot create GC thread. Out of system resources.

另一台服务器上两个实例都正常工作,但在这台服务器上容器无法启动。

尝试的解决方案

错误附带以下信息:

可能的原因: 系统物理 RAM 或交换空间已用完 进程正在运行并启用了 CompressedOops,Java 堆可能会阻塞本地堆的增长。

可能的解决方案:

  • 减少系统的内存负载
  • 增加物理内存或交换空间
  • 检查交换后备存储是否已满
  • 减小 Java 堆大小(-Xmx/-Xms)
  • 减少 Java 线程数目
  • 减小 Java 线程堆栈大小(-Xss)
  • 使用 -XX:ReservedCodeCacheSize= 设置更大的代码缓存

我们已经尝试了:

  1. 添加更多的交换空间。服务器具有 8GB 的 RAM,而我们已经尝试将交换空间从 4GB 增加到 9GB。
  2. 更改堆大小 Xms 和 Xmx,从 128m 到 4096m。
  3. 将该服务器的 RAM 增加到 16GB,而仍然在 8GB 上工作的其他服务器也是如此。

以下是内存和交换空间占用情况:

free -mh
              total        used        free      shared  buff/cache   available
Mem:           15Gi       378Mi        12Gi       1.0Mi       2.9Gi        14Gi
Swap:           9Gi          0B         9Gi

我有几个相关文物的链接。这些包括完整的docker logs输出以及在失败的服务器上运行良好的服务器上docker info输出。

这是docker ps -a返回的结果:

:~$ docker ps -a
CONTAINER ID   IMAGE                                                                                  COMMAND                  CREATED        STATUS                    PORTS                                       NAMES
d29747bf2ad3   :a7608a838625ae945bd0a06fea9451f8bf11ebe4   "catalina.sh run"        10 hours ago   Exited (1) 10 hours ago                                               jbbatch
0951b6eb5d42   :a7608a838625ae945bd0a06fea9451f8bf11ebe4   "catalina.sh run"        10 hours ago   Exited (1) 10 hours ago                                               jbapp

我们现在已经尝试了 Stack Overflow 上几乎所有的解决方案,但是我们还是没有头绪。我们错过了什么吗?


你尝试过监控应用程序的堆内存和非堆内存吗?例如,通过prometheus/grafana(如果应用程序提供监控端点)或VisualVM(如果相应代理已附加到vm)进行监控。也许一些特定于环境的配置导致了更高的内存压力。你在docker容器上设置了任何内存限制吗? - Turing85
容器无法启动,因此监控无法发挥作用。 - Master.Aurora
@Turing85 在 Docker 容器中没有隐含的内存限制。以下是服务器上内存使用情况的详细信息: https://pastebin.mozilla.org/xMJK1FTg - Master.Aurora
你能否编辑问题并包含一个MCVE(最小可复现示例)?请确保直接将相关源代码嵌入到问题中,而不是放在链接后面。目前你所提供的信息确实表明JVM内存不足,但没有源代码或其他细节,很难给出除了一般性的监控和调优建议之外的更多帮助。 - David Maze
@DavidMaze 这是一款企业应用程序,分享重现步骤可能会很困难。我也相信代码可能不是问题,因为同样的代码与相同的管道正在其他服务器上运行。“docker info” 提供的信息存在轻微差异,如 Docker 版本和内核版本。您认为这可能会导致问题吗? - Master.Aurora
2个回答

27
我看到您的Docker镜像使用了Ubuntu 22.04 LTS作为其基础。最近,基本Java镜像已经在此LTS版本之上进行了重建,这导致了在旧版本的Docker运行时中出现了许多问题。很可能这就是您所遇到的问题。这与内存无关,而是与作为基础镜像使用的更新Linux版本不兼容的Docker有关。
您的操作服务器具有Docker服务器版本20.10.10,而失败的服务器具有版本20.10.09。不兼容性问题正是在Docker 20.10.10中被修复的。更多关于不兼容性问题的技术细节请参见此处
解决方法是将失败的服务器升级至至少Docker 20.10.10。

1
我也遇到了20.10.18的问题。问题是服务器没有交换空间。通过添加交换空间,问题得以解决。 - lcetinsoy
1
@Icetinsoy 你是如何检查交换空间的? - ooomid
在Linux上,free命令 - Eric Kramer

10

我曾经也遇到过同样的错误。 输出结果为

# docker info

was:

....
Security Options:
 seccomp
  WARNING: You're not using the default seccomp profile
  Profile: /etc/docker/seccomp.json
....

问题已通过放置 XXX 解决。
  security_opt:
    - seccomp:unconfined

在docker-compose.yml文件中的服务部分,移除并重新创建容器

docker rm <container_name>
docker-compose up -d <service_name>

也许通过调整 /etc/docker/seccomp.json 文件可以获得相同的结果 - 我尝试过但失败了。

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