0008. Подкачка на узле и разрешение её подам¶
Дата: август 2026. Состояние: принято.
Контекст¶
На узле 3,8 ГБ доступной памяти. Сумма запросов всех подов — около 2,6 ГБ, сумма пределов — существенно больше: пределы поставлены с запасом на пики, и это правильно. Значит, в момент одновременного пика памяти не хватит.
Kubernetes по умолчанию требует, чтобы подкачка была выключена: kubelet не
запускается на узле с включённой подкачкой без явного разрешения. Логика
понятна — подкачка делает поведение непредсказуемым и прячет нехватку памяти
вместо того, чтобы её показать.
Решение¶
Включить файл подкачки 4 ГБ и разрешить подам им пользоваться в ограниченном режиме:
В ограниченном режиме под может вытеснить в подкачку не больше, чем разница между его пределом и запросом. Под, который просит и получает свои гарантированные ресурсы, в подкачку не уходит.
Дополнительно: vm.swappiness снижен до 10 — ядро использует подкачку только при
реальной нехватке, а не для упреждающего вытеснения. Заданы резервы под
системные и служебные процессы, чтобы вытеснение начиналось предсказуемо.
Последствия¶
Что получили. Стенд переживает пики. Часть страниц уходит в подкачку, работа замедляется, но ядро не выбирает жертву само — а выбор мог оказаться неудачным, например Prometheus, то есть ровно тот сервис, который должен показать, что происходит.
Первая же проверка сценария с утечкой памяти показала цену настройки. Балласт был
ограничен 512 МБ — больше, чем куча пода, и больше, чем предел его контейнера.
Под честно исчерпал память и перезапустился, но по пути занял почти всю подкачку
узла, узел объявил нехватку памяти, и kubelet вытеснил тот же под ещё раз, уже
как нарушителя. Наблюдаемость при этом уцелела только потому, что Prometheus
расходовал меньше своего запроса и стоял в очереди на вытеснение последним.
Вывод занесён в настройку: предел балласта опущен до 256 МБ. Сценарий по-прежнему кончается исчерпанием памяти внутри виртуальной машины Java и перезапуском контейнера, но узел до нехватки памяти уже не доходит.
Чем заплатили. Замедление вместо честного отказа. Под, ушедший в подкачку,
отвечает медленно, и это выглядит как деградация приложения, хотя причина — в
узле. Поэтому есть отдельное правило оповещения MetroskopSwapHeavilyUsed:
занятая больше чем на 60 % четверть часа подкачка означает, что памяти не хватает
по-настоящему, и это уже не страховка, а образ жизни.
Второе: подкачка на виртуальном диске сильно медленнее оперативной памяти. Перцентили времени ответа при активной подкачке ухудшаются заметно, и на графике это видно.
Что рассматривалось¶
Без подкачки, как требует умолчание — честнее по поведению, но на этом узле означало бы, что любой пик заканчивается убийством случайного пода. Для стенда, где отказы вызывают нажатием кнопки, это гарантированная потеря наблюдаемости в самый нужный момент.
Уменьшить пределы до запросов — устранило бы перерасход, но лишило бы поды права на пик. Приложение на Java с непредсказуемым поведением сборщика мусора в такой схеме перезапускалось бы регулярно.
Неограниченный режим подкачки — под смог бы уйти в подкачку целиком, и деградация стала бы неограниченной. Ограниченный режим держит её в пределах разницы между пределом и запросом.