Kubernetes Docker 容器中的内存映射文件是否与 Linux 中的常规进程一样工作?

Do memory mapped files in Docker containers in Kubernetes work the same as in regular processes in Linux?

我有进程A和进程B。进程A打开一个文件,调用mmap并写入,进程B做同样的事情,但是当进程A完成写入时读取相同的映射区域。

假设进程 A 没有调用 munmap,则进程 B 应该从内存而不是磁盘读取文件。

如果我想将进程 A 和进程 B 部署到 Kubernetes 中同一个 pod 中的不同容器,内存映射 IO 是否应该以与初始示例相同的方式工作?容器 B(进程 B)是否应该像在我的常规 Linux 桌面中那样从内存中读取文件?

让我们假设两个容器都在同一个 pod 中,并且 reading/writing 来自同一个持久卷的文件。我是否需要考虑特定类型的卷来实现 mmap IO?

如果你好奇的话,我正在使用 Apache Arrow 和 pyarrow 来读写这些文件并实现零拷贝读取。

Kubernetes pod 是一组部署在同一主机上的容器。 (reference)。所以这个问题实际上是关于同一主机上的多个容器 运行 会发生什么。

使用多种不同的技术将容器隔离在主机上。有两个 可能 与此处相关。 都没有阻止来自不同容器的两个进程在 mmap 文件时共享同一内存。

需要考虑的两件事是文件系统如何隔离以及内存如何被环围起来(受限)。

文件系统如何隔离

使用的技巧是创建一个 mount namespace so that any new mount points are not seen by other processes. Then file systems are mounted into a directory tree and finally the process calls chroot 以将 / 设置为该目录树的根。

这不会影响处理 mmap 文件的方式。这只是关于文件名/文件路径如何为两个不同进程工作的巧妙技巧。

即使作为该设置的一部分,相同的文件系统由两个不同的进程从头开始安装,结果也将与 bind mount 相同。这意味着相同的文件系统存在于两个路径下,但它是*相同的文件系统,而不是副本。

在这种情况下任何映射文件的尝试都与同一命名空间中的两个进程相同。

如何应用内存限制?

这是通过 cgroups 完成的。 cgroups 并没有真正隔离任何东西,它们只是限制了单个进程可以做什么。

但是有一个自然的问题要问,如果两个进程通过cgroups有不同的内存限制,他们可以共享相同的共享内存吗? Yes they can!

Note: file and shmem may be shared among other cgroups. In that case, mapped_file is accounted only when the memory cgroup is owner of page cache.

该参考资料有点晦涩,但描述了如何将内存限制应用于此类情况。

结论

两个进程都从同一文件系统内存映射同一文件作为同一主机上的不同容器,其行为几乎完全相同,就好像这两个进程在同一容器中一样。