Центр помощи

Пошаговые руководства по серверам, сетям и аккаунту.

Linux-сервер

Оптимизация Linux VPS с 512 МБ или 1 ГБ ОЗУ: zram, swap, лимиты journald и отключение лишних служб

Оптимизация Linux VPS с 512 МБ или 1 ГБ ОЗУ: zram, swap, лимиты journald и отключение лишних служб

Чтобы Linux VPS с 512 МБ или 1 ГБ ОЗУ работал без сбоев, сначала измерьте, что на самом деле занимает память, затем добавьте сжатый swap в ОЗУ (zram) поверх небольшого файла подкачки, ограничьте журнал systemd и отключите службы, которые серверу не нужны. В этой инструкции каждый шаг разобран для Debian 12/13 и Ubuntu 22.04/24.04 с пометками об отличиях Rocky Linux и AlmaLinux, а также показано, как читать сообщения OOM killer, если памяти всё же не хватило.

У облачного тарифа JUSTG mini 512 МБ ОЗУ и SSD на 10 ГБ, у тарифа 01 — 1 ГБ ОЗУ и SSD на 20 ГБ. На дисках такого размера swap и логи тоже должны быть скромными. Все команды выполняйте от root.

Шаг 1: Сначала измерьте, потом меняйте

Найдите реальных потребителей памяти, чтобы исправлять то, что действительно мешает.

free -h
ps -eo pid,user,rss,comm --sort=-rss | head -n 15   # RSS in KB, biggest first
systemd-cgtop -m -n 1                                # memory per service
cat /proc/pressure/memory                            # memory pressure (PSI)

ps показывает самые крупные процессы, а systemd-cgtop суммирует память по службам — это нагляднее, когда у службы много рабочих процессов. Если в /proc/pressure/memory значение avg60 держится выше ~10, задачи часто ждут память. (В Rocky/AlmaLinux PSI выключен, если ядро не загружено с параметром psi=1.)

RSS учитывает общие библиотеки целиком в каждом процессе, поэтому сумма выглядит больше реальной. smem показывает PSS, где общая память честно делится между процессами:

apt install smem            # Rocky / AlmaLinux: from EPEL
smem -tk -s pss -r | head -n 15

Шаг 2: Правильно читайте free -h: смотрите на available, а не на free

               total        used        free      shared  buff/cache   available
Mem:           961Mi       402Mi        74Mi       5.0Mi       484Mi       410Mi
Swap:          1.0Gi        12Mi       1.0Gi

Маленькое значение free — это нормально. Linux использует свободную ОЗУ как страничный кеш (buff/cache), чтобы держать файлы в памяти, и сразу отдает ее, когда она нужна программам. Важно значение available — оценка того, сколько памяти может получить новая нагрузка без использования swap. В примере выше «свободно» всего 74 МБ, но доступно 410 МБ, так что с сервером всё в порядке. Беспокоиться стоит, когда available постоянно ниже ~10% ОЗУ, а использование swap продолжает расти.

Шаг 3: Добавьте zram (сжатый swap в ОЗУ)

zram создает в ОЗУ устройство подкачки, где страницы хранятся в сжатом виде, часто в 2–3 раза компактнее. Подкачка в него гораздо быстрее, чем на диск, поэтому это очень действенный способ «растянуть» небольшой тариф. Цена — немного процессорного времени на сжатие.

Проверьте, есть ли zram в ядре

modprobe zram && echo "zram is available"
swapon --show

Если modprobe сообщает Module zram not found, ядро собрано без него (так бывает с некоторыми минимальными облачными ядрами). Переходите к шагу 4 и используйте только файл подкачки.

Вариант A: zram-tools (Debian, Ubuntu 22.04 и 24.04)

apt install zram-tools
cp /etc/default/zramswap /etc/default/zramswap.bak
cat > /etc/default/zramswap <<'EOF'
ALGO=zstd
PERCENT=50
PRIORITY=100
EOF
systemctl restart zramswap
zramctl
swapon --show

PERCENT=50 задает размер устройства zram в половину ОЗУ (несжатая емкость); реально занятая память равна сжатому объему. PRIORITY=100 заставляет ядро использовать zram раньше любого swap на диске.

Вариант B: systemd zram-generator (Debian 12/13, Ubuntu 24.04, Rocky/AlmaLinux 9)

apt install systemd-zram-generator      # Rocky / AlmaLinux 9: dnf install zram-generator
cat > /etc/systemd/zram-generator.conf <<'EOF'
[zram0]
zram-size = min(ram / 2, 2048)
compression-algorithm = zstd
swap-priority = 100
EOF
systemctl daemon-reload
systemctl start [email protected]
zramctl

Если в Rocky/AlmaLinux dnf не находит пакет, сначала подключите EPEL (dnf install epel-release).

Используйте только один из двух вариантов: zram-tools и zram-generator вместе создают конфликтующие устройства. Если zstd не принимается, выберите lz4 — он к тому же быстрее на загруженном тарифе с одним ядром.

Шаг 4: Оставьте небольшой файл подкачки как резерв и настройте swappiness

zram находится в ОЗУ, поэтому небольшой файл подкачки на диске всё равно полезен как последний резерв: на этих тарифах достаточно 512 МБ–1 ГБ. Создание файла, запись в fstab и изменение размера по шагам описаны в статье Как добавить swap на Linux VPS. По умолчанию у файла подкачки приоритет ниже, чем у zram, поэтому он используется, только когда zram заполнен.

С zram увеличьте vm.swappiness: выгрузить сжатые страницы в ОЗУ дешевле, чем сбросить файловый кеш и потом снова читать его с диска. vm.page-cluster = 0 запрещает ядру читать из swap сразу несколько страниц — это полезно только для дисков.

cat > /etc/sysctl.d/99-zram.conf <<'EOF'
vm.swappiness = 100
vm.page-cluster = 0
EOF
sysctl --system
sysctl vm.swappiness vm.vfs_cache_pressure

Файлы в /etc/sysctl.d/ читаются в алфавитном порядке, поэтому 99-zram.conf переопределяет vm.swappiness=10 из 99-swap.conf нашей статьи о swap. Без zram оставьте 10. Значение vm.vfs_cache_pressure=50 из той статьи подходит; никогда не ставьте 0 — тогда ядро вообще перестанет освобождать метаданные файловой системы.

Шаг 5: Ограничьте journald

Журнал systemd хранит логи на диске в /var/log/journal или в /run/log/journal, если журнал не постоянный. /run — это tmpfs, то есть эта копия находится в ОЗУ. Ограничьте оба:

journalctl --disk-usage
mkdir -p /etc/systemd/journald.conf.d
cat > /etc/systemd/journald.conf.d/size.conf <<'EOF'
[Journal]
SystemMaxUse=100M
RuntimeMaxUse=20M
MaxRetentionSec=1month
EOF
systemctl restart systemd-journald
journalctl --vacuum-size=100M
journalctl --disk-usage

SystemMaxUse ограничивает журнал на диске, RuntimeMaxUse — журнал в памяти, а MaxRetentionSec удаляет записи старше месяца. В Ubuntu rsyslog дополнительно пишет те же сообщения в /var/log/syslog; этот файл ротирует logrotate, так что обычно его можно оставить.

Шаг 6: Отключите службы, которые серверу не нужны

Прежде чем что-то останавливать, посмотрите, что запущено, и отключайте только то, что можете опознать:

systemctl list-units --type=service --state=running
systemctl status multipathd --no-pager                  # what is it and what started it?
systemctl list-dependencies --reverse multipathd.service  # does anything need it?
СлужбаГде встречаетсяМожно отключить, если
snapdUbuntusnap list не показывает нужных вам snap-пакетов (см. ниже)
multipathdUbuntu Servermultipath -ll ничего не выводит, что для VPS нормально
ModemManagerНекоторые образы UbuntuВсегда на VPS: модема там нет
tunedRocky / AlmaLinuxПо желанию; экономит немного ОЗУ. Если сомневаетесь, оставьте
# Ubuntu: multipath storage daemon (not needed without SAN/multipath disks)
multipath -ll                       # no output = not in use
systemctl disable --now multipathd.service multipathd.socket

# Modem manager - a VPS has no modem
systemctl disable --now ModemManager

# Undo at any time:
systemctl enable --now multipathd.service multipathd.socket

snapd занимает десятки мегабайт и монтирует loop-устройство для каждого snap-пакета. Его удаление стирает и все установленные snap-пакеты вместе с данными, поэтому сначала проверьте snap list. Если, например, certbot установлен как snap, перед удалением snapd поставьте его из apt. Файл с pin-приоритетом не даст apt снова установить snapd как зависимость.

snap list                           # what is installed as a snap?
apt purge snapd
cat > /etc/apt/preferences.d/no-snapd.pref <<'EOF'
Package: snapd
Pin: release a=*
Pin-Priority: -10
EOF
Не отключайте: ssh/sshd, собственные службы systemd (systemd-journald, systemd-logind, systemd-networkd, systemd-resolved), networking или NetworkManager, cron, синхронизацию времени (chrony или systemd-timesyncd) и файрвол (ufw, firewalld, nftables). Также оставьте qemu-guest-agent и cloud-init, если они установлены: платформа может на них опираться, а после загрузки сервера они почти не занимают память. Используйте disable, а не mask, чтобы службу было легко включить обратно.

Шаг 7: Перенесите автоматические обновления на тихое время

Не отключайте unattended-upgrades: обновления безопасности важнее нескольких мегабайт ОЗУ. Пик потребления памяти создает сам apt, поэтому просто запланируйте его на спокойное время. По умолчанию apt скачивает обновления в случайный момент в пределах 12-часового окна, а устанавливает примерно между 06:00 и 07:00; эти drop-in-файлы переносят загрузку на 04:00, а установку на 04:30 по времени сервера (проверьте его командой timedatectl):

mkdir -p /etc/systemd/system/apt-daily.timer.d /etc/systemd/system/apt-daily-upgrade.timer.d
cat > /etc/systemd/system/apt-daily.timer.d/override.conf <<'EOF'
[Timer]
OnCalendar=
OnCalendar=*-*-* 04:00
RandomizedDelaySec=15m
EOF
cat > /etc/systemd/system/apt-daily-upgrade.timer.d/override.conf <<'EOF'
[Timer]
OnCalendar=
OnCalendar=*-*-* 04:30
RandomizedDelaySec=15m
EOF
systemctl daemon-reload
systemctl list-timers 'apt-*'

В Rocky/AlmaLinux с dnf-automatic аналогично измените dnf-automatic.timer.

Шаг 8: Выбирайте более легкое ПО

  • Оставьте OpenSSH. В простое он занимает всего несколько мегабайт. Замены вроде Dropbear почти ничего не экономят, лишены части защитных функций и реже обновляются в дистрибутивах — риск того не стоит.
  • Предпочитайте nginx, а не Apache с mod_php. В модели prefork у Apache каждый дочерний процесс несет полный интерпретатор PHP. nginx с PHP-FPM или хотя бы Apache с mpm_event и PHP-FPM расходуют гораздо меньше памяти.
  • Запускайте PHP-FPM с pm = ondemand. Воркеры стартуют при поступлении запросов и завершаются после простоя, а не ждут в памяти.
  • Подгоните базу данных под тариф. Настройки MySQL и MariaDB по умолчанию рассчитаны на больший объем ОЗУ: уменьшите буферный пул и max_connections и выключите performance_schema.
; /etc/php/8.2/fpm/pool.d/www.conf  (Rocky / AlmaLinux: /etc/php-fpm.d/www.conf)
pm = ondemand
pm.max_children = 5
pm.process_idle_timeout = 10s
pm.max_requests = 500

Версия PHP в пути зависит от системы: 8.2 в Debian 12, 8.4 в Debian 13, 8.1 в Ubuntu 22.04 и 8.3 в Ubuntu 24.04. Задайте pm.max_children как объем памяти, который вы готовы отдать PHP, деленный на средний размер воркера, например 200 МБ / 40 МБ = 5. Измерьте размер, затем проверьте конфигурацию и перезагрузите службу:

# Average size of a PHP-FPM process
ps -eo rss,comm | awk '/php-fpm/ {s+=$1; n++} END {if (n) printf "%d processes, average %.0f MB\n", n, s/n/1024}'
php-fpm8.2 -t && systemctl reload php8.2-fpm    # Rocky / AlmaLinux: php-fpm -t && systemctl reload php-fpm

Шаг 9: Разберитесь с OOM killer и найдите события OOM

Когда заканчиваются и ОЗУ, и swap, OOM killer ядра завершает один процесс, чтобы спасти систему, — обычно с самым высоким oom_score, то есть, как правило, самый крупный. Служба, которая «сама по себе» перезапускается, или исчезнувшая база данных — часто результат OOM. Поищите в журнале ядра:

journalctl -k | grep -i -E 'out of memory|oom-kill|killed process'
dmesg -T | grep -i -E 'out of memory|killed process'
journalctl -k -b -1 | grep -i 'killed process'     # previous boot (persistent journal only)

Типичная строка выглядит так:

Out of memory: Killed process 812 (mariadbd) total-vm:1325400kB, anon-rss:301220kB, file-rss:0kB, shmem-rss:0kB, UID:106

В ней указан процесс и сколько памяти он занимал (anon-rss, в кБ). Если одну и ту же службу завершают снова и снова, уменьшите ее настройки, добавьте swap или zram либо ограничьте ее, как в шаге 10. В Ubuntu также проверьте systemctl status systemd-oomd: если эта служба активна, она может останавливать целые службы при нехватке памяти раньше ядра.

Шаг 10: Ограничьте прожорливую службу через systemd MemoryMax

Лимит памяти для одной службы защищает остальной сервер: если у PHP-FPM утечка памяти, ограничен будет только PHP-FPM, а SSH и база продолжат работать. MemoryHigh — мягкий лимит: выше него ядро замедляет службу и забирает у нее память; MemoryMax — жесткий лимит, при достижении которого OOM killer действует только внутри этой службы.

stat -fc %T /sys/fs/cgroup          # cgroup2fs = cgroup v2 (required)
mkdir -p /etc/systemd/system/php8.2-fpm.service.d
cat > /etc/systemd/system/php8.2-fpm.service.d/memory.conf <<'EOF'
[Service]
MemoryHigh=250M
MemoryMax=300M
# A killed worker is replaced by the master instead of stopping the service
OOMPolicy=continue
Restart=on-failure
EOF
systemctl daemon-reload
systemctl restart php8.2-fpm
systemctl show php8.2-fpm -p MemoryHigh -p MemoryMax -p MemoryCurrent

Debian 12/13, Ubuntu 22.04/24.04 и Rocky/AlmaLinux 9 по умолчанию используют cgroup v2. В старых системах с cgroup v1, например Rocky/AlmaLinux 8, используйте MemoryLimit=; MemoryHigh работает только с v2. Не ставьте жесткие лимиты на саму базу данных: внезапное завершение приводит к восстановлению после сбоя. Лучше подберите ее настройки.

Шаг 11: Поймите, когда пора переходить на тариф побольше

Настройка помогает, когда память заканчивается лишь время от времени. Если available постоянно мало, swap всё время занят, а vmstat 1 10 показывает непрерывную подкачку (si/so), нагрузке просто нужно больше ОЗУ. Облачные серверы JUSTG можно перевести на старший тариф со страницы услуги; см. Как увеличить RAM, SSD или добавить IP на VPS.

Частые вопросы

zram лучше файла подкачки?

По скорости — да: он работает со скоростью памяти и не нагружает диск. Но его объем ограничен ОЗУ, поэтому лучшая схема для небольших тарифов — оба сразу: zram с высоким приоритетом для повседневной работы и небольшой файл подкачки как последний резерв.

zram сильно нагружает процессор?

Сжатие требует немного CPU, обычно совсем немного. Если на тарифе с одним ядром сервер постоянно подкачивает в zram, переключитесь на lz4 и уменьшите нагрузку: постоянная подкачка означает, что памяти слишком мало.

Можно ли запустить Docker на тарифе mini с 512 МБ?

Один-два контейнера с небольшими приложениями заработают, но демон Docker и среда выполнения контейнеров сами занимают память. Задайте лимиты памяти для каждого контейнера, используйте zram и swap, а для нескольких контейнеров присмотритесь к тарифу от 1 ГБ.

Если службы продолжают завершаться и вы не можете найти причину, создайте тикет по адресу https://www.justg.com/submitticket.php и приложите IP сервера, вывод free -h и journalctl -k | grep -i oom. В JUSTG работает AI-поддержка 24/7 по тикетам, а вопросы, требующие участия человека, подхватывают инженеры.

Помог ли вам данный ответ?
Центр помощи
Linux-сервер Вход по SSH-ключу в Linux: настройка ключей ed25519 и отключение входа по паролю Любой сервер с публичным IPv4 через несколько минут после запуска начинают атаковать боты, перебирающие SSH-пароли. В этой инструкции… Linux-сервер Как безопасно сменить порт SSH и пароль root на Linux VPS Перенос SSH с порта 22 не остановит целенаправленную атаку, но уберёт из логов большую часть автоматического сканирования, а смена пароля… Linux-сервер Настройка файрвола в Linux: UFW и firewalld на VPS (IPv4 и IPv6) Только что установленный Linux-сервер отвечает на любом порту, который открыла какая-либо служба, поэтому файрвол — одна из первых вещей,… Linux-сервер Как добавить swap на Linux VPS (тарифы с 512 МБ и 1 ГБ ОЗУ) На облачном сервере с 512 МБ или 1 ГБ ОЗУ база данных, пул PHP-FPM и обновление пакетов легко исчерпывают память одновременно. Тогда OOM… Linux-сервер Диск заполнен в Linux: как найти и освободить место на VPS Ошибка «No space left on device» ломает на сервере почти всё: базы данных перестают писать, сайты отдают ошибки, обновления пакетов не…
AlipayUnionPayVISAMastercardPayPalUSDTstripe