Когда на малом VDS внезапно «умирает» процесс, в системном журнале часто виден след: OOM‑killer. Это не баг, а защитный механизм ядра Linux: когда оперативная память заканчивается, ядро принудительно завершает наименее «ценный» процесс. Задача администратора — сделать так, чтобы до этого не доходило, а если уж дошло — выжил хотя бы SSH и критичные сервисы.
Как Linux использует память: короткий ликбез
В Linux RAM — не просто «свободно/занято». Значительную часть занимает кэш страниц (page cache) и кеши dentry/inode. Они выталкиваются первыми при росте нагрузки, поэтому «свободной» памяти может быть мало, но система работает стабильно. Нестабильность начинается, когда:
- растут анонимные страницы (heap/stack процессов);
- падает эффективность освобождения кэшей;
- нет swap или он исчерпан;
- жесткие лимиты (cgroups) срабатывают раньше, чем общая система.
Отсюда инструменты: swap (включая компрессированный zram
), параметры sysctl
(vm.overcommit_memory
, vm.swappiness
и другие), а также осознанная изоляция сервисов в cgroup через systemd. Если ваш проект на виртуальном хостинге уже упирается в RAM, рассмотрите переход на VDS — это даст контроль над ядром, swap и cgroup.
Swap: зачем, сколько и как
Swap — это страховка от кратковременных пиков. Он не заменяет RAM и не «ускоряет» сервер, но дает ядру пространство для «холодных» страниц, снижая шанс OOM. Для малых VDS практична связка: компрессированный zram
как быстрый swap в памяти плюс небольшой swap‑файл на диске.
Базовый рецепт swap‑файла
sudo fallocate -l 1G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
sudo swapon --show
Сделайте swap постоянным через /etc/fstab
:
/swapfile none swap sw,pri=10 0 0
Рекомендации по размеру: на малом VDS (1–4 ГБ RAM) начните с 0.5–1× от RAM суммарно, учитывая zram (ниже), и смотрите по реальной нагрузке. Для баз данных и latency‑критичных систем держите swap умеренным и следите за I/O.
ZRAM: компрессированный swap в ОЗУ
zram создает блок‑устройство в оперативной памяти, где данные хранятся в сжатом виде. Сжатие (LZ4/ZSTD) даёт «виртуальное» увеличение доступной памяти при низких задержках. Типовой сценарий: zram со старшим приоритетом, дисковый swap с младшим.
Вариант 1: zram‑tools (Debian/Ubuntu)
sudo apt update
sudo apt install zram-tools
Отредактируйте /etc/default/zramswap
(если файла нет, создайте):
ALGO=zstd
PERCENT=50
PRIORITY=100
Примените:
sudo systemctl enable zramswap --now
sudo zramctl
sudo swapon --show
PERCENT=50
означает «создать zram размером 50% от RAM». Для 2 ГБ RAM это ~1 ГБ сжатого swap, который фактически влезет в меньший объём за счёт компрессии.
Вариант 2: zram‑generator (RHEL/Fedora/новые дистрибутивы)
sudo dnf install zram-generator
Создайте /etc/systemd/zram-generator.conf
:
[zram0]
zram-size = ram / 2
compression-algorithm = zstd
swap-priority = 100
Активируйте:
sudo systemctl daemon-reload
sudo systemctl restart systemd-zram-setup@zram0.service
sudo zramctl
sudo swapon --show
Одновременный zram и дисковый swap: приоритеты
Убедитесь, что у zram приоритет выше (например, 100), а у дискового swap ниже (например, 10). Тогда ядро сперва использует быстрый компрессированный swap и только затем — медленный диск.
Sysctl‑параметры: пресеты без фанатизма
Создайте файл /etc/sysctl.d/99-memory.conf
и задайте базовые значения. Два проверенных профиля:
Профиль A: универсальный малый VDS (веб‑приложение, очереди, небольшая БД)
vm.swappiness = 80
vm.vfs_cache_pressure = 100
vm.overcommit_memory = 2
vm.overcommit_ratio = 120
vm.min_free_kbytes = 65536
vm.page-cluster = 0
Пояснения:
vm.swappiness=80
— позволяет активнее выносить «холодные» страницы в zram, снижая вероятность резкого OOM.vm.overcommit_memory=2
иvm.overcommit_ratio=120
— строгий контроль overcommit: ядро не обещает программам больше памяти, чем доступно по формуле (RAM + swap × ratio). Это уменьшает риск внезапного OOM.vm.page-cluster=0
— уменьшает «чтение пачками» при подкачке, что полезно для интерактивности на медленном диске.
Профиль B: latency‑чувствительные сервисы
vm.swappiness = 20
vm.vfs_cache_pressure = 200
vm.overcommit_memory = 2
vm.overcommit_ratio = 100
vm.min_free_kbytes = 131072
vm.page-cluster = 1
Идея: меньше полагаться на swap, агрессивнее чистить кеши, держать чуть больший «воздушный зазор» свободной памяти. Применение настроек:
sudo sysctl --system

vm.overcommit_memory без страха
vm.overcommit_memory
имеет три режима:
- 0 — эвристика ядра (может быть непредсказуемой на малых VDS).
- 1 — разрешить любой overcommit (максимальный риск OOM).
- 2 — ограничивать выделение в пределах расчётного лимита (
vm.overcommit_ratio
).
На малом VDS безопаснее режим 2. Он откажет в выделении памяти раньше (например, malloc()
вернёт ошибку), чем сервер уйдёт в своп‑шторм и OOM. Это легче отлавливать в приложении и логах.
OOM‑killer: понять и приручить
Когда памяти не хватает, OOM‑killer выбирает жертву по баллам (oom_score
). На результат можно влиять через oom_score_adj
(от −1000 до 1000). Чем меньше, тем «ценнее» процесс для системы.
Защитим SSH и критичные демоны
Сделайте systemd‑override для SSH:
sudo systemctl edit sshd
В открывшемся редакторе добавьте:
[Service]
OOMScoreAdjust=-900
Перезапустите:
sudo systemctl daemon-reload
sudo systemctl restart sshd
Проверьте:
cat /proc/$(pidof sshd)/oom_score_adj
Аналогично можно защитить прокси, watchdog или легкий админский агент. Не злоупотребляйте: если «неубиваемых» процессов много, OOM‑killer выберет что‑то другое, возможно важное.
Ограничения по памяти на уровень сервиса
systemd позволяет задавать cgroup‑лимиты и реакцию на OOM:
[Service]
MemoryMax=512M
MemoryHigh=384M
OOMPolicy=restart
MemoryHigh
сигнализирует ядру дросселировать процесс при приближении к лимиту, MemoryMax
— жесткий предел. OOMPolicy
задает поведение systemd при OOM внутри cgroup (например, перезапустить сервис).
PHP‑FPM, воркеры и «тихие пожиратели RAM»
Частая причина OOM — слишком много процессов. Для PHP‑FPM, Node.js/PM2, Python‑воркеров и Java‑сервисов пересчитайте пулы и ограничьте рост:
- PHP‑FPM: подберите
pm
,pm.max_children
и лимиты памяти расширений. - Node.js: учтите дефолтные лимиты V8 и используйте
--max-old-space-size
где нужно. - Python/uwsgi/gunicorn: контролируйте число воркеров и используйте перезапуски по памяти.
Лучший способ — задать разумный предел на уровне systemd через MemoryMax
и наблюдать фактическое потребление.
Мониторинг и диагностика memory pressure
Минимальный набор команд для наблюдения:
free -h
vmstat 1
Топ прожорливых процессов и их OOM‑метрики:
ps -eo pid,cmd,pmem,rss,oom_score,oom_score_adj --sort=-rss | head -n 20
Pressure Stall Information (PSI) показывает «время под давлением»:
cat /proc/pressure/memory
Строки some
и full
растут — значит, задачи ждут память, а система «давится». Ищите всплески перед инцидентами.
Логи OOM‑killer в dmesg/journal:
dmesg -T | grep -i oom
journalctl -k -g OOM -n 100
Тест под нагрузкой: лучше сломать на стенде
Инструменты для репродукции проблем памяти:
sudo apt install stress-ng
stress-ng --vm 1 --vm-bytes 80% --timeout 60s
Или проверка на ошибки RAM:
sudo apt install memtester
sudo memtester 256M 1
Параллельно смотрите PSI, swap‑активность и отклики сервисов. Если под нагрузкой система резко уходит в swap на диск — уменьшите swappiness
или увеличьте долю zram. Если ловите OOM — проверьте vm.overcommit*
, лимиты cgroup и размер swap. Быстрый стенд для таких экспериментов удобнее поднять на отдельном VDS.
Практический пресет для малого VDS: пошагово
- Включите zram (50% RAM, приоритет 100).
- Добавьте небольшой дисковый swap‑файл (0.5–1 ГБ, приоритет 10).
- Примените профиль sysctl:
vm.overcommit_memory=2
,vm.overcommit_ratio=120
,swappiness=80
,page-cluster=0
. - Задайте
OOMScoreAdjust=-900
для SSH и одного‑двух критичных сервисов. - Ограничьте прожорливые службы через
MemoryHigh
/MemoryMax
. - Протестируйте
stress-ng
, наблюдайте PSI и логи OOM. - Зафиксируйте изменения в конфигурациях, перезагрузите и убедитесь, что всё поднимается автоматически.
Тонкости и подводные камни
- Дисковый swap на медленном SSD/HDD может вызывать задержки. Делайте ставку на zram, а диск оставляйте как «вторую линию».
- Слишком высокий
swappiness
без zram приведет к «липкому» дисковому swap и лагам. - Жесткий overcommit (
vm.overcommit_memory=2
) может ломать запуск редких приложений, ожидающих «много памяти на старте». Решение — временно ослабить лимит или поднятьvm.overcommit_ratio
. - Не защищайте от OOM всё подряд. Смысл в том, чтобы ядро могло безопасно выгрузить наименее важное.
- Следите за
journalctl
: если видите постоянные предупреждения о throttling поMemoryHigh
, значит, лимит слишком tight.
Планируете переезд и подбор панели управления? Смотрите сравнение актуальных панелей для VDS: что выбрать для администрирования, и пошаговую инструкцию по миграции с шареда: как переехать на VDS без простоев.
Итог
На малом VDS стабильность достигается комбинацией мер: быстрый компрессированный swap через zram, аккуратный дисковый swap, строгий vm.overcommit_memory=2
с разумным vm.overcommit_ratio
, корректный swappiness
и явные границы для прожорливых сервисов через cgroup. Добавьте защиту SSH от OOM, наблюдайте PSI и тестируйте под нагрузкой — и «внезапные Kill» уйдут в прошлое.
Правильная настройка памяти — это не разовый твик, а цикл: замер, изменение, проверка, откат при необходимости. Документируйте решения и держите план теста под рукой.