Большой объем RAM не гарантирует высокую скорость Linux. Ядро использует оперативную память для анонимных страниц процессов, файлового кэша, структур ядра и буферов ввода-вывода. Часть этого объема можно быстро освободить, поэтому значение used в free или top само по себе не показывает дефицит памяти.
Page cache ускоряет повторное чтение файлов, swap временно сохраняет редко используемые анонимные страницы, а механизм reclaim освобождает доступные ресурсы под нагрузкой. Производительность начинает падать, когда системе приходится постоянно сканировать и вытеснять страницы, выполнять активный swap-in и swap-out, ждать диск или сокращать рабочие наборы процессов. OOM-killer срабатывает позже, когда reclaim и swap уже не позволяют удовлетворить запрос на выделение памяти.
Для диагностики смотрите на available, memory pressure, активность si/so в vmstat, задержки I/O, RSS процессов и сообщения ядра. Очистка page cache или отключение swap без подтвержденной причины обычно маскирует симптомы и может ускорить переход системы в OOM.
Почему большой объем RAM не гарантирует высокую скорость
RAM влияет на скорость через несколько механизмов. Процессор получает данные быстрее из памяти, чем с накопителя, а Linux старается использовать свободные страницы для кэширования файлов. При росте нагрузки ядро освобождает часть кэша, перераспределяет страницы между процессами и файловой системой, после чего может подключить swap.
Проблема появляется, когда рабочий набор приложения больше доступного физического ресурса или постоянно меняется. В такой ситуации ядро тратит время на reclaim, процессы блокируются на операциях памяти и диска, а пользователи видят рост latency. Нулевое значение free может быть штатным состоянием, если available остается высоким и swap не активен.
Что именно занимает оперативную память
Основные категории памяти в Linux имеют разную цену освобождения:
- Anonymous memory, или анонимная память, хранит heap, stack и другие данные процессов, которые не связаны напрямую с файлом на диске. Для вытеснения таких страниц требуется swap или завершение процесса.
- File-backed memory связана с отображенными файлами и библиотеками. При необходимости ее можно перечитать из исходного файла.
- Page cache хранит содержимое файлов после операций чтения и часть данных перед записью на диск.
- Slab содержит структуры ядра, включая кэш inode и dentry. Часть slab можно освободить, часть нужна ядру постоянно.
- Kernel memory включает служебные структуры, сетевые буферы и другие объекты, которыми управляет ядро.
Команда free -h показывает несколько важных строк:
total used free shared buff/cache available
Mem: 31Gi 18Gi 1.2Gi 420Mi 12Gi 11Gi
Swap: 4Gi 0B 4Gi
В этом примере свободно только 1,2 GiB, однако ядро оценивает доступный объем в 11 GiB. Показатель available учитывает свободную память и часть page cache, которую можно вернуть приложениям без тяжелого swap. Именно его динамику полезно сопоставлять с нагрузкой.
Показатели buff/cache и used нельзя складывать или трактовать как жестко занятую память. Для детального разбора применяйте /proc/meminfo, где видны MemAvailable, Cached, SwapCached, Slab, SReclaimable, AnonPages и другие счетчики.
Когда загрузка RAM становится проблемой
Нагрузка на память становится практической проблемой при сочетании нескольких признаков:
MemAvailableбыстро сокращается во время обычной рабочей нагрузки;- растут
siиsoвvmstat; - увеличивается memory PSI, особенно показатель
full; - растет latency диска и время ответа сервисов;
- рабочие наборы приложений не помещаются в RAM, поэтому одни и те же страницы постоянно загружаются и вытесняются;
- в журналах появляются сообщения reclaim, allocation failure или OOM.
Система может заметно тормозить задолго до OOM. OOM означает крайнюю точку, когда конкретный запрос на память не удалось удовлетворить. До нее процессы могут долго ждать reclaim и I/O, а CPU при этом будет загружен умеренно. Для общего набора метрик удобно использовать рабочий список показателей производительности Linux-сервера.
Кэш памяти в операционной системе: как работает page cache в Linux
Page cache хранит страницы файлов в оперативной памяти. Ядро использует их для ускорения повторного доступа и сглаживания разницы между скоростью приложения и накопителя. Размер кэша меняется динамически: при нехватке RAM clean pages можно вытеснить и прочитать заново.
Как работает page cache в Linux при чтении файлов
При первом чтении файл обычно проходит такой путь:
- Приложение вызывает операцию чтения.
- Ядро проверяет, есть ли нужные страницы в page cache.
- При промахе ядро ставит запрос к файловой системе и накопителю.
- Полученные страницы помещаются в RAM и передаются приложению.
- Повторное чтение тех же данных может обслуживаться из памяти без обращения к диску.
Эффект зависит от локальности доступа. Последовательное чтение часто получает помощь read-ahead: ядро заранее загружает соседние страницы, предполагая продолжение операции. При случайном доступе такой прогноз работает слабее, а маленькие обращения к большим файлам могут давать высокую latency даже при заметном объеме свободной RAM.
Page cache полезен для файловых серверов, баз данных, сборки проектов, контейнерных образов и логов. Его размер не задают как постоянный процент RAM. Ядро само сопоставляет доступную память, активность страниц и приоритеты reclaim.
Dirty pages, write-back и задержки записи
При записи приложение может сначала изменить страницу в RAM. Такая страница получает статус dirty, пока ядро не отправит ее содержимое на накопитель. Фоновый write-back постепенно сбрасывает грязные страницы, чтобы не создавать резкий пик I/O.
Быстрая запись в системный вызов не всегда означает, что данные уже лежат на диске. Приложение, которому нужна гарантия сохранения, вызывает fsync, fdatasync или использует эквивалентный механизм библиотеки. В этот момент оно может ждать завершения записи и получить latency, близкую к задержке накопителя.
При интенсивной записи объем dirty pages растет, если приложение производит данные быстрее, чем устройство их сохраняет. Когда достигаются пороги фоновой записи, ядро увеличивает давление на I/O. При достижении предельных значений новые записи могут блокироваться, пока накопитель не уменьшит очередь.
Проверяйте Dirty, Writeback и связанные счетчики в /proc/meminfo, а задержки и очередь устройства смотрите через iostat -xz 1. Сочетание большой очереди, высокого await и роста времени ответа приложения указывает на ограничение хранилища, а не на одну лишь нехватку RAM.
Почему очистка кэша редко ускоряет сервер
Clean page cache, который ядро может перечитать с диска, относится к reclaimable-памяти. При необходимости Linux освобождает ее автоматически. Ручной сброс удаляет прогретые страницы, после чего следующие операции снова обращаются к накопителю.
Для контролируемого сравнения дисковой подсистемы иногда применяют:
sync
printf 1 | sudo tee /proc/sys/vm/drop_caches
Значение 1 просит ядро освободить page cache, 2 используется для dentries и inode, 3 объединяет оба действия. Такой тест нужно выполнять вне критичного окна и фиксировать результаты нескольких повторов. Перед этим полезно дождаться завершения записи через sync.
В production очистка page cache не устраняет утечку памяти, чрезмерный рабочий набор, неверный лимит контейнера или медленный диск. Частый запуск команды создает повторные промахи по кэшу и способен увеличить latency.
Как работает swap в Linux и когда он замедляет систему
Swap предоставляет ядру место для хранения страниц, которые временно не помещаются в RAM. Чаще всего туда перемещаются редко используемые anonymous pages. File-backed pages можно вытеснить без записи в swap, если их содержимое доступно в исходном файле и не изменялось.
Какие страницы попадают в swap
Приложение может выделить несколько гигабайт памяти, но активно обращаться только к небольшой части. Неиспользуемые страницы такого процесса ядро может отправить в swap, освободив RAM под page cache или рабочий набор другого сервиса.
Когда процесс обращается к выгруженной странице, возникает page fault. Ядро читает страницу из swap, может вытеснить другую страницу и продолжает выполнение. Один такой обмен во время пикового запуска часто переносится нормально. Постоянные обмены между RAM и накопителем приводят к thrashing.
Занятый swap не означает, что система уже работает медленно. Страницы могли быть выгружены час назад и больше не понадобиться. Оценка должна учитывать текущую скорость swap-in, swap-out, memory PSI и latency приложений.
Как распознать активный swap и thrashing
Быстрый снимок виртуальной памяти дает команда:
vmstat 1
Важные поля:
swpdпоказывает объем используемого swap;siотражает чтение страниц из swap;soотражает запись страниц в swap;rпоказывает очередь готовых к выполнению задач;bпоказывает задачи, ожидающие завершения блокирующих операций;waпомогает заметить время ожидания I/O.
Высокие si и so, рост b и wa, увеличение latency диска и падение throughput образуют типичный профиль активного swap. Load average может расти при невысокой загрузке CPU, потому что процессы ждут страницы или операции I/O.
Для истории полезны sar -W 1, метрики накопителя и графики memory PSI. Один короткий всплеск swap не равен thrashing. Ищите устойчивую активность, совпадение с ростом времени ответа и повторяющийся цикл вытеснения одних и тех же страниц.
vm.swappiness, zram и zswap
Параметр vm.swappiness задает склонность ядра выбирать reclaim anonymous memory относительно reclaim файловых страниц. Он не означает прямой процент использования swap и не задает момент, когда swap заполнится.
Снижение значения может сохранить больше anonymous pages в RAM и отложить swap, но при этом сократить место под page cache. Повышение значения помогает раньше выгружать редко используемые страницы и сохранять файловый кэш. Результат зависит от рабочей нагрузки, соотношения чтения и записи, размера RAM и скорости накопителя.
Проверить текущее значение можно так:
sysctl vm.swappiness
Zram создает сжатое блочное устройство в RAM и использует его как swap. Диск при этом не участвует, но часть CPU и памяти уходит на сжатие. Такой механизм полезен на системах с ограниченной RAM и приемлемой нагрузкой на процессор.
Zswap работает как сжатый кэш перед основным swap-устройством. Ядро сначала пытается сохранить страницу в сжатом пуле, а при заполнении пула отправляет ее в обычный swap. Zswap может уменьшить обращения к диску, но тоже расходует CPU и RAM.
Меняйте один параметр за раз и сравнивайте vmstat, PSI, latency, throughput и CPU. Копирование значения vm.swappiness из чужой конфигурации без такой проверки не дает предсказуемого результата.
Когда swap полезен, а когда нужен дополнительный объем RAM
Swap полезен как буфер для кратковременных пиков и как место для редко используемых страниц. Он снижает вероятность немедленного OOM при коротком всплеске, если накопитель выдерживает дополнительные операции.
Дополнительная RAM нужна, когда swap используется постоянно, active working set стабильно превышает доступный объем, memory PSI растет, а сервисы теряют latency. Причиной может быть утечка, рост числа запросов, слишком высокая параллельность, крупный кэш приложения или заниженные лимиты.
Размер swap выбирают по сценарию. Для серверов баз данных, высоконагруженных очередей и систем реального времени приоритетом часто становятся предсказуемая latency и запас RAM. Для универсального Linux-сервера swap остается полезной страховкой, но его наличие не компенсирует систематическую нехватку физической памяти.
Давление на память: как увидеть проблему до OOM
Memory pressure описывает цену нехватки памяти в виде ожидания. При дефиците ресурсов процессы могут простаивать, пока ядро освобождает страницы, читает swap или завершает операции записи. Один показатель использования RAM этого состояния не отражает.
PSI и /proc/pressure/memory
Linux Pressure Stall Information показывает, сколько времени задачи проводят в ожидании ресурса. Для памяти доступны строки some и full:
someрастет, когда хотя бы одна не простаивающая задача ждет память;fullрастет, когда все не простаивающие задачи в группе одновременно задержаны из-за памяти.
Проверка выполняется командой:
cat /proc/pressure/memory
Пример вывода:
some avg10=1.25 avg60=0.48 avg300=0.12 total=1843921
full avg10=0.31 avg60=0.08 avg300=0.01 total=482110
avg10, avg60 и avg300 показывают долю времени ожидания за 10, 60 и 300 секунд. total хранит суммарное время ожидания в микросекундах с момента запуска или сброса счетчика. Краткий пик avg10 может совпасть с запуском тяжелой задачи. Устойчивый рост avg60 и avg300 уже требует проверки рабочей нагрузки.
PSI удобно связывать с SLO сервиса. Например, рост memory.some вместе с p95 latency базы данных дает более сильный сигнал, чем алерт только на 90 процентов занятой RAM.
vmstat и признаки работы reclaim
Для первичной проверки сохраните несколько десятков строк vmstat, а не одно значение:
date
free -h
vmstat 1 30
cat /proc/pressure/memory
swapon --show
Сопоставляйте вывод по времени:
- падение
availableбез swap и PSI может означать обычный рост page cache; - рост
si/soвместе сwaуказывает на обмен страниц с накопителем; - рост
bпри высокой очереди диска показывает блокирующее ожидание I/O; - высокие
rпри низкихwaиsi/soбольше похожи на дефицит CPU; - увеличение slab или kernel memory требует отдельного разбора структур ядра, сетевых буферов и файловой системы.
Команда sar -r 1 помогает собрать историю использования памяти, а sar -W 1 показывает операции swap. Исторические данные особенно полезны после восстановления сервиса, когда разовый снимок уже не отражает пик инцидента.
Симптомы memory pressure на уровне сервисов
Пользователь обычно видит не слово pressure, а последствия:
- растет время ответа HTTP или RPC;
- появляются таймауты и повторные запросы;
- снижается throughput при прежнем числе CPU;
- SSH открывает сессию с задержкой;
- очереди задач растут быстрее, чем обрабатываются;
- периодически завершаются worker-процессы;
- сервисы теряют соединения из-за задержек heartbeat.
Связывайте эти симптомы с временными рядами памяти, swap, диска, CPU и трафика. Практический порядок проверки узких мест собран в руководстве по мониторингу производительности сервера в Linux.
OOM killer Linux: почему ядро завершает процессы
OOM-killer Linux завершает выбранный процесс, когда ядро не может удовлетворить запрос на память после попыток reclaim и использования доступного swap. Это аварийный механизм сохранения работоспособности системы, а не обычный способ управления нагрузкой.
Что такое OOM killer и когда он срабатывает
Путь к OOM обычно выглядит так:
- Процесс запрашивает дополнительные страницы памяти.
- Ядро проверяет доступные страницы и допустимость выделения с учетом overcommit.
- Запускается reclaim, очищаются доступные файловые страницы, при необходимости выполняется swap.
- Если выделение все равно не удается, ядро выбирает процесс-жертву.
- Память процесса освобождается, а в журнал попадает запись о событии.
Причиной может быть нехватка user memory, исчерпание обязательных резервов ядра, жесткий лимит cgroup или политика overcommit. Системный OOM на узле и cgroup OOM внутри контейнера имеют похожие симптомы, но требуют разной проверки.
Факт наличия свободного места в swap не исключает OOM. Не вся память пригодна для выгрузки, запрос может превышать лимит группы, а ядру может требоваться непрерывный или зарезервированный ресурс. Оценка зависит от типа выделения и текущего состояния системы.
Как выбирается процесс-жертва
Ядро рассчитывает оценку OOM для процессов с учетом их потребления и других факторов. Значение /proc/PID/oom_score показывает текущую склонность процесса стать жертвой, а /proc/PID/oom_score_adj позволяет изменить приоритет:
cat /proc/1234/oom_score
cat /proc/1234/oom_score_adj
Положительное значение oom_score_adj повышает вероятность выбора, отрицательное снижает ее. Значение -1000 защищает процесс от выбора OOM-killer, но такая защита может перенести завершение на другой сервис и ускорить отказ узла. Системные компоненты нельзя защищать без оценки последствий.
Самый большой RSS-процесс не всегда становится жертвой. Решение зависит от oom_score_adj, контекста cgroup, типа памяти и других условий. Имя завершенного процесса помогает найти точку отказа, но первопричиной мог быть соседний сервис, который постепенно наращивал потребление.
Где искать события OOM
Проверяйте сообщения текущего ядра и журнал загрузки:
dmesg -T | grep -i -E 'out of memory|killed process|oom'
journalctl -k -b | grep -i -E 'out of memory|killed process|oom'
В записи OOM ищите:
- время события;
- имя и PID процесса;
total-vm;anon-rssиfile-rss;oom_score_adj;- название cgroup или контейнера;
- признаки global OOM либо локального cgroup OOM.
Если журнал ротировался или сообщения ядра пересылаются в отдельную систему, ищите событие по времени, PID и имени сервиса во всех доступных источниках. После аварии полезно сопоставить его с графиками RSS, memory.current, PSI, swap и числом запросов.
Практическая диагностика: от симптома к причине
Диагностику начинайте с фиксации состояния. Изменение параметров до сбора данных может убрать признаки, которые нужны для поиска причины. Для общей последовательности анализа можно использовать материал о порядке диагностики снижения производительности автоматизированных систем.
Базовый снимок состояния сервера
Соберите команды с временной меткой и повторите их во время пика:
date -Is
uptime
free -h
vmstat 1 10
cat /proc/pressure/memory
swapon --show
ps -eo pid,ppid,comm,rss,vsz,%mem --sort=-rss | head -n 20
iostat -xz 1 3
journalctl -k -b --no-pager | tail -n 200
Запишите, когда началась деградация, какие сервисы изменяли нагрузку, был ли релиз, запуск резервного копирования, рост трафика или изменение числа worker-процессов. Временная корреляция часто отделяет утечку от штатного роста рабочей нагрузки.
Как найти процесс, который расходует память
ps сортирует процессы по RSS, но RSS включает страницы, разделяемые с другими процессами. VSZ показывает виртуальное адресное пространство и может быть большим без соответствующего расхода физической RAM.
Для первого списка используйте:
ps -eo pid,ppid,user,comm,rss,vsz,%mem --sort=-rss | head -n 20
top -o %MEM
Для более точного распределения памяти применяйте PSS, который делит shared pages между владельцами. Инструмент smem показывает PSS, USS и RSS, а pidstat -r -p PID 1 помогает наблюдать fault и динамику процесса. Для контейнеров смотрите потребление cgroup, потому что сумма RSS процессов не всегда совпадает с показателем группы.
Память приложения нужно сопоставлять с его внутренними метриками: heap, connection pool, очередями, кэшем, числом worker и размером обрабатываемых объектов. Один RSS редко объясняет причину полностью.
Как отличить утечку памяти от тяжелой рабочей нагрузки
Утечка обычно проявляется монотонным ростом RSS или heap после снижения трафика и отсутствием возврата к прежнему уровню. При штатной нагрузке потребление растет вместе с объемом данных, числом запросов или размером рабочего набора, затем стабилизируется около некоторого уровня.
| Признак | Вероятная причина | Что проверить |
|---|---|---|
| RSS растет после каждого запроса и не снижается | Утечка или неограниченный кэш | Профиль памяти, heap, освобождение объектов |
| Page cache растет при чтении файлов | Прогрев файлового кэша | Cached, MemAvailable, повторное чтение |
| RSS меняется вместе с трафиком | Рабочий набор приложения | Количество запросов, очереди, размер данных |
Растут si/so и PSI | Физической памяти не хватает | Swap, latency диска, лимиты cgroup |
Снимайте данные в течение нескольких интервалов нагрузки. Одно измерение после перезапуска процесса не позволяет отличить утечку от разогрева кэша.
Проверка диска и I/O при активном swap
Swap использует накопитель, поэтому его цена зависит от latency, throughput и конкурирующих операций. Медленный или перегруженный диск увеличивает время page fault и блокирует сервисы, которые используют тот же ресурс.
iostat -xz 1
pidstat -d 1
cat /proc/diskstats
В iostat проверяйте await, aqu-sz, %util, скорость чтения и записи. Высокая утилизация устройства сама по себе не означает проблему, но сочетание высокой очереди, роста latency и активного swap указывает на насыщение.
Отдельно выясните, кто создает I/O: swap, журнал, база данных, резервное копирование или массовая запись логов. Подробный разбор IOPS, latency, throughput и очередей есть в статье о влиянии дисков и файловых систем на производительность серверов.
Что делать при нехватке памяти: безопасная настройка и порядок действий
Порядок действий зависит от того, идет ли активный инцидент или плановая настройка. Сначала остановите рост потребления и сохраните данные диагностики. Затем исправляйте лимиты, рабочую нагрузку и код, а параметры виртуальной памяти меняйте после измерений.
Приоритет мер во время инцидента
- Зафиксируйте время,
free -h,vmstat, PSI, список процессов и журнал ядра. - Снизьте параллелизм, временно остановите необязательные batch-задачи, резервное копирование или воркеры.
- Ограничьте runaway-процесс или корректно остановите сервис, который продолжает расти.
- Проверьте cgroup и systemd-лимиты, чтобы понять, где возник дефицит: внутри сервиса или на всем узле.
- После сохранения диагностики перезапустите неисправный процесс, если это согласуется с процедурой восстановления.
Сначала отправляйте процессу SIGTERM, чтобы приложение успело закрыть соединения и сохранить состояние. SIGKILL прерывает работу немедленно и может оставить незавершенные операции, поэтому используйте его при угрозе отказа узла или отсутствии реакции на корректное завершение.
Массовая очистка page cache редко помогает при anonymous memory. Отключение swap во время активного давления может вызвать резкий OOM. Перезапуск всего сервера без сохранения журналов уничтожает контекст инцидента и затрудняет поиск причины.
Настройка swap и параметров виртуальной памяти
Проверьте состояние swap:
swapon --show
free -h
cat /proc/swaps
Swap лучше размещать на предсказуемом и достаточно быстром устройстве, которое не конкурирует с критичными операциями, если архитектура это позволяет. Не задавайте единый размер для всех серверов: базы данных, контейнерные узлы, файловые сервисы и рабочие станции имеют разные требования к latency и пиковому потреблению.
vm.swappiness корректируют после сравнения профилей с разными значениями. vm.vfs_cache_pressure влияет на склонность ядра освобождать кэши inode и dentry относительно page cache. Это не универсальный регулятор скорости диска и не способ исправить утечку памяти.
Изменение для текущей загрузки выглядит так:
sudo sysctl -w vm.swappiness=10
sudo sysctl -w vm.vfs_cache_pressure=100
Числа выше приведены как пример синтаксиса, а не как готовый профиль. Сохраняйте исходные значения, меняйте один параметр и сравнивайте available, PSI, si/so, I/O latency и время ответа сервиса.
Zram подходит, когда нужно сократить обращения к диску ценой CPU и части RAM. Zswap полезен при наличии обычного swap и потребности сжать часто используемые страницы перед записью. Оба механизма требуют проверки на конкретном ядре и рабочей нагрузке.
Если сервер регулярно упирается в память при корректных лимитах и отсутствии утечки, добавление RAM обычно дает более предсказуемый результат, чем агрессивная настройка swap. Для временного увеличения ресурсов можно использовать облачные серверы и VDS Timeweb Cloud, если рабочая архитектура допускает перенос или масштабирование нагрузки.
Лимиты памяти и защита от runaway-процессов
Лимит делает отказ локальным и предсказуемым. В systemd применяют параметры MemoryHigh и MemoryMax:
[Service]
MemoryHigh=2G
MemoryMax=3G
MemoryHigh создает давление и просит группу снизить потребление, а MemoryMax задает жесткий предел. Слишком низкое значение вызывает ранний cgroup OOM внутри сервиса. Слишком высокий лимит оставляет узел без запаса.
В cgroup v2 текущие значения проверяют через memory.current, лимит через memory.max, а события через memory.events. В Docker аналогичный контроль задают при запуске, например --memory=2g. Связанный параметр --memory-swap определяет совокупный предел RAM и swap по правилам конкретной версии Docker, поэтому его проверяют вместе с фактическим поведением контейнера.
Резервируйте память для ОС, daemon-процессов, page cache, сетевых буферов и аварийного запаса. Сумма лимитов приложений, равная всей RAM узла, оставляет систему без пространства для накладных расходов.
Мониторинг и профилактика повторного OOM
Минимальный набор сигналов включает:
MemAvailableи anonymous memory;- memory PSI:
some,full,avg10,avg60,avg300; - скорость swap-in и swap-out;
- RSS, PSS и heap ключевых процессов;
memory.current,memory.eventsиmemory.maxдля cgroup;- latency, очередь и загрузку накопителей;
- события OOM и перезапуски сервисов;
- трафик, число запросов, релизы и изменения конфигурации.
Порог алерта выбирайте по SLO. В качестве стартовой проверки можно отдельно наблюдать устойчивый рост memory.full за минутные и пятиминутные окна, а не реагировать на краткий пик занятой RAM. Алерт должен подсказывать действие: снизить параллелизм, проверить процесс, изучить swap или увеличить ресурс.
Как OOM проявляется в Docker и Kubernetes
Контейнер может завершиться с причиной OOMKilled, хотя на узле еще видна свободная память. Контейнер работает внутри cgroup, а ее лимит может закончиться раньше общего ресурса node. Проверять нужно и состояние группы, и состояние всей машины.
Почему контейнер получает OOMKilled
Причины OOM внутри контейнера:
- рабочий набор приложения превысил
memory limit; - heap или внутренний кэш растет без верхней границы;
- лимит задан ниже реального пикового потребления;
- несколько процессов внутри одной cgroup совместно исчерпали память;
- приложение не учитывает overhead runtime, shared memory и буферы.
Проверьте статус и события контейнера, его фактическое потребление, лимит группы и время завершения. Увеличение swap на узле не обязано исправлять превышение memory.max. При жестком лимите cgroup процесс может получить OOMKilled, пока соседние группы продолжают работать.
Requests, limits и давление на Kubernetes node
requests участвуют в планировании Pod и сообщают планировщику, сколько ресурса нужно зарезервировать для размещения. limits ограничивают потребление контейнера. Эти значения должны отражать рабочий набор и пики, иначе приложение либо получает ранний OOMKilled, либо узел теряет запас памяти.
Когда на node возникает memory pressure, kubelet может начать eviction Pod. Это отличается от cgroup OOM: eviction принимает решение на уровне управления узлом, а OOM-killer реагирует на неудачное выделение памяти. Итоговые действия зависят от QoS-класса, requests, limits, приоритета Pod и настроек кластера.
Если для всех контейнеров Pod requests и limits совпадают, Pod может получить класс Guaranteed. При разнице значений чаще формируется Burstable, а Pod без requests и limits относится к BestEffort. QoS влияет на порядок вытеснения, но не отменяет лимит памяти контейнера.
Swap в Kubernetes зависит от версии kubelet, конфигурации узлов и политики кластера. Не рассчитывайте на него как на замену корректным requests, limits и достаточному объему RAM.
Диагностика OOM в контейнерной среде
Начните с описания Pod и событий:
kubectl describe pod POD -n NAMESPACE
kubectl get events -n NAMESPACE --sort-by=.lastTimestamp
kubectl top pod POD -n NAMESPACE
kubectl top node NODE
В выводе ищите Last State, Reason: OOMKilled, код завершения, время перезапуска и заданные requests или limits. Затем сопоставьте эти данные с метриками cAdvisor, container runtime, memory.current cgroup и node-level PSI.
Если Pod получил OOMKilled при низком memory pressure node, сначала проверяйте его лимит и рабочий набор. Если одновременно растут PSI, swap, I/O latency и потребление нескольких Pod, причина может находиться на уровне узла. Сопоставление временных рядов отделяет проблему приложения от давления всей инфраструктуры.
Короткая памятка: смотрите на available, а не на один показатель used; не считайте page cache утечкой; различайте занятый swap и активный thrashing; проверяйте PSI до OOM; ищите процесс и cgroup в журналах; меняйте vm.swappiness и лимиты после измерений; в Kubernetes разделяйте OOMKilled контейнера и eviction Pod.