Несколько дней новогоднего волшебства:
Успейте начать обучение в 2018-ом году со скидкой до 30%!
Выбрать курс

Память, systemd и контейнеры

Linux_Deep_LAST_26.07.png

Один из простейших вопросов, которые вы получаете на собеседовании на ряду с «что такое LA?» – это «как понять, сколько свободной памяти в системе». Вы смело отвечаете что-то вроде «MemFree + Cached + Buffers», и будете правы. Но потом, в «бою», вы, возможно, будете удивлены приходящему OOM Killer при наличии большого количества свободной памяти.

Операционные системы стараются агрессивно кешировать дисковые операции, и это иногда приводит к разнообразным проблемам. Кроме обеспечения скорости чтения при повторениях это ещё и простой механизм доступа к любому байту при чтении с блочных устройств: жёсткий диск и даже SSD до сих пор даёт читать только блоками.

Кстати, начали задумываться о прямом чтении с SSD, но это long term revolution: очень много механизмов придётся переделать, и в мейнстриме мы это увидим, хорошо, если года через два. Слишком много ПО за 40 лет было спроектировано с оглядкой на поблочное чтение. Например, абсолютно все базы данных хранят данные в страницах, кратных размеру блока.

Но мы отвлеклись!

Все ведь в курсе, что при недостатке памяти ОС будет освобождать память из-под кеша под нужды приложения. И теперь, собственно, анекдот!

В одной весьма известной компании решили уместить на одном хосте примерно несколько сотен контейнеров с простой службой – апачом. Контейнер представлял собой образ операционки, почти не урезанный, благо использовался BTRFS со снапшотами. И все сотни контейнеров много места не занимали (если ещё не знаете, погуглите LVM Thin Provision – интересная технология, пригодится).

Но при запуске всех контейнеров к процессам в контейнерах приходит пушной зверёк по имени OOM Killer. Cache size показывался в районе половины памяти. Сначала не поверили, посчитали awk'ом сумму резидентной памяти всех процессов. Совпадает.

Пособирали atop'ом потребление ресурсов системы, нашли много интересного (например, действительно вылезающий в своп апач) и даже немного расслабились. Но проблема не ушла. Попробовали сбросить кеши:

echo 3 > /proc/sys/vm/drop_caches

И увидели что память из-под кеша не освобождается, хотя должна.

И тут стали думать

Проблема была ещё в том, что проявлялось это не сразу, а через час/два/три после рестарта фермы. Долго ли, коротко ли, но проблему мы нащупали. Посмотрели на различия с предыдущей реализации контейнеров.

Новые контейнеры стали стильные-модные-молодёжные - с systemd. С приходом systemd поменялась раскладка файлов по диску (исторический анекдот: «/usr» появился просто потому что диски были маленькие). Кроме объединения «/» и «/usr» стал активно использоваться tmpfs. А в «/tmp» (tmpfs) стал жить ротируемый журнал journald. Ну подумаешь, несколько мегабайт всего, кто заметит. Но эти несколько мегабайт, помноженные на сотни контейнеров — уже значительный кусок памяти. И главное: tmpfs аллоцирует память в кеше.

Решение было тривиальное Поменяли режим сохранения журнала в контейнерах на persistent. И проблемы больше не было, а вы узнали чуть больше о том, что такое «свободная память».

Есть вопрос? Напишите в комментариях!

Автор
0 комментариев
Для комментирования необходимо авторизоваться