【问题标题】:tail in a Docker container: Cannot allocate memoryDocker容器中的尾部:无法分配内存
【发布时间】:2019-01-23 14:26:31
【问题描述】:

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

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

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

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

使用默认设置的脚本会生成一个包含 1 亿行 (~2.5GB) 的随机 CSV,将其复制 20 次,然后运行 ​​20 个运行 tail -n +2 ... 的容器。在具有 1TB SSD 的 m5.2xlarge 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

(最后一个没有OOMKilled)

我不知道tail 应该消耗任何内存。如果并发工作的容器数量足够少,它可以轻松地在 64MB 内存下生存。对于大量容器,即使 256MB 也不够内存。我一直在看 htopdocker stats 并没有看到任何内存消耗高峰。

我们已经尝试过的事情

  • 不同的 Docker 镜像(alpine、centos、ubuntu)
  • 不同的文件系统(ext3、xfs)
  • 不同的操作系统发行版(centos、ubuntu)
  • 不同的实例提供商(Digital Ocean、AWS)
  • 不同类型的实例和块设备
  • 文件系统交换/swappiness
  • Docker 内存交换和交换

其中一些只是部分帮助。调整内存限制或容器数量使其每次都再次崩溃。我们有一个 1GB 内存的容器在 OOMKilled 的大文件崩溃时运行简单的tail

进一步了解我几个月前的尝试 - https://500.keboola.com/cp-in-docker-cannot-allocate-memory-1a5f57113dc4。而--memory-swap 原来只是部分帮助。

有什么建议吗?我不是 Linux 专家,所以我可能遗漏了一些重要的东西。非常感谢任何帮助或建议。

【问题讨论】:

  • 您接受的答案是否成功?
  • @antoine-sac 是的,这是后续行动 - 500.keboola.com/…
  • 您写一篇关于它的完整博客文章的可能性有多大?太好了,谢谢反馈!

标签: linux docker memory


【解决方案1】:

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

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

有一个名为pdflush 的守护进程负责刷新缓存并将那些dirty_pages 写入磁盘。我认为您肯定在寻找参数vm.dirty_bytesvm.dirty_background_bytes。这两个参数在这里有很好的描述Difference between vm.dirty_ratio and 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

希望对您有所帮助!

【讨论】:

    【解决方案2】:

    我没有代表发表评论,所以这里是一个答案的猜测!我们遇到了类似的问题,结果我们发现磁盘内存不仅仅是你总共使用了多少空间——还有一些叫做 inode 的东西有一个单独的、有限的数字,比如 node_modules (在 js 中)或任何形式的大型小文件库,甚至可能是日志文件,都可能真正耗尽您的 inode。

    尝试在命令行中输入(假设您使用的是 linux 或 mac)

    df -ih

    如果您的根目录(安装在 / 上)的 IUse 为 99%,那么这就是您的问题。您很可能拥有一堆陈旧的 docker 卷,其中包含数十万个文件,占用了您的所有空间。

    Linux 通常建议为根目录 (/) 设置一个小容量 (20G),然后为您的 /home 设置一个大容量以适合您所有的小猫个人照片等。但是,除非另有说明,否则 Docker 会将其所有数据在根挂载中,因此您可以非常快速地将其填满,并且仍然在服务器上留下看起来像负载的空间!这通常与专业服务器无关,但值得牢记。

    【讨论】:

    • 感谢@abulafia 的建议,我们的用例有点不同。该操作通常发生在单个大文件上。在整个处理过程中,我一直在监控IUse%,尤其是当容器开始崩溃并且 IUse% 从未超过 1% 时。该实例是新启动的,完全为空,根分区为 1TB。我也在非 root RAID0 2TB 分区上进行了尝试,结果相同。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-03-29
    • 2020-02-08
    • 2015-09-22
    • 2017-11-15
    • 1970-01-01
    • 1970-01-01
    • 2020-06-06
    相关资源
    最近更新 更多