Сбой системы и падение виртуального выделенного сервера VDS

Почему падает VDS: 7 неочевидных причин сбоя

Вы переехали на VDS, настроили быструю связку Nginx + PHP-FPM и оптимизировали базу данных. Сайт работает со скоростью мысли, но внезапно в самый разгар рабочего дня сервер падает. Реальные пользователи бьются об ошибку 500 Internal Server Error, а хостинг-панель не подает признаков жизни. Вы перезагружаете сервер через биллинг, всё восстанавливается, но через пару дней история повторяется.

Когда падает обычный хостинг, проблему решает техподдержка. На VDS вы остаетесь один на один с сервером. Самое опасное — это скрытые, неочевидные проблемы, которые не видны при обычном осмотре. Давайте разберем 7 скрытых причин, почему ваш сервер может уйти в глухой нокаут, и конкретные решения для каждого сбоя.

1. Трагедия OOM Killer: почему Linux сам убивает вашу базу данных

Самая частая причина внезапного падения MySQL или MariaDB — это системный механизм защиты ядра Linux, который называется OOM Killer (Out of Memory Killer). Когда на сервере физически заканчивается свободная оперативная память (RAM), операционная система, чтобы не зависнуть намертво и защитить ядро от коллапса, включает аварийный протокол. Она сканирует все запущенные приложения, высчитывает по специальной формуле количество набранных штрафных очков (oom_score) и принудительно, без предупреждения убивает самый тяжелый процесс. Естественно, этим процессом почти всегда оказывается база данных вашего сайта.

Чаще всего это происходит из-за скрытой перегрузки пула процессов PHP-FPM. Если на сайт одновременно набегают агрессивные ИИ-боты или парсеры конкурентов, а лимит pm.max_children настроен некорректно или оставлен дефолтным, каждый новый визитер порождает отдельный поток PHP, который отъедает по 40–80 Мб RAM. Память улетает в ноль за секунды. В системном журнале /var/log/syslog или dmesg в этот момент появляется характерная запись: «Out of memory: Kill process (mysqld)».

Пошаговое решение

Зажмите лимиты PHP-FPM. Откройте конфигурационный файл вашего пула (например, /etc/php/8.3/fpm/pool.d/www.conf) и жестко пропишите лимит одновременных процессов. Для сервера с 4 Гб RAM значение pm.max_children = 30 или 40 — это потолок. PHP больше физически не сможет занять всю память.
Настройте oom_score_adj для MySQL. Вы можете прямо сказать ядру Linux: «Не трогай базу данных ни при каких обстоятельствах!». Для этого в системный юнит службы (через команду systemctl edit mysql) добавьте параметр OOMScoreAdjust=-1000. Теперь Linux скорее пристрелит зависшего бота, но сохранит базу данных живой.

2. Смерть при свободном месте: исчерпание лимита Inodes

Вы заходите на сервер через SSH-консоль, вводите классическую команду проверки диска df -h и видите прекрасную картину: на NVMe-накопителе свободно еще 30–40 гигабайт пространства. Но при этом CMS вашего сайта сыплет фатальными техническими ошибками, сессии пользователей не сохраняются, корзина товаров сбрасывается, а MySQL наотрез отказывается записывать новые заказы, выдавая лог «No space left on device».

Причина кроется в исчерпании лимита inodes (индексных дескрипторов). В файловых системах Linux под каждый отдельный файл, папку или даже символическую ссылку выделяется одна inode. Количество этих дескрипторов жестко фиксируется в момент форматирования диска провайдером. Если ваш интернет-магазин генерирует миллионы мелких картинок товаров, или на сайте криво настроен плагин кэширования, создающий под каждую страницу отдельный микро-файл HTML, лимит inodes закончится гораздо раньше физических гигабайт. Введите в консоли df -i: если в колонке использования красуется 100%, сервер заблокирован.

Пошаговое решение

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

find / -xdev -type d -exec sh -c 'echo "$(find "$1" -type f | wc -l) $1"' _ {} \; | sort -nr | head -n 10

Use code with caution.Очистите мусор. Чаще всего виновата папка с устаревшими сессиями PHP (/var/lib/php/sessions/) или папка кэша вашей CMS. Удалите старый кэш.Измените логику кэширования. Вместо сохранения миллионов мелких файлов на диск переведите кэш сайта в оперативную память — установите Redis или Memcached (как мы рекомендовали в статье про оптимизацию).

3. Отсутствие Swap-файла (Аварийная подушка безопасности)

Многие хостинг-провайдеры продают VDS с полностью отключенным файлом подкачки (Swap). Логика дата-центров понятна: они хотят сберечь ресурс своих дорогостоящих корпоративных NVMe-дисков от постоянного износа при перезаписи системного кэша. Однако для стабильности вашего коммерческого проекта отсутствие Swap-пространства — это бомба замедленного действия.

Swap выполняет роль буфера безопасности. Когда оперативная память сервера заполняется под завязку в моменты пикового трафика, Linux не включает OOM Killer сразу. Вместо этого ядро берет «спящие» процессы, которые в данный момент не выполняют активных вычислений (например, фоновые службы мониторинга или неактивные потоки панели управления), и временно сбрасывает их данные из RAM на жесткий диск. Если Swap-файла на VDS нет, то при любом краткосрочном скачке посещаемости сервер мгновенно словит ошибку критической нехватки RAM и уронит базу данных.

Пошаговое решение

Проверьте наличие Swap. Введите команду free -m. Если в строке Swap стоят нули, его нужно создать вручную.Создайте файл подкачки (например, на 2 Гб). Выполните в консоли поочередно:

fallocate -l 2G /swapfile
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile

Use code with caution.Зафиксируйте настройки. Чтобы Swap не исчез после перезагрузки сервера, добавьте строчку /swapfile none swap sw 0 0 в конец файла /etc/fstab. Теперь у вашего сервера есть надежный защитный буфер.

4. Атака «зомби»: зависшие и залипшие процессы PHP

Когда реальный пользователь закрывает вкладку вашего интернет-магазина, не дождавшись загрузки тяжелого отчета, или поисковый бот обрывает сетевое соединение посередине долгой операции, Nginx мгновенно прекращает трансляцию. Но запущенный на сервере PHP-скрипт об этом обрыве связи ничего не знает. Он продолжает методично выполнять тяжелые вычисления или делать запросы к внешним API.

Если в глобальных настройках php.ini не заданы жесткие таймауты выполнения скриптов, такой процесс превращается в «зомби». Он продолжает мертвым грузом занимать место в оперативной памяти сервера и грузить процессор бесконечными циклами. Ситуация усугубляется, если скрипт пытается достучаться до стороннего сервера (например, забрать остатки поставщика или курс валют), который завис. Когда за сутки таких залипших процессов накапливается несколько десятков, они полностью парализуют процессор (CPU улетает в перманентные 100%), и сайт уходит в офлайн.

Пошаговое решение

Настройте таймауты в php.ini. Ограничьте максимальное время жизни скрипта, прописав параметры: max_execution_time = 30 и max_input_time = 30. Если скрипт не отработал за 30 секунд, сервер убьет его автоматически.
Включите принудительное прерывание. В конфигурационном файле PHP-FPM (www.conf) активируйте директиву request_terminate_timeout = 30s. Это гарантирует, что «зомби»-процессы будут жестко ликвидироваться системой каждые полминуты, освобождая процессорное время.

5. Переполнение диска логами (Эффект лог-бомбы)

Журналы сервера (access.log и error.log), архитектуру которых мы детально препарировали в первой статье, жизненно необходимы для SEO-аналитики и аудита безопасности. Однако при сильной хакерской атаке, бесконтрольном парсинге или циклической ошибке в коде какого-нибудь плагина эти текстовые файлы превращаются в оружие массового поражения для вашей операционной системы.

Если ваш сайт подвергся жесткому брутфорсу (подбору паролей) со стороны сотен ботов, Nginx начинает записывать каждую попытку входа. Текстовый файл лога начинает раздуваться со скоростью геометрической професси, прибавляя по несколько гигабайт в час. Как только логи занимают все 100% доступного дискового пространства накопителя, операционная система блокирует работу СУБД, так как MySQL не может записать временные таблицы. Сайт моментально закрывается с критической ошибкой, а вы теряете возможность зайти даже в панель управления хостингом.

Пошаговое решение

Проверьте утилиту logrotate. Убедитесь, что на сервере активна автоматическая ротация логов (файл /etc/logrotate.d/nginx). Настройте её так, чтобы архивация происходила не раз в неделю, а каждый день (daily), а старые архивы удалялись через 7 дней (rotate 7).
Включите сжатие. Обязательно раскомментируйте параметр compress в настройках logrotate. Это позволит сжимать текстовые логи в компактные .gz архивы, уменьшая их вес на 90% и спасая диск от переполнения во время затяжных атак.

6. Лимиты открытых файлов: скрытый потолок операционной системы

В архитектуре Linux действует фундаментальное правило: абсолютно всё является файлом. Обычная картинка товара, PHP-скрипт, кэш-директория, база данных и даже каждое открытое сетевое TCP-соединение с браузером пользователя обрабатываются системой как открытый файл. В целях безопасности у каждого пользователя в системе (включая системную учетную запись www-data, под которой работает веб-сервер) есть жесткий внутренний лимит на количество одновременно открытых дескрипторов файлов, называемый nofile.

По умолчанию во многих популярных дистрибутивах этот лимит составляет всего 1024 единицы. Если на ваш сайт одновременно зашло 200 пользователей и пара поисковых краулеров, браузер каждого посетителя отправляет десятки запросов на скачивание контента. Веб-сервер Nginx мгновенно упирается в системный потолок Linux, в логе ошибок появляется страшная запись «Too many open files», сервер наотрез отказывается принимать новые подключения, а клиенты видят бесконечную, пустую загрузку вкладки.

Пошаговое решение

Увеличьте лимиты в операционной системе. Откройте файл /etc/security/limits.conf и добавьте в конец строки для веб-сервера:

www-data soft nofile 65535
www-data hard nofile 65535

Use code with caution.Пропишите лимиты в самом Nginx. В главном конфигурационном файле /etc/nginx/nginx.conf на первой строчке добавьте директиву: worker_rlimit_nofile 65535;. После перезапуска сервисов веб-сервер сможет легко переваривать любые пиковые наплывы пользователей и SEO-роботов.

7. Медленный DDoS уязвимостей: атака без мусорного трафика

Классический DDoS — это примитивная грубая сила, когда сетевой канал вашего сервера забивают гигабитами бессмысленного мусорного трафика. Такую атаку легко обнаружить по графикам сетевой активности хостинга и заблокировать на уровне Cloudflare. Однако современные злоумышленники действуют гораздо изощреннее, используя так называемый «медленный» или прикладной DDoS (Application Layer Attack), нацеленный на уязвимости в логике работы вашей CMS.

Автоматический бот предварительно сканирует сайт и находит самую ресурсоемкую, тяжелую страницу. Чаще всего это внутренний поиск по каталогу товаров с использованием сложных многоуровневых AJAX-фильтров, скрипт генерации больших PDF-отчетов или страница корзины. Вместо миллионов запросов хакер запускает интеллектуальный скрипт, который шлет всего 5–10 запросов в секунду, но бьет прицельно по этим тяжелым адресам. Внешне сетевой трафик выглядит абсолютно нормально. Однако процессор вашего VDS мгновенно улетает в 100% перегрузку, пытаясь обработать сложнейшие математические сортировки баз данных.

Пошаговое решение

Включите модуль ngx_http_limit_req_module в Nginx. Он позволяет жестко ограничить скорость обработки запросов для конкретных страниц. Пропишите в настройках виртуального хоста лимит для тяжелых страниц (например, для поиска):t

limit_req_zone $binary_remote_addr zone=search_limit:10m rate=1r/s;

Use code with caution.Это разрешит одному IP-адресу делать не более 1 запроса к поиску в секунду. Все лишние запросы от ботов Nginx мгновенно и безболезненно сбросит с кодом 503, полностью защитив процессор сервера от перегрузки.

Что делать, если Linux OOM Killer постоянно убивает базу данных MySQL?

Необходимо проверить использование оперативной памяти. Настройте жесткие ограничения на количество одновременных процессов в PHP-FPM (pm.max_children), уменьшите кэш базы данных или создайте файл подкачки (Swap).

Как очистить inodes на сервере, если свободное место на диске еще есть?

Для очистки inodes нужно найти и удалить директории с миллионами мелких файлов. Чаще всего это папки устаревшего кэша CMS, старые сессии пользователей (/var/lib/php/sessions) или неиспользуемые логи.

Как узнать, включен ли файл подкачки Swap на моем VDS сервере?

Введите в консоли Linux команду free -m или swapon --show. Если в строке Swap везде указаны нули, значит файл подкачки отключен, и его необходимо создать вручную через терминал.

Что означает ошибка «Too many open files» в логах веб-сервера Nginx?

Эта ошибка указывает на то, что Nginx исчерпал системный лимит Linux на количество одновременно открытых файлов и сетевых соединений. Для исправления нужно увеличить параметры worker_rlimit_nofile в Nginx и ulimit в системе.

Прокрутить вверх