Представим сообщение от клиента номер семь: «После вчерашней правки сломалась форма заявок. Верните, пожалуйста, как было, только у нас. Остальных не трогайте». Для менеджера это обычная просьба. Для инженера это экзамен на архитектуру: можно ли вернуть один проект на вчерашнее состояние так, чтобы девять других не заметили вообще ничего?
Ответ зависит от того, как устроен хостинг агентства. Вопрос «один VPS или десять» обычно сводят к арифметике: одна машина дешевле десяти. Но цена в счёте — только часть расходов. Остальное складывается из часов, которые уходят на обновления, расследования, переговоры о окнах работ и объяснения клиентам, почему их сайт лежал из-за чужого проекта. Ниже мы пройдём по этим расходам в том порядке, в котором они возникают, на условном примере агентства с десятью клиентами.
Один инцидент в двух схемах
Возьмём мысленный сценарий, не случай из практики. Клиент семь просит вернуть проект. Параллельно выясняется, что десять дней назад в его приложении обновили зависимость, а вместе с ней изменилась схема базы данных. Посмотрим, что происходит в двух схемах.
Общий VPS
На одной машине живут десять проектов: у кого-то контейнеры, у кого-то классическая связка веб-сервера и PHP, общая система управления базами данных. Откат проекта семь означает по сути три отдельные операции: вернуть код, вернуть данные его базы и не задеть всё остальное. Если проекты разложены по отдельным каталогам, отдельным базам и отдельным конфигурациям, это решаемо: берём копию именно этого каталога и именно этой базы. Но тут появляется условие, которое легко упустить: такая операция возможна только если копии делались на уровне проекта, а не только на уровне всей машины.
Снимок или откат целого сервера для этой задачи не подходит. Он вернёт к прошлому состоянию все десять проектов, включая заказы, которые клиенты с первого по шестой и с восьмого по десятый приняли за последние сутки. Поэтому «откатить всю машину, чтобы починить один проект» — не восстановление одного проекта, а потеря данных девяти остальных. Эту ловушку стоит держать в голове, выбирая схему резервирования: на общем сервере нужны копии с границей по проекту, и их восстановление нужно хотя бы раз проверить на тестовой копии.
Есть и вторая сторона. Если обновление затронуло общий компонент (версию PHP, системную библиотеку, СУБД), то проблема придёт ко всем одновременно. И наоборот: отложить обновление ради проекта семь тоже нельзя, пока он единственный на общей версии. Общий сервер заставляет синхронизировать темп всех десяти проектов.
Отдельные VPS
Если у клиента семь своя машина, ситуация проще концептуально: снимок или копия диска этой машины возвращает именно его проект, и никого больше. Версия системы, версия языка, расписание обновлений — всё своё. Можно обновить проект семь в удобное для клиента окно, а у проекта три оставить старую версию до конца сезонной кампании.
Цена этого — десять систем, которые нужно обновлять, мониторить и помнить. Безопасность ядра, доступы по SSH, сертификаты, журналы, резервные копии — всё умножается на десять. Если для этого нет автоматизации, вы получите десять слегка разных серверов, которые со временем расходятся в настройках. Тогда выигрыш в изоляции частично съест хаос в администрировании.
Итог первого шага простой: отдельная машина удобнее для точечного восстановления и независимого темпа обновлений, а общая — для единообразия. Но реальная граница проходит не только по машинам, и дальше нужно разобраться, где именно проект отделён от соседей.
Права системы и изоляция внутри приложения — не одно и то же
Когда на одном VPS живёт несколько клиентов, слово «изоляция» используют слишком широко. Его стоит разложить как минимум на два слоя.
Первый слой — системные права. Это пользователи операционной системы, права на каталоги, процессы и сеть. Если веб-приложения всех клиентов работают от одного пользователя, то уязвимость в плагине одного сайта даёт возможность читать файлы остальных: у них одни и те же права. Если у каждого проекта свой пользователь и закрытые каталоги, масштаб ущерба меньше.
Второй слой — изоляция внутри приложения и между приложениями: контейнеры, отдельные базы, отдельные секреты. Здесь популярен Docker. По документации, изоляция контейнеров опирается на namespaces и cgroups, то есть на механизмы ядра. Это важная ступень, но не стена между серверами: ядро остаётся общим. Там же подчёркнуто, что граница доверия проходит через сам Docker daemon, и право им управлять может позволить смонтировать файловую систему хоста. Для агентства это очень практичное следствие: если разработчику клиента или подрядчику выдан доступ к управлению Docker на общей машине, то фактически выдан доступ ко всему, что на ней лежит, включая проекты других клиентов.
Это стоит превратить в правило доступа. Подрядчик, которому нужно править проект семь, получает доступ к своему каталогу, своему пользователю и, при необходимости, к своим логам — но не членство в группе, управляющей daemon.
Для снижения последствий некоторых уязвимостей существует и rootless-режим, где daemon и контейнеры запускаются от непривилегированного пользователя. Он полезен как дополнительный слой, но не превращает контейнеры в отдельные виртуальные машины: система и ресурсы остаются общими. К тому же у него есть предпосылки и ограничения установки, поэтому решение о нём лучше принимать после проверки на тестовой машине, а не по принципу «включим, и станет безопасно».
Отдельно о том, что на практике ломается раньше всего. Часто изоляция нарушается не эксплойтами, а бытовыми вещами:
- общий файл с переменными окружения, где лежат пароли всех проектов;
- одна база данных с одним пользователем для всех приложений;
- общий сетевой мост, на котором контейнеры разных клиентов видят друг друга;
- ключи резервного копирования, у которых есть доступ ко всем проектам сразу;
- «временный» доступ подрядчика, который никто не отозвал.
Все пять пунктов исправимы на общем сервере, но требуют дисциплины. На отдельных машинах часть из них пропадает сама собой: соседей по сети и по файловой системе просто нет. Однако не надо думать, что отдельный VPS снимает вопрос секретов: ключ агентства, лежащий на десяти машинах, остаётся общей точкой компрометации.
Что означает слово «отдельный»
Здесь нужна оговорка, которая меняет ожидания. Десять отдельных VPS — это десять отдельных виртуальных машин с отдельными системами и ресурсами. Но из этого не следует, что они стоят на разном физическом оборудовании. Отдельность виртуальной машины и независимость физических областей отказа — разные свойства. В документации Amazon EC2 для этого есть специальные механизмы, например группы размещения: partition-группы разделяют экземпляры по непересекающемуся оборудованию, а spread размещает небольшую группу на разном оборудовании, чтобы снизить риск коррелированных отказов. Этот пример иллюстрирует только общий принцип; он ничего не говорит об устройстве и гарантиях MAATRIX. Поэтому, покупая десять VPS, не стоит обещать клиентам «ваш сайт не зависит от чужого железа», пока размещение не подтверждено провайдером письменно. Честная формулировка выглядит иначе: «ваш проект работает в отдельной системе, и вы можете обновлять и восстанавливать его независимо от других».
То же верно и в обратную сторону. Раздельные контейнеры на одном VPS не превращают его в независимые серверы с независимыми отказами: диск, ядро, сеть и виртуальная машина остаются общими. Но если требуется настоящая независимость от физических отказов, одной покупки нескольких VPS недостаточно, нужна ещё резервная площадка или отдельное подтверждение размещения.
Общий запас ресурсов и пики, которые не договариваются
Главный экономический аргумент в пользу общего сервера — усреднение. Десять проектов редко нагружены одновременно: у интернет-магазина пик вечером и в дни акций, у корпоративного сайта почти ничего, у сервиса отчётов тяжёлые задачи по ночам. Общая машина может быть меньше, чем сумма десяти маленьких, потому что запас используется совместно.
Этот аргумент верен ровно до тех пор, пока пики не совпадают. А они совпадают чаще, чем хочется: в Чёрную пятницу активны сразу несколько магазинов, а ночью у нескольких проектов запускаются резервные копии и обновления индексов. И здесь видна обратная сторона общего запаса: один проект может занять память или процессор так, что остальным не хватит.
В документации Docker про ограничение ресурсов описано важное для нас поведение: по умолчанию контейнеры не имеют заданных ограничений, а CPU и память можно ограничить явно. Там же говорится, что при нехватке памяти ядро способно завершать процессы, а swap работает медленнее оперативной памяти и не заменяет достаточный объём. Для агентства отсюда следуют три практических вывода.
- Без лимитов один «зависший» проект может утянуть за собой соседей. Проблема клиента три превращается в проблему клиентов с первого по десятый.
- С лимитами проблема локализуется, но не исчезает: проект, упёршийся в свой потолок, будет тормозить или перезапускаться, зато остальные проживут.
- Нехватка памяти ударяет не по тому, кто её съел, а по тому, кого выберет ядро. Это может оказаться совсем другой проект, и расследование займёт часы.
Поэтому разговоры о том, сколько проектов «поместится» на сервер, лишены смысла без замера. Число сайтов — плохая единица измерения: один каталог документации и один магазин с поиском и очередями — совсем разные нагрузки. Размер машины подтверждается нагрузочным тестом на реальных сценариях, а не списком клиентов.
Пример условного распределения
Возьмём условный пример для иллюстрации; цифры придуманы, это не результаты измерений. Допустим, у агентства десять проектов: шесть лёгких сайтов-визиток, два магазина средней нагрузки, один сервис с фоновой обработкой и один внутренний инструмент. Посмотрим, как ведут себя разные схемы.
| Схема | Что объединено | Что разделено | Где болит |
|---|---|---|---|
| Один общий VPS | Ядро, диск, память, процессор, расписание обновлений | Каталоги, пользователи, базы, лимиты контейнеров (если настроены) | Пики совпадают; откат машины затрагивает всех |
| Десять отдельных VPS | Ничего на уровне системы; общие только ваши процессы и ключи | Системы, диски, версии, окна обновлений | Десять систем для сопровождения; запас простаивает |
| Несколько групп | Проекты внутри группы | Группы между собой | Нужны правила распределения по группам |
В условной схеме с группами шесть визиток живут вместе на одной небольшой машине, два магазина получают по отдельной, сервис с фоновой обработкой тоже отдельную, а внутренний инструмент подселяется к визиткам. Из десяти проектов получается пять машин вместо одной или десяти. Здесь важно не число пять, а принцип разбиения: по характеру нагрузки и по цене инцидента.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации Россия, США, Франция и Великобритания. Оплата картой РФ и по СБП.
Платежи и часы сопровождения в одном расчёте
Теперь сведём деньги. Ниже условный расчёт для того же агентства; цены тарифов не указываем, чтобы не придумывать числа, поэтому считаем в условных единицах. Пусть общий сервер достаточного размера стоит 4 единицы в месяц, а небольшая отдельная машина под лёгкий проект стоит 1 единицу. Это допущение для демонстрации метода, а не прайс.
Платёж за серверы — только часть формулы. Вторая часть — время. Допустим, что рутинное сопровождение (обновления, проверка копий, мониторинг, ответы на вопросы) занимает на одну систему около двух часов в месяц, а на общий сервер, где живут все десять проектов, — около шести часов, потому что нужно учитывать взаимное влияние проектов и согласовывать окна работ. Час работы инженера примем равным 1 единице. Это тоже условные числа.
- Общий сервер: 4 единицы за аренду плюс 6 часов — всего около 10 единиц в месяц.
- Десять отдельных машин: 10 единиц аренды плюс 20 часов — около 30 единиц в месяц.
- Пять групп: 5 единиц аренды плюс около 10 часов — около 15 единиц в месяц.
Модель грубая, но она показывает главное: разница между схемами по большей части складывается из времени, а не из счёта провайдера. Если автоматизировать развёртывание, обновления и копии одним набором скриптов, то время на каждую дополнительную машину падает, и отдельные VPS подорожают заметно меньше. Если автоматизации нет, десять машин превращаются в десять ручных процедур.
Есть и скрытая статья расходов: инцидент. Допустим, на общем сервере проект три исчерпал память и сервер три раза за квартал останавливал соседей. Если каждый такой эпизод занимает полтора часа расследования и коммуникации с клиентами, а среди пострадавших — два магазина, то стоимость инцидента нужно считать не по времени простоя, а по обращениям, извинениям и доверию. Эти потери не лежат в счёте провайдера, но именно они обычно склоняют решение в пользу разделения самых чувствительных проектов.
В обратную сторону работает другой скрытый расход: простаивающий запас. Десять отдельных машин, подобранных «с запасом на всякий случай», в сумме содержат десять запасов. В большинстве проектов он не нужен месяцами. Если резервная мощность оплачивается постоянно, а пик случается раз в году, вопрос ставится так: что дешевле — держать запас круглый год или один раз в году временно увеличить ресурсы? Это зависит от того, как легко и быстро провайдер позволяет менять конфигурацию, и это нужно проверить до заказа, а не после.
Смешанная схема: кому что положено по требованиям
Практичный ответ для агентства с десятью клиентами редко бывает «всех в одну кучу» или «всех по одному». Чаще это разбиение по требованиям. Чтобы не делать его на глаз, можно задать каждому проекту несколько вопросов.
- Как дорого обходится его простой? Магазин в сезон — дорого, визитка — терпимо.
- Как часто он меняется? Проект с еженедельными релизами не должен зависеть от окна обновлений соседа.
- Какие у него данные? Персональные данные клиентов, платежи, внутренние документы — повод сильнее разделять доступы и копии.
- Кто имеет к нему доступ? Если у клиента своя команда разработчиков, лучше выдать ей отдельную машину, чем объяснять границы прав на общей.
- Какая у него нагрузка? Стабильная и предсказуемая подходит для совместного размещения, всплесковая и тяжёлая — нет.
- Что написано в договоре? Если клиенту обещан независимый сервер или отдельное окружение, этот пункт решает вопрос раньше всех остальных.
Теперь применим это к условному набору. Шесть визиток: простой дешёвый, нагрузка низкая, обновления редкие, данных мало — подходят для общей машины, где у каждого свой пользователь, свои каталоги и свои лимиты. Два магазина: простой дорог, нагрузка всплесковая, данные клиентов — каждому по отдельному VPS, и пусть их размер подбирается по тесту нагрузки, а не по размеру каталога. Сервис с фоновой обработкой: ему нужен собственный запас памяти и процессора, чтобы не вытеснять соседей, поэтому отдельная машина. Внутренний инструмент агентства: можно поселить вместе с визитками, но только если в нём нет секретов, дающих доступ к клиентским системам; иначе его тоже надо выделять.
Смешанная схема не отменяет дисциплины, она её перераспределяет. На общей машине с визитками проверяем лимиты и права по проектам. На отдельных машинах заводим единые шаблоны настроек, чтобы они не расходились. Ключи резервного копирования разделены: каждой группе свой, чтобы компрометация одного не открывала всё. Права подрядчиков выдаются на уровне проекта.
Если нужно увидеть, как это выглядит в ресурсах VPS, ориентиром могут служить линейки тарифов: у MAATRIX это конфигурации от Ba с 1 vCPU, 2 ГБ RAM и 40 ГБ NVMe до Djed с 16 vCPU, 32 ГБ и 320 ГБ (промежуточные — Uab, Heka, Maat). Эти параметры описывают конфигурацию, а не обещание вместимости: сколько проектов выдержит конкретная машина, показывает только замер на ваших приложениях. Для лёгкой группы визиток логично начинать с небольшой конфигурации и расти, для магазина — тестировать нагрузку на выбранном размере до запуска. Полезно, что доступ root позволяет самому настроить пользователей, лимиты и расписание копий, а локации (в публичном предложении названы UK, US, RU и FR) дают выбор площадки ближе к аудитории клиента. Доступность конкретных образов и операционных систем в каждой локации уточняется в форме заказа.
Автоматические резервные копии во всех тарифах при этом не следует принимать как данность: в публичном описании такой гарантии нет, поэтому схему копий проекта, включая проверку восстановления, агентство организует само и проверяет сама.
Разбор клиента номер семь
Вернёмся к исходной просьбе. Допустим, агентство выбрало смешанную схему, и клиент семь оказался магазином на отдельной машине. Тогда восстановление проходит в три действия: создать копию текущего состояния на случай, если откат окажется неудачным; вернуть код и данные проекта до момента перед обновлением; проверить форму заявок и то, что заказы, принятые после обновления, не потеряны. Последний пункт касается данных, а не кода: возвращая базу к вчерашнему состоянию, вы теряете сегодняшние заказы, и о них нужно договориться с клиентом заранее, а лучше предусмотреть выгрузку новых записей перед откатом.
Если же клиент семь живёт на общем сервере, действия те же, но только на уровне проекта: свой каталог, своя база, свой набор копий. Здесь нельзя использовать откат всей машины, потому что он затронет остальных девятерых. И именно поэтому до просьбы клиента должны существовать копии с границей по проекту и протестированная процедура восстановления одного проекта на тестовую копию. Если их нет, то честный ответ клиенту будет долгим, а восстановление — рискованным.
Заметьте, что в обоих случаях отдельная машина не делает восстановление волшебным. Она лишь убирает необходимость что-то выковыривать из общей среды. Всё остальное — копии, проверка, договорённости о данных — остаётся работой агентства.
Сколько стоит независимость одного клиента
Независимость — не абстрактное достоинство, а конкретный набор обязательств, которые агентство берёт на себя и которые кто-то оплачивает. Отдельная машина для клиента семь означает собственную систему, которую нужно обновлять, собственные копии, которые нужно проверять, собственный мониторинг и собственную строку в бюджете. Взамен клиент получает право на своё окно обновлений, на отсутствие чужих пиков в своей памяти и на восстановление, которое не требует согласования с девятью другими проектами.
Поэтому разумный вопрос агентству звучит не «насколько изолировать клиентов», а «за какую независимость готов платить этот конкретный клиент и что именно она ему даёт». Клиенту с визиткой, которая обновляется дважды в год, отдельная машина даст немного: он заплатит за покой, которого и так достаточно. Магазину, у которого простой в сезон стоит дороже годовой аренды, независимость окупается первым же предотвращённым инцидентом. А клиенту, которому в договоре обещана физическая независимость от других проектов, одной отдельной виртуальной машины недостаточно: это обещание нужно подтверждать размещением, а не количеством VPS в счёте.
Так что итог для десяти клиентов складывается не из лозунга, а из десяти небольших расчётов: что этот проект теряет при чужом сбое, сколько часов стоит его отдельное сопровождение и какую часть этой суммы клиент готов взять на себя. Там, где ответ ясен, проекту выдаётся своя машина. Там, где не ясен, он пока живёт в группе с ограничениями, а границу можно сдвинуть, когда цена независимости станет оправданной.