Знакомая картина для каждого, кто держит сайты или сервисы на недорогом VDS с 1–2 ГБ оперативной памяти: в 3 часа ночи запускается плановый бэкап или приходит внезапный наплыв поисковых краулеров, память забивается под 100%, и ядро Linux без предупреждения прибивает процесс базы данных mysqld или воркеры PHP/Node.js. В браузерах клиентов загорается ошибка 502 Bad Gateway или Error establishing a database connection, а консоль SSH перестает отзываться.
⚠️ Типичная ошибка администратора:
Первое, что делает большинство вебмастеров в такой ситуации — наспех создает классический файл подкачки /swapfile на 2–4 ГБ командой fallocate. Но при реальном скачке нагрузки диск захлебывается в операциях ввода-вывода (I/O wait подскакивает до 80–95%), процессор уходит в непрерывный троттлинг, и сервер зависает намертво на десятки минут вместо спасительного сброса нагрузки.
1. Анатомия сбоя: как Linux OOM Killer выбирает жертвой MySQL или Nginx
Когда в системе физически заканчивается свободная оперативная память и ядро больше не может выделить ни одной страницы под буферы приложений, срабатывает защитный механизм ядра — Out of Memory (OOM) Killer. Его единственная задача — предотвратить полный крах всей операционной системы ценой мгновенного уничтожения одного из работающих процессов.
Чтобы понять, кто именно стал жертвой OOM Killer в вашем случае, выполните в терминале диагностическую команду:
sudo dmesg -T | grep -E -i "oom|out of memory|killed process"
В логе ядра вы увидите красноречивые строки следующего вида:
[Fri Sep 4 03:14:22 2026] Out of memory: Killed process 14205 (mysqld) total-vm:1845220kB, anon-rss:921440kB, file-rss:0kB, shmem-rss:0kB, UID:112 pgtables:2104kB oom_score_adj:0
Как ядро выбирает «жертву»? Каждый процесс в Linux имеет специальный внутренний рейтинг — oom_score (число от 0 до 1000). Чем больше страниц оперативной памяти занимает процесс и чем меньше привилегий имеет его владелец, тем выше его балл. Именно поэтому MySQL / MariaDB, PostgreSQL, Java или PHP-FPM pool почти всегда оказываются на первой строчке расстрельного списка ядра — они держат в RAM кэши таблиц, пулы соединений и буферы сортировки.
2. Почему классический Swap на диске часто делает только хуже
Казалось бы, решение очевидно — включить подкачку на диск (Swap). Однако на серверах начального уровня (1–2 vCPU, 1–2 GB RAM) стандартный swapfile нередко превращается в мину замедленного действия:
- Колоссальная разница в скорости: Даже самый быстрый NVMe-накопитель корпоративного класса с задержкой 50–100 мкс уступает шине оперативной памяти DDR4/DDR5 (задержка 50–70 нс) более чем в 1000 раз.
- Катастрофический I/O Thrashing: Когда ядро пытается одновременно читать и писать сотни мегабайт сжатых страниц на диск, очередь ввода-вывода блокирует выполнение любых системных потоков. В этот момент vCPU занят не обработкой HTTP-запросов, а ожиданием ответа от дискового контроллера (параметр
%iowaitв утилитеtop). - Износ NVMe накопителя: Постоянные циклы записи и перезаписи страниц памяти в файл подкачки быстро вырабатывают ресурс TBW виртуального диска, из-за чего облачный провайдер может ограничить IOPS вашего тарифа.
3. Что такое zRAM: виртуальное сжатие памяти на лету без износа NVMe
zRAM — это встроенный модуль ядра Linux, который создает сжатое блочное устройство прямо в оперативной памяти сервера. Вместо того чтобы сбрасывать неактивные страницы RAM на медленный NVMe/SSD диск, ядро мгновенно сжимает их с помощью сверхбыстрых алгоритмов компрессии (ZSTD или LZ4) и сохраняет в специально выделенном сегменте той же самой оперативной памяти.
| Критерий | Классический Swap на диске | Сжатая память zRAM |
|---|---|---|
| Скорость доступа | 1–3 ГБ/с (NVMe) с высокой задержкой | 15–40 ГБ/с (широкая шина RAM) |
| Влияние на I/O wait | Вызывает скачок до 80–95% | Строго 0% (диск вообще не задействуется) |
| Коэффициент сжатия | 1:1 (страницы сохраняются как есть) | 2.2:1 – 3.0:1 (в зависимости от данных) |
| Нагрузка на vCPU | Минимальная (но CPU простаивает в I/O) | 1–3% vCPU при сжатии и распаковке |
| Поведение при пиках | Зависание сервера (Thrashing) | Плавное обслуживание запросов |
💡 Реальный эффект на VDS с 1 ГБ RAM:
При выделении 1 ГБ под устройство zRAM с алгоритмом ZSTD средний коэффициент сжатия текстовых структур баз данных и логов составляет около 2.5:1. Это означает, что в 400 МБ физической RAM вы можете уместить около 1 ГБ данных, высвободив ценную физическую память под активные буферы Nginx и MySQL без единого обращения к диску.
4. Пошаговая настройка zRAM на Ubuntu 24.04 и Debian 12
Для надежного управления устройствами zRAM в Debian-подобных дистрибутивах используется пакет zram-tools, который автоматически настраивает системный сервис под управлением systemd.
Шаг 4.1: Установка пакета
Обновите списки пакетов и установите утилиту:
sudo apt update && sudo apt install -y zram-tools
Шаг 4.2: Конфигурация параметров сжатия
Откройте файл конфигурации /etc/default/zramswap в вашем любимом редакторе:
sudo nano /etc/default/zramswap
Приведите конфигурационный файл к следующему выверенному виду:
# Включаем создание пула zRAM при загрузке
ALGO=zstd
# Процент от общего объема физической RAM, отдаваемый под пул сжатия.
# Для VDS 1–2 GB оптимально значение 75-100%
PERCENT=100
# Максимальный приоритет swap для zRAM (чтобы страницы шли сначала сюда, а не на диск)
PRIORITY=100
Пояснения по алгоритму:
ALGO=zstd— современный стандарт в ядрах Linux 6.x. Обеспечивает наивысший коэффициент сжатия при высокой скорости.ALGO=lz4— альтернатива для одноядерных VDS со слабым процессором (минимальная нагрузка на CPU, но чуть меньший процент сжатия).
Шаг 4.3: Перезапуск и проверка статуса
Перезапустите службу zramswap:
sudo systemctl restart zramswap
sudo systemctl enable zramswap
Проверьте активность сжатого устройства с помощью утилиты zramctl:
zramctl
Вывод должен выглядеть следующим образом:
NAME ALGORITHM DISKSIZE DATA COMPR TOTAL STREAMS MOUNTPOINT
/dev/zram0 zstd 1G 0B 0B 4K 1 [SWAP]
5. Создание аварийного Swapfile на NVMe со вторичным приоритетом
Почему одного zRAM может быть недостаточно? Если всплеск потребления памяти превысит объем zRAM, сервер снова окажется в ситуации OOM. Поэтому профессиональный подход заключается в двухуровневой архитектуре подкачки:
- Уровень 1 (Приоритет 100): Сжатый пул
/dev/zram0в памяти. Обслуживает 99% всех скачков. - Уровень 2 (Приоритет 10): Классический файл
/swapfileна NVMe-накопителе объемом 1–2 ГБ. Он выполняет роль «подушки безопасности» и используется ядром только тогда, когда zRAM заполнится полностью.
Создаем аварийный файл подкачки на 2 ГБ:
# Создаем файл заданного размера
sudo fallocate -l 2G /swapfile
# Выставляем строгие права безопасности (чтение только root)
sudo chmod 600 /swapfile
# Инициализируем пространство подкачки
sudo mkswap /swapfile
# Активируем swap с низким приоритетом (например, priority 10)
sudo swapon -p 10 /swapfile
Закрепляем аварийный swap в fstab:
Откройте /etc/fstab и добавьте строку с явным указанием приоритета pri=10:
echo "/swapfile none swap sw,pri=10 0 0" | sudo tee -a /etc/fstab
Теперь выполните команду swapon --show. Вы увидите идеальную многоуровневую структуру:
NAME TYPE SIZE USED PRIO
/dev/zram0 partition 1G 0B 100
/swapfile file 2G 0B 10
💡 Как работает эта связка:
Ядро Linux всегда отправляет вытесняемые страницы в swap-устройство с наивысшим приоритетом (PRIO=100). Вся нагрузка ложится на мгновенный zRAM в оперативной памяти. Если же произойдет аномальная перегрузка, ядро не вызовет OOM Killer, а плавно начнет сбрасывать излишки на медленный NVMe (PRIO=10), сохранив доступность SSH и процессы баз данных.
6. Тонкий тюнинг ядра в sysctl.conf: swappiness, vfs_cache_pressure и watermark
По умолчанию ядро Linux настроено консервативно: оно неохотно использует swap до последнего момента, сохраняя файловые дисковые кэши. При использовании zRAM стратегию ядра необходимо изменить: чем раньше страницы неактивных программ попадут в быстро сжимаемый zRAM, тем больше физической памяти освободится под рабочие соединения.
Создайте файл пользовательских настроек ядра /etc/sysctl.d/99-zram-tuning.conf:
sudo nano /etc/sysctl.d/99-zram-tuning.conf
Вставьте следующие параметры с комментариями инженеров:
# 1. Агрессивное использование swap (для zRAM это выгодно, страницы мгновенно жмутся в RAM)
vm.swappiness = 100
# 2. Баланс между кэшированием inode/dentry файловой системы и памятью процессов
vm.vfs_cache_pressure = 50
# 3. Предотвращение резких всплесков при нехватке памяти (упреждающее освобождение страниц)
vm.watermark_boost_factor = 0
vm.watermark_scale_factor = 125
# 4. Защита от избыточного выделения виртуальной памяти без подтверждения
vm.overcommit_memory = 0
Примените параметры на лету без перезагрузки сервера:
sudo sysctl --system
7. Защита критических служб от OOM Killer через oom_score_adj и systemd
Даже при наличии zRAM и swapfile полезно застраховать ключевые службы сервера (например, SSH-сервер и MySQL) от аварийного уничтожения при пиковом потреблении памяти вспомогательными скриптами.
Параметр oom_score_adj принимает значения от -1000 (полный запрет убийства процесса) до +1000 (уничтожить в первую очередь). Значение -100 или -200 надежно убережет сервис от случайной ликвидации.
Защита службы SSH (sshd):
Чтобы вы никогда не потеряли доступ к серверу по SSH в момент нехватки памяти, создайте drop-in оверлей для systemd:
sudo systemctl edit ssh.service
Добавьте строки:
[Service]
OOMScoreAdjust=-500
Защита базы данных MySQL / MariaDB:
Аналогично защищаем демон MySQL:
sudo systemctl edit mysql.service
[Service]
OOMScoreAdjust=-200
Примените изменения в systemd:
sudo systemctl daemon-reload
sudo systemctl restart ssh mysql
8. Стресс-тестирование связки и мониторинг памяти
Никогда не оставляйте сервер на продакшене без предварительной проверки настроек. Протестируем поведение подсистемы памяти утилитой stress-ng:
# Устанавливаем стресс-утилиту
sudo apt install -y stress-ng
# Запускаем выделение 1.5 ГБ памяти на 30 секунд в реальном времени
stress-ng --vm 1 --vm-bytes 1500M --timeout 30s --metrics-brief
В соседнем окне терминала запустите мониторинг zramctl и free -h. Вы наглядно увидите, как:
- Устройство
/dev/zram0плавно заполняется сжатыми данными. - Показатель
COMPRв разы меньше реального объема данныхDATA. - SSH-сессия остается абсолютно отзывчивой, а в логах
dmesgотсутствуют записи о вызове OOM Killer.
🎯 Готовая инфраструктура для стабильных проектов
Если проект вырос из базового тарифа с 1 ГБ RAM, а нагрузка базы данных продолжает расти, лучшим инженерным решением будет своевременный апгрейд на современный VDS с быстрыми ядрами AMD EPYC и NVMe-дисками корпоративного уровня.
Развернуть надежный VDS для продакшена →Рекомендуемые VDS-провайдеры
Отказоустойчивые сервера с быстрыми NVMe и каналом до 1 Гбит/с
Timeweb Cloud VDS
Сверхбыстрые NVMe диски до 3000 МБ/с, идеальны для запуска стеков с базами данных и zRAM. Почасовая оплата, мгновенные снапшоты и гибкое масштабирование RAM в 1 клик.
Selectel Cloud VPS
Выделенные KVM-ресурсы с гарантированной частотой процессоров. Чистая изоляция ядер и честные лимиты без оверселлинга для продуктивных нагрузок.
Beget VPS
Простое управление, изолированные ресурсы KVM, бесплатные ежедневные бэкапы всего сервера и отзывчивая техническая поддержка сисадминов.