我有一个第三方应用程序,我们的管道在构建服务器上运行,位于专用的 Docker 容器内,每次都全新启动,只为完成这项工作。该应用程序占用大量内存和 CPU,生成许多进程,运行时间约为 20 分钟。当一次运行一次(非并发)时,它每次都能成功运行完成。
当管道尝试在同一台服务器上同时运行此应用程序容器的两个或多个实例时,就会出现问题。在执行过程中的某些位置(这些位置有些随机,但似乎是从一组一致且有限的位置中选择的),这些应用程序进程中的一个或多个会因分段错误而崩溃,通常会出现与无效空闲或错误的 remalloc 有关的错误。
我尝试了多种技术来尝试调试段错误,但是应用程序没有提供调试信息,日志不足,并且有一些东西阻止strace
运行(运行时它在开始时崩溃strace
)。
我一直在监控服务器的内存消耗,并没有出现内存不足的情况。
虽然还有其他可能性,但此时我假设应用程序正在动态库中使用共享内存,并且由于 Docker 镜像使用相同的层,任何容器中的每个进程都隐式地与其他容器共享此内存,这是由于 Docker/Linux 如何有效地处理驻留在同一个 inode 上的共享库:https://stackoverflow.com/a/40096194
我正在寻找一种方法来隔离这些 Docker 容器,以便它们不会以这种方式在它们之间隐式共享内存。
请注意,如果我直接在服务器上运行应用程序,不使用 Docker,我会看到相同的行为 - 多个并发实例最终会导致一个或多个段错误。该应用程序显然不是设计为在同一主机上并发运行的,这就是为什么如果可能的话我想在 Docker 中隔离。
我理解如果我实际复制了 Docker 镜像,那么这将导致共享对象来自每个容器中的不同 inode,这可能足以帮助证明或反驳该假设,但我不知道如何复制或展平 Docker 镜像以便它使用其中的全新文件。
编辑:为了完整起见,我应该提到我可以在两个不同的主机,没有问题。它们仅在同一主机上运行时(在 Docker 容器内部或外部)才会崩溃。