tail в контейнере Docker: невозможно выделить память - PullRequest
0 голосов
/ 23 января 2019

Я бьюсь головой об стену с этим вопросом. Мы запускаем много контейнеров параллельно, они выполняют простые операции с файловой системой или простые команды linux, и некоторые из них при определенных обстоятельствах терпят неудачу из-за проблем с выделением памяти, контейнер Docker получает OOMKiled.

Я считаю, что это не связано с конкретной командой. tail - не единственная неудачная команда, мы также столкнулись с cp или gzip.

Мы сузили проблему и создали сценарий, который почти наверняка завершится ошибкой, если параметры будут настроены в соответствии с базовой системой.

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

Скрипт с настройками по умолчанию генерирует случайный CSV с 100M строками (~ 2,5 ГБ), копирует его 20 раз, а затем запускает 20 контейнеров, работающих tail -n +2 .... В экземпляре m5.2xlarge AWS EC2 с твердотельным накопителем 1 ТБ некоторые контейнеры являются 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 должно вообще потреблять память. Если количество одновременно работающих контейнеров достаточно мало, он может легко выжить с 64 МБ памяти. При большем количестве контейнеров даже 256 МБ недостаточно. Я наблюдал за htop и docker stats и не видел никаких всплесков потребления памяти.

Вещи, которые мы уже попробовали

  • разные Docker imges (альпийский, сентос, убунту)
  • различные файловые системы (ext3, xfs)
  • разные ОС (Centos, Ubuntu)
  • разные поставщики экземпляров (Digital Ocean, AWS)
  • различные типы экземпляров и блочных устройств
  • файловая система swap / swappiness
  • Подкачка и замена памяти Docker

Часть этого помогла только частично. Регулировка предела памяти или количества контейнеров приводила к тому, что он каждый раз снова падал. У нас был контейнер с 1 ГБ памяти, работающий просто tail в случае сбоя большого файла с OOMKilled.

Далее то, что я пробовал несколько месяцев назад - https://500.keboola.com/cp-in-docker-cannot-allocate-memory-1a5f57113dc4. И --memory-swap оказался лишь частичной помощью.

Есть предложения? Я не эксперт по Linux, поэтому я могу упустить что-то важное. Любая помощь или совет с благодарностью.

Ответы [ 2 ]

0 голосов
/ 25 января 2019

Кажется, у вас проблема с "Размер кэша записи".

Когда вы хотите записать что-то на диск, оно не записывается напрямую, а сохраняется в кэше записи (называемом dirty_pages).Это связано с тем, что всем процессам не нужно ждать, пока они получат привилегию для записи на диск и продолжат свою работу.Но когда процесс не получал привилегию для записи на диск в течение длительного времени, его буфер записи начинает расти, пока не достигнет предела памяти, определенного для контейнера.Затем его убивает докер.

Есть демон по имени pdflush, который заботится о очистке кэшей и записи этих dirty_pages на диск.Я думаю, что вы определенно ищете параметры vm.dirty_bytes и vm.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

Надеюсь, это поможет!

0 голосов
/ 23 января 2019

У меня нет представителя, чтобы комментировать, так что угадайте ответ! Мы столкнулись с подобной проблемой, и оказалось, что дисковая память - это не только то, сколько места вы используете в целом - существуют также вещи, называемые inode, которые имеют отдельное конечное число, и такие вещи, как node_modules (в js) или любая форма большой библиотеки небольших файлов или даже файлов журналов может ДЕЙСТВИТЕЛЬНО съесть ваши inode.

Попробуйте ввести это в командной строке (при условии, что вы используете Linux или Mac)

df -ih

Если IUse вашего root (установлен на /) составляет 99%, то это ваша проблема. Вы могли бы иметь кучу устаревших томов Docker с сотнями тысяч файлов, которые занимают все ваше пространство.

Linux часто предлагает небольшой том (20 ГБ) для root (/), а затем большой том для вашего / home, чтобы вместить все ваши личные фотографии котят и т. Д. Однако Docker, если не указано иное, помещает все свои данные в корневом монтировании, так что вы можете очень быстро заполнить его и при этом иметь на своем сервере то, что похоже на большое количество свободного места! Обычно это не относится к профессиональным серверам, но стоит иметь в виду.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...