Docker容器中的尾巴:无法分配内存

Ond*_*ček 5 linux memory docker

我正用这个问题把头撞在墙上。我们正在并行运行许多容器,它们正在运行简单的文件系统操作或简单的linux命令,并且其中某些在某些情况下会因内存分配问题而失败,Docker容器会出现OOMKiled。

我相信它与特定命令无关。tail不是唯一失败的命令,我们也遇到过cpgzip

我们已经缩小了问题的范围,并创建了一个脚本,当参数根据底层系统进行相应调整后,几乎可以肯定会失败。

https://github.com/keboola/processor-oom-test

具有默认设置的脚本会生成具有100M行(〜2.5GB)的随机CSV,将其复制20次,然后运行20个运行中的容器tail -n +2 ...。在m5.2xlarge具有1TB SSD 的AWS EC2实例上,某些容器被OOMKilled(某些容器具有不同的错误)。进程因各种错误而终止:

/code/tail.sh: line 2:    10 Killed                  tail -n +2 '/data/source.csv' > '/data/destination.csv'
tail: error reading '/data/source.csv': Cannot allocate memory
tail: write error
Run Code Online (Sandbox Code Playgroud)

(最后一个不是OOMKilled)

我不知道该tail消耗任何内存。如果可以同时工作的容器数量足够少,则可以轻松使用64MB的内存。对于更大数量的容器,即使256MB内存也不够用。我一直在观察htopdocker stats还没有看到内存消耗的任何峰值。

我们已经尝试过的事情

  • 不同的Docker图片(Alpine,centos,ubuntu)
  • 不同的文件系统(ext3,xfs)
  • 不同的操作系统发行版(centos,ubuntu)
  • 不同的实例提供者(Digital Ocean,AWS)
  • 不同类型的实例和块设备
  • 文件系统交换/交换
  • Docker内存交换和交换

其中一些只提供了部分帮助。调整内存限制或容器数量会使它每次都再次崩溃。我们有一个带有1GB内存的容器,tail使用OOMKilled可以在大型文件崩溃时简单地运行。

关于几个月前我尝试过的内容-https: //500.keboola.com/cp-in-docker-cannot-allocate-memory-1a5f57113dc4。而--memory-swap原来只仅仅是一个局部的帮助。

有什么建议么?我不是Linux专家,所以我可能缺少一些重要的东西。任何帮助或建议,我们将不胜感激。

小智 5

似乎您对“写入缓存大小”有问题。

当您想要向磁盘写入某些内容时,它不会直接写入,而是存储在写入缓存中(称为 dirty_pages)。这是因为所有进程都不需要等到获得写入磁盘的权限并继续工作。但是,当进程长时间没有获得在磁盘上写入的权限时,它的写入缓冲区开始增长,直到达到为容器定义的内存限制。然后它被docker杀死了。

有一个名为的守护进程pdflush负责刷新缓存并将这些 dirty_pages 写入磁盘。我认为您肯定正在寻找参数vm.dirty_bytesvm.dirty_background_bytes。这两个参数在这里有很好的描述vm.dirty_ratio 和 vm.dirty_background_ratio? 之间的区别?

例如,如果您正在使用内存限制--memory=128M,并且您的容器一次仅运行一个进程,则您的内存vm.dirty_bytes不应超过 128M(以字节为单位)。vm.dirty_background_ratio(可以选择设置比率[总内存的%]或确切的字节数)取决于同时运行的容器数量。该值对您来说并不那么重要,您可以将其设置为 10 到 15 之间的某个值。

要设置这些变量,请使用sysctl -w. 对于你的情况应该是:

sysctl -w vm.dirty_bytes=134217728
sysctl -w vm.dirty_background_ratio=15
Run Code Online (Sandbox Code Playgroud)

希望它会有所帮助!