Память, systemd и контейнеры | OTUS
⚡ Подписка на курсы OTUS!
Интенсивная прокачка навыков для IT-специалистов!
Подробнее

Курсы

Программирование
C++ Developer. Professional JavaScript Developer. Professional Android Developer. Professional Microservice Architecture React.js Developer JavaScript Developer. Basic PostgreSQL Программист С C++ Developer. Basic Team Lead PHP Developer. Professional Подготовка к сертификации Oracle Java Programmer (OCAJP) Алгоритмы и структуры данных Разработчик IoT C# Developer. Basic Unreal Engine Technical Game Design C# ASP.NET Core разработчик Python Developer. Basic Базы данных Node.js Developer iOS Developer. Professional Cloud Solution Architecture Kotlin Backend Developer Agile Project Manager Scala-разработчик Symfony Framework iOS Developer. Basic Супер-интенсив Azure Специализация Python Developer
Инфраструктура
Экспресс-курс по управлению миграциями (DBVC) Экспресс-курс «IaC Ansible» Microservice Architecture Разработчик программных роботов (RPA) на базе UiPath и PIX Внедрение и работа в DevSecOps NoSQL Специализация Administrator Linux
-24%
Разработчик IoT Мониторинг и логирование: Zabbix, Prometheus, ELK MongoDB
-37%
DevOps практики и инструменты MS SQL Server Developer SRE практики и инструменты Administrator Linux. Advanced Infrastructure as a code Супер-интенсив "Tarantool" Специализация Network engineer
Корпоративные курсы
Экспресс-курс по управлению миграциями (DBVC) Экспресс-курс «IaC Ansible» Разработчик программных роботов (RPA) на базе UiPath и PIX Внедрение и работа в DevSecOps NoSQL Spark Developer Экспресс-курс «CI/CD или Непрерывная поставка с Docker и Kubernetes» Game QA Engineer DevOps практики и инструменты Enterprise Architect Node.js Developer Cloud Solution Architecture Agile Project Manager Супер-практикум по работе с протоколом BGP Infrastructure as a code Промышленный ML на больших данных Супер-интенсив Azure Руководитель поддержки пользователей в IT
Специализации Курсы в разработке Подготовительные курсы Подписка
+7 499 938-92-02

Память, 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. И проблемы больше не было, а вы узнали чуть больше о том, что такое «свободная память».

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

Не пропустите новые полезные статьи!

Спасибо за подписку!

Мы отправили вам письмо для подтверждения вашего email.
С уважением, OTUS!

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