Настройка swap Linux: почему сервис падает при пике памяти
Аварийный перезапуск сервиса случается в разгар пиковой нагрузки на сервер, хотя мониторинг в этот же момент показывает свободную память. Это не ошибка графиков: нехватка оперативной памяти проявляется не в общем объёме, а в доступности страниц в нужной зоне и в способности ядра выделить непрерывный участок. В логах Linux это выглядит так: oom killer завершил процесс, а супервизор поднял его заново.
Жертву ядро выбирает по oom_score с поправкой oom_score_adj, и чаще всего ей становится основной рабочий процесс, а не тот, кто накопил утечку: у долгоживущего сервиса выше потребление — выше и шанс попасть под завершение. Перезапуск возвращает соединения, но теряет недописанные транзакции, а через несколько минут картина повторяется, если причину не устранили.
Настройка swap Linux в этой схеме — не «добавить медленной памяти», а выдать ядру буфер времени: выгрузить холодные страницы вместо немедленного завершения процесса на первом же пике. vm.swappiness определяет, насколько охотно вытесняются анонимные страницы, а лимиты cgroup и режим vm.overcommit_memory — кому и сколько вообще разрешено занять.
Разбираем, как это закрывается: по каким метрикам приближение к отказу видно раньше самого OOM, как считаются лимиты по группам процессов и что делать, если рабочий набор сервиса уже не влезает в память.
Эффект управляемой подкачки: отклик и стабильность
Эффект управляемой подкачки видно не по графику свободной памяти, а по числу инцидентов. После того как swap и политика реакции на нехватку памяти настроены под профиль нагрузки, сервис на пиках уходит в предсказуемую деградацию: часть операций замедляется, но процессы не гибнут и не тянут за собой соседние. Ниже — проверки, по которым мы принимаем работу.
- Аварийные перезапуски. Число падений процессов по нехватке памяти падает на порядок: вместо десятков событий остаются единичные, и каждое разбирается как аномалия, а не как фон.
- Предсказуемая деградация. Под пиком растёт время ответа, но очереди не рвутся: холодные страницы уходят в подкачку, горячий рабочий набор остаётся в памяти, отказ сервиса не наступает.
- Ровный отклик на всплесках. Порог свободных страниц и агрессивность вытеснения выставлены под нагрузку, поэтому короткие bursts проходят без провалов — сервис замедляется плавно, а не обрывается.
- Изоляция последствий. Лимиты памяти для групп процессов и ранний убийца по давлению на память разбираются только с проблемным сервисом; соседи на той же машине не теряют доступность.
- Снятый класс инцидентов. Ночные подъёмы и страницы дежурного из-за падений по памяти уходят из потока — остаются задачи на плановое расширение, а не на тушение.
- Быстрый возврат. После пика сервис входит в рабочий режим за десятки секунд, без повторного прогрева кэша и ручного вмешательства.
Каждый пункт проверяем на стенде с воспроизводимым профилем нагрузки: снимаем метрики до и после, сравниваем частоту перезапусков и поведение на пределе. Так эффект подкачки становится измеримым, а не декларативным.
Способы организации подкачки: сравнение и ограничения
Выбор носителя подкачки определяет не только доступный объём, но и время отклика в момент исчерпания памяти. Ядро опрашивает активные области подкачки в порядке убывания приоритета, поэтому swap-файл на быстром локальном накопителе и ёмкий раздел на медленном массиве спокойно сосуществуют: горячие страницы уходят на быстрый, холодные — на объёмный. Ошибка начинается там, где под подкачку отдают носитель, не рассчитанный на постоянную запись.
| Вариант | Когда подходит | Ограничения |
|---|---|---|
| Swap-файл на локальном накопителе | Быстро развернуть, изменить размер, добавить вторую область | Требует свободного места в файловой системе, при изменении размера фрагментируется |
| Отдельный раздел подкачки | Предсказуемая задержка, серверы без гибернации, СУБД | Размер фиксируется при разметке, меняется только переразбивкой |
| Сжатая подкачка в оперативной памяти | Малопамятные виртуальные машины, узлы без локального диска | Тратит процессорные такты, не спасает при настоящем дефиците памяти, не переживает перезагрузку |
| Том на менеджере логических томов | Нужно менять размер на ходу без остановки служб | Дополнительный слой абстракции, снапшоты незаметно съедают место |
| Область на удалённом блочном устройстве | Кластеры без локальных дисков, аварийный резерв | Сетевая задержка делает её бесполезной под нагрузкой |
Приоритет областей подкачки задаётся явно — в записи файловой системы или ключом при подключении, — иначе порядок заполнения окажется случайным. Подбор swappiness ведут по профилю нагрузки: для сервисов с большим файловым кэшем значение снижают, для виртуальных машин и тонких клиентов поднимают. Решение принимают не по вкусу, а по счётчикам промахов страничных отказов и данным о давлении на память — тогда подкачка закрывает пики, а не маскирует нехватку памяти.
Порядок работ: от аудита памяти до передачи регламентов
Начинаем не с правки конфигурации, а с фактов: без профиля потребления любая настройка параметров памяти превращается в угадывание. Такой порядок исключает типовой сценарий, когда подкачку включают «на всякий случай» и получают просадку отклика или внезапный перезапуск сервиса в час пик.
- Аудит потребления памяти. Снимаем метрики по процессам и группам: пиковое и среднее потребление, доля анонимных страниц, поведение в часы нагрузки. Отдельно смотрим, кто удерживает память после всплеска.
- Схема размещения подкачки. Определяем, нужен ли файл подкачки или отдельный раздел, на каком носителе и какого размера. Фиксируем, какие данные допустимо вытеснять, а какие обязаны оставаться в оперативной памяти.
- Настройка порогов и аварийного завершения. Задаём интенсивность вытеснения, лимиты для групп процессов и приоритеты, по которым ядро выбирает жертву при нехватке памяти. Явные приоритеты надёжнее автоматического выбора.
- Проверка под нагрузкой. Прогоняем сценарии с искусственным дефицитом памяти и смотрим результат: растёт ли задержка отклика, срабатывает ли аварийное завершение и какие процессы гибнут первыми.
- Наблюдаемость. Ставим оповещения на приближение к лимитам, на рост вытеснения и на факт аварийного завершения — инцидент становится виден до того, как упадёт сервис.
- Передача регламентов. Отдаём схему размещения подкачки, значения параметров с обоснованием, процедуру отката и чек-лист действий при резком росте потребления.
Комплект документов и конфигураций после внедрения
После внедрения у команды остаются не только рабочие настройки, но и документы, по которым их можно менять и передавать без нас. Ниже — перечень артефактов, которые заказчик получает вместе с результатом. Каждый рассчитан на дежурного инженера, который откроет его в момент инцидента, а не «когда-нибудь прочитаем».
- Конфигурация подкачки — файл или раздел с записью в fstab, значения vm.swappiness, overcommit и cache_pressure, рядом комментарий: почему выбрано такое поведение и что изменится при возврате к значениям по умолчанию.
- Политики по сервисам — лимиты памяти в cgroup и приоритеты oom_score_adj: кто получает шанс выжить под давлением, кого ядро освобождает первым.
- Схема размещения — на каком узле и носителе лежит область подкачки, как она соотносится с томами данных и где узкие места по дисковым операциям.
- Регламент дежурной смены — пошаговые действия при росте потребления памяти и срабатывании OOM Killer: что смотреть, что перезапускать, когда звать старшего инженера.
- Документация по памяти — профиль потребления по сервисам, границы нормы, типовые причины роста и журнал изменений настроек.
- Проверки и план отката — метрики, оповещения и команды диагностики в готовом виде плюс порядок возврата предыдущего профиля, если изменения ухудшили поведение сервиса.
Отдельно фиксируем владельцев: кто в вашей команде пересматривает лимиты при росте нагрузки и по каким признакам запускается пересмотр.
Кейс: устранение аварийных перезапусков при пиках
Сервис под нагрузкой вёл себя ровно, но в пиковые часы упирался в память. Ядро, не найдя свободных страниц, аварийно завершало самые тяжёлые процессы — вместе с ними уходил весь узел. Итог: семь инцидентов в месяц, каждый с ручным разбором; восстановление занимало до 45 минут, и часть запросов в это окно терялась.
Что изменили
Разделили два разных сценария — короткий всплеск и устойчивую нехватку памяти. Под всплески отвели область подкачки на отдельном томе: она даёт ядру запас, чтобы дождаться освобождения памяти, а не завершать процессы. Для контейнеров задали жёсткие лимиты и порядок завершения — первым уходит фоновый обработчик, фронтальный сервис остаётся в строю.
За потреблением следили через Prometheus: алерт на устойчивый рост настроен так, чтобы срабатывать раньше аварийного механизма. Это дало разбор причины до сбоя, а не после.
Изменения закрепляли тремя месяцами наблюдений. Сводка до и после:
| Показатель | До | После |
|---|---|---|
| Аварийные перезапуски сервиса | 7 в месяц | 1 за квартал |
| Время восстановления сервиса | до 45 минут вручную | до 3 минут автоматически |
| Пики, поглощённые подкачкой | не измерялись | 9 из 10 |
| Ночные вызовы дежурного | 4–6 в месяц | 0 |
Подкачка при этом не маскирует утечку: если потребление растёт линейно, приходит алерт, и причину разбирают до того, как закончится запас.
Чем swap-файл отличается от отдельного раздела?
С точки зрения ядра разницы почти нет: и файл, и раздел после инициализации становятся блочным устройством, которое подключается одной командой. Разница проявляется в том, как этот объём создаётся, меняется и переживает пересборку диска.
Выделенный раздел — заранее отрезанный кусок разметки. Ядро обращается к нему напрямую, без прослойки файловой системы, поэтому накладные расходы на ввод-вывод ниже, а поведение под нагрузкой предсказуемее. Плата за это — жёсткость: размер фиксируется в момент разметки, и чтобы его изменить, приходится трогать таблицу разделов и часто перезагружаться. Такой вариант берут там, где подкачка связана с гибернацией: ядру нужен непрерывный участок диска, описываемый в параметрах загрузки.
Файл подкачки живёт в существующей файловой системе. Его создают и подключают на ходу, размер меняют без остановки сервисов, а несколько файлов с разными приоритетами позволяют разложить нагрузку по разным дискам. Ограничения наследуются от файловой системы: на части сетевых и копирующих хранилищ такой файл не работает, а при гибернации требует ручного расчёта смещения.
На разметку это влияет напрямую: раздел отъедает место заранее и заставляет планировать схему при установке, файл оставляет разметку плоской и даёт подгонять объём подкачки под реальную нагрузку. Отсюда и выбор: физические серверы с гибернацией — раздел; виртуальные машины, хосты контейнеров и облако — файл, потому что менять разметку там дороже, чем убрать или добавить файл.
Частые вопросы по поведению системы при нехватке памяти
Перед стартом работ всплывают одни и те же сомнения: не начнёт ли сервис падать чаще, не просядет ли отклик, что изменится в контейнерах и можно ли обойтись без перезагрузки узла. Часть вопросов снимается на диагностике — по счётчикам убийств процессов, статистике vmstat и лимитам cgroup видно, что происходит сейчас и чем это грозит под нагрузкой.
Как понять, что сервис упал именно из-за памяти?
Запись в журнале ядра называет процесс-жертву и причину — исчерпание памяти узла или лимита группы. Если строки об убийстве нет, а процесс всё равно завершился, причину ищем в приложении: утечка, собственный ограничитель, ошибка в обработке пика. Разница принципиальна: в одном случае настраиваем ядро, в другом правим код.
Нужна ли подкачка, если оперативной памяти хватает?
Подкачка не ускоряет работу, но держит запас на пике: редко используемые страницы уходят на диск вместо запуска убийства процесса. Отключать её стоит только там, где важна предсказуемая задержка, — и тогда лимиты задаются жёстче, с явным резервом под пиковую нагрузку.
Не станет ли сервис работать медленнее?
Пока активные страницы остаются в памяти, отклик не меняется. Просадка начинается при активном вытеснении: её видно по полям ввода-вывода в vmstat и по росту времени ответа. Поэтому значение swappiness подбирают под профиль нагрузки, а не оставляют унаследованным.
Как это работает в контейнерах и применяется ли без перезагрузки?
Внутри контейнера действуют лимиты группы, а не память узла: жертву выбирает ядро хоста, но по приоритетам внутри группы, поэтому параметры согласуют на двух уровнях. Большинство значений меняется на лету, остальные фиксируются в конфигурации — перезагружать узел не нужно, достаточно перезапустить контейнер.
Обсудим задачу и вернёмся с планом внедрения
Старт всегда одинаковый: сначала разбор ситуации, потом оценка и план внедрения, и только затем изменения на живых серверах. Мы не трогаем параметры памяти «по ощущениям» — сначала нужно увидеть, как swap и механизм аварийного завершения процессов ведут себя под вашей реальной нагрузкой. Для этого достаточно описания задачи и доступа к наблюдениям за системой, а не полного доступа к продакшену на первом шаге.
- Разбор ситуации. Фиксируем, какие сервисы живут на хосте, какие у них пики потребления памяти и что уже происходило: были ли перезапуски, «замирания» под нагрузкой, внезапные падения процессов.
- Сбор исходных данных. Смотрим текущие параметры подкачки, лимиты памяти для контейнеров и служб, историю срабатываний аварийного завершения процессов. Это отвечает на вопрос, где именно теряется память.
- Оценка работ. Определяем объём изменений, порядок шагов, окна для правок и точки отката. Вы получаете оценку и план до того, как что-то поменяется на серверах.
- План внедрения. Согласуем, какие пороги и приоритеты выставляем, какие процессы защищаем от завершения, как настраиваем аварийное освобождение памяти, чтобы оно било по нужной цели.
- Внедрение и проверка. Меняем конфигурацию, прогоняем нагрузочный профиль и убеждаемся, что под пиком система не уходит в перезапуск. Результат — предсказуемое поведение вместо внезапных падений.
- Передача. Отдаём конфигурации, схему принятых решений и метрики, по которым изменения видно на графиках.
Чтобы начать, опишите задачу: что за сервисы, какие симптомы беспокоят и что уже пробовали. Вернёмся с оценкой и планом внедрения — без обязательств запускать работы сразу.







