MAATRIX / Блог / Антипаттерн: один сервер под всё сразу

Антипаттерн: один сервер под всё сразу

MAATRIX

Знакомая картина: один VPS тянет продакшн-сайт, тестовую копию для экспериментов, почтовый сервер и ещё парочку личных проектов — «зачем платить за несколько серверов, если этот справляется». Справляется он ровно до того момента, пока тестовый прогон не положит продакшн, а дыра в забытом личном скрипте не откроет доступ ко всей машине. Разберём, что именно идёт не так и как разделить окружения так, чтобы это не било по бюджету.

Типичная картина: как это накапливается

Так обычно не планируют — это происходит постепенно. Сначала на сервере поднимают продакшн: сайт или API, база данных рядом на localhost, всё просто и логично. Потом нужно что-то потестировать перед выкладкой — копируют код в соседнюю папку, поднимают второй nginx-виртуалхост на другом порту, база для staging — либо отдельная схема в той же СУБД, либо вообще та же самая база «чтобы не мучиться с синхронизацией данных». Потом нужна рабочая почта для домена — ставят Postfix и Dovecot туда же, благо порты свободны. А через пару месяцев на этом же сервере оказывается личный блог владельца на WordPress, который никто не обновляет, потому что «он же не главный».

В итоге на одной машине уживаются:

  • продакшн-база данных с реальными клиентскими данными;
  • staging-версия сайта, куда заливают недоделанный код и гоняют нагрузочные тесты;
  • почтовый сервер с рабочей перепиской;
  • личный проект, который последний раз трогали полгода назад.

По отдельности каждый из этих сервисов не создаёт видимой проблемы. Вместе они делят один и тот же CPU, одну и ту же оперативную память, один и тот же диск и одну и ту же сетевую точку отказа — и именно это создаёт три конкретных риска, которые не видны, пока не сработают.

Проблема №1: конкуренция за ресурсы

Продакшн и всё остальное на сервере используют общий пул CPU, RAM, дискового I/O и полосы сети. Это значит, что нагрузка от логически никак не связанного с продакшном процесса напрямую роняет производительность боевого сервиса.

Типичный сценарий: разработчик запускает на staging нагрузочный тест перед релизом — условно ab -n 50000 -c 200 http://localhost:8080/, или прогоняет тяжёлую миграцию базы для проверки перед продакшн-деплоем. Тест съедает все свободные ядра CPU и упирается в диск. Продакшн-сайт, который крутится тут же, начинает отвечать с задержками, а под пиковой посещаемости — вовсе отваливаться по таймауту.

Ещё хуже, когда источник нагрузки не тестовый, а вредоносный: в заброшенном личном проекте (старый WordPress, забытый Node.js-скрипт) заводится майнер криптовалюты через уязвимую библиотеку или взломанный плагин. Майнер по определению старается выжать из CPU максимум — и продакшн начинает деградировать без видимой внешней причины. При этом диагностика превращается в квест: метрики показывают высокую нагрузку на CPU, но связать её с процессом, который физически и логически не имеет отношения к продакшн-приложению, с ходу не получается. Приходится вручную поднимать htop, сортировать по CPU, разбираться, что за процесс xmrig или kdevtmpfsi вообще делает на сервере — и это время, когда клиенты уже видят тормоза.

# первое, что стоит проверить при необъяснимой нагрузке
top -o %CPU
ps aux --sort=-%cpu | head -20
iostat -dx 2 5

Если бы личный проект и продакшн жили на разных серверах, майнер в лучшем случае замедлил бы личный блог — но никак не тронул бы платящих клиентов основного сервиса.

Частичный костыль — ограничить ресурсы через cgroups или Docker (--cpus=1.5 --memory=1g для контейнера с тестовым окружением), но это лечит симптом, а не причину: общий диск и общая сеть всё равно разделяются, и полной изоляции так не добиться.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Проблема №2: единая точка отказа для несвязанных сервисов

Второй риск — сервер как единая точка отказа. Причина падения может быть какой угодно: закончилось место на диске из-за разросшихся логов staging-окружения, обновление ядра потребовало перезагрузки, диск деградировал по SMART, провайдер провёл незапланированное обслуживание хост-ноды. Неважно, что именно случилось — важно, что падает всё сразу: и критичный продакшн, и совершенно некритичный тестовый стенд, который вообще не должен был участвовать в этом уравнении.

Показательный пример — переполнение диска. Staging часто настроен небрежно: логи не ротируются, тестовые бэкапы копятся в /var/backups, докер-образы старых версий никто не чистит. В какой-то момент df -h показывает 100% на корневом разделе — и тут ложится не только staging, а вся машина: СУБД не может писать WAL и падает, почтовый сервер не принимает письма, продакшн-сайт отдаёт 500-е.

# разросшиеся логи — частая причина 100% на диске
du -sh /var/log/* | sort -rh | head -10
docker system df
docker image prune -a --filter "until=720h"

Логика простая: у продакшна и у staging принципиально разные требования к доступности. Продакшн должен работать всегда, staging может лежать сутками — никто, кроме разработчика, это не заметит. Но пока они делят один сервер, их доступность физически склеена в одну величину: сервер либо жив целиком, либо мёртв целиком.

Проблема №3: слабое звено становится точкой входа

Третий риск — самый неочевидный и самый опасный: уязвимость в наименее защищённом сервисе на сервере открывает доступ ко всей машине, включая продакшн-данные, которые формально вообще не связаны с этим сервисом.

Личный блог на старом WordPress с непропатченным плагином, забытая панель управления с дефолтным паролем, тестовый Jenkins с открытым наружу портом «на время, потом закрою» — вот типичные точки входа. Заброшенные проекты обновляют реже всего именно потому, что они не критичны: если продакшн ломается, это сразу заметно и его чинят; если ломается забытый личный сайт — это может оставаться незамеченным месяцами.

Проблема в том, что после эксплуатации уязвимости атакующий оказывается не «внутри личного блога», а внутри операционной системы сервера. С этой точки у него есть доступ ко всем процессам, ко всем файлам, на которые хватает прав, к сетевым сокетам, включая локальные соединения к продакшн-базе данных. Если процессы работают от разных системных пользователей, а права на файлы выставлены строго — эскалация может застопориться. Но на практике сервер «под всё сразу» почти всегда настраивают по пути наименьшего сопротивления: один и тот же пользователь для всех сайтов, права 777 «чтобы не разбираться с правами», MySQL/PostgreSQL слушает на всех интерфейсах без ограничения по IP. В такой конфигурации взлом любого из сервисов — это компрометация всего сервера целиком.

Это прямое продолжение темы, которую мы разбирали в статье про антипаттерн работы под root — привычка не разделять права «для простоты» одинаково опасна что внутри одного сервиса, что между несколькими на одном сервере.

Методика разделения: с чего начать

Полностью изолировать вообще всё — не всегда реалистично по бюджету, но есть чёткий приоритет: в первую очередь отделяется то, что критично, от того, что нет. Практическая методика:

  1. Составьте список сервисов на сервере и оцените каждый по двум осям — критичность для бизнеса (приносит деньги / влияет на репутацию — да/нет) и надёжность кода (обновляется регулярно / заброшено — да/нет).
  2. Продакшн-сервисы, приносящие деньги, отделяются первыми — минимум на отдельный сервер или отдельный виртуальный инстанс, никаких компромиссов.
  3. Всё, что не обновляется годами, изолируется вторым приоритетом — не потому что оно ценно, а потому что оно опасно как потенциальная точка входа.
  4. Staging воспроизводит продакшн по конфигурации, но живёт отдельно — отдельная база (даже если это тот же движок СУБД на другом сервере), отдельные учётные данные, никакого прямого сетевого доступа к продакшн-базе.
  5. Почта разворачивается отдельно от веб-стека — либо на отдельном сервере, либо через внешний почтовый сервис. Почта требует своей репутации IP (SPF/DKIM/DMARC, чистый PTR), и падение веб-сервера не должно ронять доставку писем, и наоборот.

Минимальная безопасная конфигурация из практики — это уже два сервера: один под продакшн (сайт + прод-база), второй — под всё остальное (staging, личные проекты, тестовые эксперименты). Это не идеал, но это уже разрывает главную связку «тестовый скрипт валит платящих клиентов».

Если инфраструктура растёт, следующий шаг — разнести и внутри продакшн-сервера: например, база данных на отдельном сервере от веб-приложения, что заодно снимает конкуренцию за диск между СУБД и веб-сервером. Про это подробнее в материале про настройку staging-копии сайта — там разобрано, как воспроизвести продакшн-окружение так, чтобы staging не расходился с реальностью и при этом не трогал боевые данные.

Компромисс: сколько серверов реально нужно

Главный аргумент в пользу «всё на одном» — цена. Разберём его честно, на порядок величин (ориентир, у вас конкретные цифры будут отличаться в зависимости от тарифов и региона):

ВариантПримерная стоимость/месИзоляцияРиск при инциденте
Один мощный сервер под всё1 серверНулеваяПадает всё сразу
Прод отдельно + всё остальное на втором2 недорогих сервераБазоваяПрод не зависит от staging/личных проектов
Прод + staging + почта на трёх серверах3 сервераХорошаяКаждый сервис падает независимо
Полная изоляция каждого сервисаN серверовМаксимальнаяОправдано только при высокой нагрузке/критичности

Разница в деньгах между вариантом 1 и вариантом 2 обычно куда меньше, чем разница в стоимости часа простоя продакшна для бизнеса, у которого есть платящие клиенты. Если сайт приносит доход, экономия на втором недорогом сервере — это ложная экономия: один инцидент с падением по вине несвязанного тестового процесса легко обойдётся дороже, чем год аренды второго VPS.

Практический ориентир: если продакшн генерирует доход или на нём завязана репутация бизнеса, второй сервер под всё остальное окупается почти всегда, а не «в теории». Дальнейшее дробление (отдельно staging, отдельно почта, отдельно личные проекты) имеет смысл, когда нагрузка на каждый из этих сервисов действительно требует собственных ресурсов, а не просто «для красоты архитектуры».

Сравнение подходов к аренде инфраструктуры разобрано в статье VPS или выделенный сервер — что выбрать: для схемы «прод + второй сервер под остальное» чаще всего достаточно пары недорогих VPS, выделенный сервер имеет смысл, когда счёт идёт на десятки одновременных проектов.

Промежуточный вариант: контейнеры на одном физическом сервере

Если бюджет пока не позволяет второй сервер, есть промежуточное решение — разделение через контейнеры (Docker) или лёгкую виртуализацию (LXC) на одном физическом сервере. Это не замена разделению на разные машины, а способ снизить риски там, где полной изоляции пока нет.

Что это даёт:

  • Ограничение ресурсов на контейнерdocker run --cpus="1.5" --memory="2g" не даст одному контейнеру (например, staging) выжрать все ресурсы хоста и уронить соседний контейнер с продакшном.
  • Изоляция файловой системы — у каждого контейнера свой корень, взломанный staging-контейнер не имеет прямого доступа к файлам продакшн-контейнера.
  • Изоляция сети через отдельные Docker-сети — продакшн-контейнер и staging-контейнер можно посадить в разные docker network, чтобы между ними не было прямой сетевой связности без явного проброса портов.
# пример: жёсткое ограничение ресурсов для staging-контейнера
docker run -d \
  --name staging-app \
  --cpus="1.0" \
  --memory="1g" \
  --memory-swap="1g" \
  --network staging-net \
  myapp:staging

Но важно понимать честные границы этого подхода. Контейнеры на одном сервере — это изоляция процессов и файловой системы, а не изоляция ядра и физических ресурсов. Все контейнеры на хосте по-прежнему используют одно и то же ядро Linux, один и тот же диск, одну и ту же сетевую карту. Уязвимость побега из контейнера (container escape) — событие редкое, но не нулевое, и в случае эксплуатации даёт доступ ко всему хосту, включая соседние контейнеры. Диск, забитый логами одного контейнера, всё так же может положить хост целиком, если для контейнеров не настроены отдельные разделы или квоты.

Более подробно о том, где проходит эта граница, разобрано в статье изоляция сервисов через Docker для безопасности и в сравнении Docker или LXC — что выбрать для сервера. Практический вывод: контейнеры — это хороший первый шаг при ограниченном бюджете, но для по-настоящему критичного продакшна с реальными деньгами на кону физически отдельный сервер остаётся более надёжной границей, чем любая виртуализация на общем железе.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

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

Можно ли держать staging и продакшн на одном сервере, если использовать разные Docker-контейнеры?

Можно как временное решение при ограниченном бюджете, с жёсткими лимитами ресурсов на каждый контейнер и раздельными сетями. Но это снижает риск, а не убирает его: общий диск, общее ядро и общая сетевая карта остаются точками, где сбой одного окружения может задеть другое.

Как понять, что пора разносить сервисы по разным серверам?

Как только продакшн начал приносить деньги или на нём завязана репутация — это первый и самый весомый сигнал. Дополнительные сигналы: нагрузочные тесты на staging начали заметно влиять на отклик прод-сайта, или в логах находится процесс, который не должен был там оказаться.

Сколько стоит минимальное безопасное разделение?

Обычно это два недорогих VPS вместо одного — разница в цене небольшая по сравнению с одним сервером помощнее, но выигрыш в устойчивости кардинальный: инцидент на одном сервере не трогает второй.

Что делать с почтой — обязательно отдельный сервер?

Не обязательно отдельный сервер, но обязательно отдельная репутация IP: почта либо на отдельной машине, либо через специализированный почтовый сервис. Смешивать почту с веб-стеком на одном IP рискованно ещё и потому, что попадание IP в чёрные списки из-за проблем с вебом ударит по доставляемости писем, и наоборот.

А если я один разработчик и это просто личный проект без реальных денег?

Тогда риски ниже, и один сервер с аккуратными контейнерами — вполне рабочий компромисс. Но если на этом же сервере крутится хоть один сервис с реальными платящими пользователями или чужими персональными данными, правило «прод отдельно» уже актуально.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →