3.14 Мультиарендность и архитектура SaaS
Обзор и мотивация
Мультиарендность это практика запуска одного экземпляра вашей программы так, чтобы он обслуживал одновременно многих отдельных клиентов, логически разделяя данные и конфигурацию каждого, пока они делят один и тот же код и нередко одну и ту же инфраструктуру. Каждый клиент это арендатор (tenant). Эта единственная идея экономический двигатель программного обеспечения как услуги (SaaS), модели, в которой вы продаёте доступ к работающему приложению, а не копию для установки. Когда тысяча арендаторов делит одно развёртывание, вы патчите один раз, масштабируете одну систему, а предельная стоимость следующего клиента приближается к нулю. Поэтому хорошо построенный мультиарендный продукт может обслуживать стартап из двух человек и корпорацию на сто тысяч рабочих мест из одной кодовой базы, и поэтому выбранная вами модель аренды определяет ваши маржи, положение безопасности и эксплуатационную нагрузку на годы.
Для больших команд ставки глубже стоимости. Мультиарендность ставит жёсткое требование в центр вашей архитектуры: арендатор A никогда не должен видеть данные арендатора B, никогда, ни при какой ошибке, гонке или неверной настройке. Одна утечка между арендаторами может прикончить компанию. В то же время вся суть разделения в эффективности, поэтому каждое проектное решение лежит на спектре между сильной изоляцией (безопаснее, дороже) и плотным разделением (дешевле, рискованнее). Правильный выбор это разница между продуктом, изящно масштабирующимся, и тем, который либо разоряет вас на инфраструктуре, либо выводит в заголовки. Эта глава опирается на облачную архитектуру (глава 3.11), сильно полагается на архитектуру данных (глава 3.4) и облачную безопасность (глава 4.3) и связана с масштабируемостью и устойчивостью (глава 3.5) и отнесением затрат (глава 9.4).
Корпорации и государства поднимают планку ещё выше. Корпоративные покупатели согласовывают договорные гарантии данных, требуют выделенной изоляции для своего уровня и ожидают, что вы переносите их между средами без простоя. Государства добавляют законы о местонахождении данных, разделение по классификации и частое требование, чтобы каждое ведомство было отдельным арендатором со своей границей аудита. Решения об аренде здесь не детали реализации; это обязательства, которые вы берёте перед каждым клиентом, доверившим вам свои данные.
Ключевые принципы
- Изоляция это спектр, а не выключатель. Модели silo, pool и bridge меняют эффективность на разделение; выбирайте по уровню и по ресурсу, а не раз и навсегда для всего.
- Контекст арендатора священен. Каждый запрос, запрос к данным, строка журнала и фоновое задание должны нести идентификатор арендатора, а каждый доступ к данным должен им ограничиваться.
- Утечка между арендаторами это отказ, который важнее всего. Проектируйте так, чтобы один пропущенный фильтр не мог открыть данные другого арендатора; защита в глубину, а не одно условие WHERE.
- Шумные соседи это архитектурная проблема. Без квот и справедливости один тяжёлый арендатор ухудшает жизнь всем; планируйте это заранее.
- Конфигурация на арендатора масштабируется; код на арендатора нет. Гните продукт данными и флагами, а не форками.
- Жизненный цикл арендатора это функция продукта. Подключение, развёртывание, отключение и экспорт данных должны быть первоклассными, автоматизированными и проверяемыми.
- Нельзя управлять тем, что нельзя отнести. Наблюдаемость и стоимость должны разрезаться по арендаторам, иначе вы летите вслепую и по надёжности, и по марже.
Рекомендации
Выбирайте модель аренды по уровню вдоль спектра изоляции и эффективности
Три модели закрепляют спектр. В модели silo (выделенной) каждый арендатор получает свой изолированный стек: отдельные вычисления, отдельную базу данных, иногда отдельную учётную запись или сеть. Изоляция сильнейшая, а радиус поражения ошибки один арендатор, но вы платите за простаивающую мощность на каждого клиента и эксплуатируете много копий. В модели pool (общей) все арендаторы делят одни вычисления и одну базу данных, разделённые только логикой и идентификатором арендатора. Эффективность наивысшая, а предельная стоимость арендатора около нуля, но изоляция теперь целиком зависит от корректности вашего кода. Модель bridge (гибридная) смешивает обе: общие вычисления с базами данных на арендатора или общий пул для малых арендаторов и выделенные silo для крупных или регулируемых.
Не выбирайте одну модель на весь продукт. Правильный ответ обычно bridge, отображающийся на ваши ценовые уровни. Поместите длинный хвост малых арендаторов в эффективный общий пул, где их экономика работает. Предложите выделенное или одноарендное развёртывание как премиальный уровень для корпоративных клиентов, которые заплатят за изоляцию и договорные гарантии. Запишите это отображение как запись об архитектурном решении (глава 3.11), потому что «какие арендаторы что делят» это утверждение, от которого зависят ваши команды безопасности, продаж и финансов.
Разделяйте данные намеренно и делайте ограничение по арендатору невозможным для забывания
Данные это то, где мультиарендность живёт или умирает, поэтому воспринимайте выбор разделения как основное решение архитектуры данных (глава 3.4). Три стратегии параллельны моделям аренды. Отдельная база данных на арендатора даёт сильнейшую изоляцию, лёгкое резервное копирование и восстановление по арендатору и простой экспорт данных ценой многих баз данных для эксплуатации и миграций схем для рассылки. Отдельная схема на арендатора внутри общей базы данных это средний путь: один сервер, логическое разделение, всё ещё много объектов для миграции. Общие таблицы с ключом в столбце арендатора, где каждая строка несёт tenant_id, самое плотное и дешёвое, и самое опасное, потому что теперь один запрос без фильтра арендатора открывает данные между клиентами.
Если вы делите таблицы, не полагайтесь на то, что разработчики помнят фильтр. Принуждайте к ограничению по арендатору в слое, который нельзя обойти: безопасность на уровне строк базы данных, прикрепляющая обязательное условие к каждому запросу на основе арендатора сессии, слой ORM или доступа к данным, автоматически вставляющий условие арендатора, или оба. Ремень и подтяжки здесь правильны. По мере роста арендаторов естественным становится шардирование по арендатору: размещайте группы арендаторов на разных шардах базы данных, чтобы ни один экземпляр не держал всех, что также ограничивает радиус поражения отказа одного шарда и позволяет перенести крупного арендатора на собственный шард, не меняя модель.
Передавайте контекст арендатора повсюду и защищайтесь от утечек между арендаторами в глубину
Идентификатор арендатора должен ехать с каждой единицей работы. Установите его на границе, обычно из аутентифицированной сессии или поддомена, проверьте и пронесите через контекст запроса, каждый нижестоящий вызов сервиса, каждую сессию базы данных, каждое задание в очереди и каждую строку журнала и метрику. Опасные пробелы асинхронные: фоновый исполнитель, обрабатывающий задание без восстановления контекста арендатора, кэш с ключом без арендатора, обработчик веб-хука, доверяющий идентификатору арендатора от вызывающего. Каждое из этого путь к выдаче данных одного арендатора другому.
Воспринимайте изоляцию между арендаторами как свойство безопасности с защитой в глубину и передайте детали главе 4.3. Применяйте принцип наименьших привилегий, чтобы даже скомпрометированный компонент мог достичь только арендатора, от имени которого действует. Никогда не принимайте идентификатор арендатора из управляемого клиентом ввода для решений авторизации; выводите его из аутентифицированной идентичности. Выделяйте пространства имён кэшей, префиксов объектного хранилища и индексов поиска по арендатору, чтобы коллизия ключей не пересекала границу. Затем проверяйте границу намеренно: автоматические тесты, утверждающие, что учётные данные арендатора A не могут читать записи арендатора B, и периодические учения красной команды, пытающиеся вырваться из арендатора. Утечка, найденная вашим набором тестов, ошибка; утечка, найденная клиентом, кризис.
Сдерживайте шумных соседей квотами, ограничениями частоты и справедливостью
Когда арендаторы делят ресурсы, всплеск одного арендатора становится отказом для всех. Эта проблема шумного соседа не крайний случай; это поведение общего пула под нагрузкой по умолчанию. Проектируйте против неё с самого начала. Задавайте квоты на арендатора для важных ресурсов (запросы в секунду, одновременные задания, хранилище, стоимость запроса) и принуждайте к ним ограничением частоты на границе и на дорогих внутренних рубежах. Предпочитайте справедливое планирование, дающее каждому арендатору долю, очередям «первым пришёл, первым обслужен», позволяющим одному арендатору обездолить остальных.
Подбирайте принуждение к вашей модели аренды. В общем пуле квоты и справедливость основная защита, поэтому вкладывайтесь в них. Для арендатора, чья нагрузка действительно превышает то, что может поглотить справедливое разделение, ответ нередко в переводе его из пула в развёртывание bridge или silo, что функция, которую можно продать, а не отказ. Свяжите это с вашей работой по масштабируемости и устойчивости (глава 3.5): сброс нагрузки, предохранители и противодавление должны учитывать арендатора, чтобы сброс избыточной нагрузки одного арендатора защищал остальных, а не деградировал всю систему.
Настраивайте арендаторов данными, а не форками вашего кода
Каждый клиент захочет чего-то слегка иного: свой логотип, правила рабочего процесса, интеграции, поле, которого у вас нет. Масштабируемый способ сказать «да» это конфигурация на арендатора: флаги функций, настройки, права и точки расширения, являющиеся данными, вычисляемыми во время выполнения и общими для одной кодовой базы. Путь, разрушающий бизнес SaaS, это заказной код на арендатора: ветка, форк или особый случай в пути кода для крупного клиента. Десять таких, и у вас больше нет продукта, у вас десять продуктов в одном плаще, а каждое изменение надо тестировать десять раз.
Проведите твёрдую линию. Моделируйте оси вариации, которые вы готовы поддерживать, как первоклассную конфигурацию и воспринимайте запросы вне этих осей либо как дорожную карту продукта, либо как твёрдое «нет». Когда клиенту нужна настоящая настройка, дайте ему точки расширения (веб-хуки, API, плагины, пользовательские поля), запускающие его логику без ветвления вашей. Оставляйте действительно заказные развёртывания для одноарендного премиального уровня, где изоляция и есть суть, а более высокая цена покрывает эксплуатационные затраты.
Делайте жизненный цикл арендатора автоматизированным, наблюдаемым и с отнесением затрат
Подключение арендатора должно быть автоматизированным потоком самообслуживания: развернуть раздел данных арендатора, засеять значения по умолчанию, задать права и быть готовым за секунды, а не заявкой команде эксплуатации. Отключение важно не меньше и легче поддаётся пренебрежению. Когда арендатор уходит, вы должны уметь экспортировать его данные в пригодном формате, а затем доказуемо удалить их, потому что договоры и закон о приватности потребуют и то, и другое. Проектируйте экспорт и удаление данных с первого дня; дооснащение ими схемы с общими таблицами болезненно.
Инструментируйте всё по арендаторам. Помечайте журналы, трассировки и метрики идентификатором арендатора, чтобы ответить за секунды на «этот отказ у всех арендаторов или у одного?» и «какой арендатор вызывает эту стоимость?». Относите стоимость инфраструктуры на арендаторов, чтобы знать свою истинную маржу на клиента и замечать арендатора, чьё использование делает его убыточным при нынешней цене (глава 9.4). Наблюдаемость и отнесение затрат с учётом арендатора превращают мультиарендность из чёрного ящика в систему, которую можно реально эксплуатировать и оценивать.
Компромиссы: плюсы и минусы
| Модель аренды | Плюсы | Минусы |
|---|---|---|
| Silo (выделенный стек на арендатора) | Сильнейшая изоляция, наименьший радиус поражения, лёгкие соответствие и экспорт по арендатору, простая история шумного соседа | Наивысшая стоимость, простаивающая мощность на арендатора, много копий для эксплуатации и патчей |
| Pool (полностью общий) | Наименьшая предельная стоимость, самая плотная упаковка, одна система для масштабирования и обновления | Изоляция целиком зависит от корректности кода, худший риск шумного соседа, труднее всего экспорт и удаление по арендатору |
| Bridge (гибрид по уровням) | Эффективен для малых арендаторов, выделенная изоляция для крупных, отображается на цены | Больше моделей для построения и эксплуатации, путь перевода между уровнями для сопровождения |
| Общая БД, общая схема (столбец арендатора) | Дешевейшее хранилище, одна миграция, простейшая эксплуатация | Один пропущенный фильтр открывает данные; нужна безопасность на уровне строк как страховка |
| Общая БД, схема на арендатора | Логическая изоляция, один сервер, приемлемый экспорт | Много объектов схемы, миграции разворачиваются веером, пределы масштабирования на сервер |
| База данных на арендатора | Сильная изоляция данных, резервные копии и экспорт по арендатору | Много баз данных, веер миграций, более высокая стоимость |
Центральное напряжение между изоляцией и эффективностью, и оно проходит через каждую строку. Более плотное разделение умножает ваши маржи и умножает ваш риск одним движением; более сильная изоляция покупает безопасность и простоту по реальной цене на арендатора. Решение не в выборе одного полюса, а в намеренном размещении каждого арендатора вдоль спектра, обычно по уровню: упаковывайте малых арендаторов плотно там, где этого требует экономика и риск ограничен, изолируйте крупных и регулируемых там, где они заплатят за это и радиус поражения должен быть малым. Затем делайте плотный конец безопасным принудительным ограничением по арендатору, а изолированный дешёвым автоматизацией, чтобы ни один полюс не болел так сильно, как наивная версия.
Вопросы для обсуждения с командой
Если бы завтра пропал один фильтр ограничения по арендатору, увидел бы клиент данные другого клиента? Это вопрос, отделяющий защищаемый мультиарендный продукт от аварии, ждущей своего часа. Честная проверка проследить настоящий путь чтения и спросить, что обеспечивает границу арендатора: одно условие WHERE, написанное разработчиком, или есть страховка вроде безопасности на уровне строк базы данных или слоя доступа к данным, вставляющего ограничение независимо ни от чего? Принесите ваши настоящие пути запросов, фоновые задания и кэши, потому что утечка почти всегда прячется в асинхронном углу, который никто не ограничил. Принесите также результаты теста, намеренно использующего сессию арендатора A, чтобы запросить записи арендатора B, и утверждающего отказ. Если граница держится одной человеческой бдительностью, у вас скрытое нарушение, и исправление (защита в глубину) должно взлететь на верх бэклога.
Какую модель аренды и разделения данных на самом деле использует каждый уровень клиентов и соответствует ли она тому, что мы им продали? Многие команды по умолчанию дрейфуют к одной модели, а затем обнаруживают, что их цены и архитектура расходятся: корпоративным клиентам обещали изоляцию, которой общий пул не даёт, или малые клиенты сидят в дорогих выделенных стеках, разрушающих маржу. Отобразите каждый уровень на его реальную модель (silo, pool или bridge; база данных на арендатора, схема или общая таблица) и положите рядом с договорными гарантиями данных, которые даёт ваш отдел продаж. Где они расходятся, у вас либо риск соответствия, либо проблема стоимости, и то, и другое стоит вскрыть до того, как клиент или аудитор это найдут. Принесите отображение уровень-модель, стоимость на арендатора и фактические формулировки в ваших корпоративных договорах.
Когда нагрузка крупного арендатора всплескивает, кто ещё это чувствует и каков наш план? В общем пуле ответ нередко «все», и команды часто не знают этого, пока инцидент не сделает это очевидным. Пройдите по тому, что происходит, когда ваш крупнейший арендатор запускает массовый импорт или получает всплеск трафика: сдерживают ли это квоты и справедливое планирование на арендатора, защищает ли соседей сброс нагрузки или вся система деградирует вместе? Принесите данные о нагрузке и историю вашего последнего инцидента шумного соседа, потому что арендатора, который вам вредит, обычно можно назвать. Ответ должен определить и ваши вложения в ограничение частоты, и стратегию уровней, поскольку чистейшее исправление для арендатора, перерастающего справедливое разделение, перевести его в развёртывание bridge или выделенное, за которое можно взимать плату.
Если арендатор завтра уходит, можем ли мы вручить ему чистый экспорт и доказать, что удалили каждый след, или будем метаться? Отключение это часть жизненного цикла арендатора, которой команды пренебрегают, пока пункт о выходе из контракта или запрос по закону о приватности не вынудит, а к тому времени общая схема делает извлечение и удаление болезненными. Для большой команды риск растёт, потому что данные арендатора разбросаны по основной базе данных, кэшам, объектному хранилищу, индексам поиска, резервным копиям и аналитическим конвейерам, и каждое должно быть экспортировано в пригодном формате, а затем доказуемо очищено. Конкурирующие соображения реальны: плотные общие таблицы, дающие дешёвое хранилище, именно те, что делают извлечение и удаление по арендатору труднейшими, поэтому эффективность, купленную на слое хранения, вы можете вернуть на выходе. Принесите живой проход по отключению на настоящем арендаторе, список каждого хранилища, держащего данные арендатора, и свидетельства, которые вы показали бы, что удаление действительно произошло. Для корпоративных и государственных арендаторов экспорт должен быть заверенным, а удаление доказуемым, чтобы удовлетворить законы о государственных записях и приватности, поэтому воспринимайте отсутствие пути удаления как дефект соответствия, который нужно закрыть сейчас, а не функцию, добавляемую, когда клиент уходит.
Сколько разовых особых случаев для отдельных клиентов уже живёт в нашем пути кода и где линия, которую мы отказываемся пересекать? Форки кода на арендатора это тихий способ, которым бизнес SaaS перестаёт быть одним продуктом и становится многими продуктами под одним именем, где каждое изменение надо тестировать против каждого особого случая, а скорость затухает с добавлением клиентов. Напряжение в том, что крупному клиенту с реальной потребностью трудно отказать, а ветка в пути кода кажется быстрее построения поверхности конфигурации, поэтому особые случаи копятся по одному разумному исключению. Принесите честную опись: пройдите по кодовой базе поиском по именам клиентов и веткам для уровней, посчитайте их и оцените дополнительную стоимость тестирования и рецензирования, налагаемую каждым на несвязанное изменение. Обсуждение должно провести твёрдую линию между вариацией, которую вы моделируете как первоклассную конфигурацию (флаги, права, точки расширения), и настоящей заказной работой, которую вы оставляете для одноарендного премиального уровня, где более высокая цена покрывает эксплуатационные затраты. Для корпоративных покупателей, требующих глубокой настройки, долговечный ответ точки расширения, запускающие их логику без ветвления вашей, так что управление и аудит остаются обозримыми по всему парку.
Можем ли мы сказать по арендаторам и чего стоит инцидент и кому, и какие клиенты убыточны при нынешней цене? Мультиарендность превращается в чёрный ящик, как только ваши журналы, трассировки, метрики и стоимость инфраструктуры не несут измерения арендатора, потому что тогда вы не можете ответить, затрагивает ли отказ одного арендатора или весь парк, и не можете назвать арендатора, чьё использование делает его убытком по цене контракта. Для большой команды это отнесение отличает эксплуатацию платформы от гадания, и оно напрямую определяет и реакцию на надёжность, и цены. Соображения тянут против стоимости инструментирования и кардинальности: пометка всего по арендатору не бесплатна, а метрики высокой кардинальности нагружают ваш бюджет наблюдаемости, поэтому вы выбираете намеренно, что разрезать по арендатору, а что сэмплировать. Принесите текущее покрытие пометками арендаторов, настоящий запрос, относящий облачные расходы на одного арендатора, и таблицу маржи, позволяющую назвать вашего наименее прибыльного клиента. В корпоративной и государственной среде стоимость на арендатора и наблюдаемость в границах аудита также питают возмещение затрат, планирование мощности и границу аудита, на которую вправе рассчитывать каждое ведомство или бизнес-подразделение, поэтому измерение арендатора требование управления не меньше, чем эксплуатационное.
Взгляд по секторам
Стартап. С первого дня выпускайте единый общий пул и вкладывайте дефицитное инженерное внимание в то единственное, что нельзя дооснастить: принудительное ограничение по арендатору. Управляемый Postgres с безопасностью на уровне строк, tenant_id в каждой таблице и контекст арендатора, определяемый на границе, покупает безопасную плотность без эксплуатационной команды. Не стройте уровни silo или инфраструктуру на арендатора спекулятивно; добавляйте уровень bridge только когда платящий корпоративный потенциальный клиент делает изоляцию стоящей своей цены.
Малый бизнес. Без платформенного специалиста и при ограниченном бюджете опирайтесь на то, что ваше облако и фреймворк уже дают, а не стройте механизм изоляции сами. Управляемые базы данных с безопасностью на уровне строк, платформа как услуга, ограничивающая арендаторов за вас, и провайдер аутентификации, несущий идентичность арендатора, обычно дешевле и безопаснее самодельных эквивалентов. Воспринимайте мультиарендность как решение «купить или построить» на каждом слое и оставляйте заказную работу для тестов границы арендатора, которые можете написать только вы.
Крупная организация. Проблема в управлении портфелем по многим командам: многоуровневая архитектура bridge, запись об архитектурном решении, отображающая каждый уровень на его модель аренды и разделения данных, и отнесение стоимости на арендатора, чтобы финансы знали истинную маржу по каждому счёту. Стандартизируйте передачу контекста арендатора и страховку ограничения, чтобы ни одна команда не изобретала их заново, бюджетируйте автоматизацию изоляции и жизненного цикла явно и держите поддерживаемый оцененный путь переноса арендатора между уровнями без простоя по мере роста или смены потребностей соответствия.
Государственный сектор. Закупки, местонахождение данных и публичная подотчётность определяют модель. Привязывайте данные каждого ведомства к регионам внутри страны политикой-как-кодом, выделяйте чувствительные или высококлассифицированные нагрузки в отдельные учётные записи со своей границей аудита и давайте каждому ведомству собственную интеграцию идентичности, правила хранения и след аудита, чтобы аудиторы одного ведомства никогда не видели активность другого. Отключение должно давать заверенный экспорт и доказуемое удаление для удовлетворения законов о государственных записях и приватности, а подписываемые вами гарантии аренды должны быть теми, которые ваша архитектура способна сохранить.
Примеры
Стартап. Стартап из пятнадцати человек строит продукт как единый общий пул с первого дня и правильно делает. Все арендаторы делят одну управляемую базу данных Postgres с tenant_id в каждой таблице, безопасность на уровне строк принуждает к условию арендатора в базе данных, так что забытый фильтр не может вызвать утечку, а приложение определяет арендатора по поддомену на границе и проносит его через каждый запрос и фоновое задание. Подключение самообслуживаемое: новая регистрация разворачивает строку арендатора, засевает значения по умолчанию и оживает за секунды. Два инженера эксплуатируют всю платформу, потому что система одна. Когда их первый настоящий корпоративный потенциальный клиент требует выделенную базу данных и договорную гарантию изоляции, они добавляют уровень bridge: та же кодовая база, но этот арендатор получает собственную базу данных на собственном шарде, продаваемую по цене, покрывающей стоимость.
Крупная организация. Поставщик SaaS, обслуживающий крупные финансовые учреждения, ведёт многоуровневую архитектуру bridge. Тысячи малых и средних клиентов живут в региональных общих пулах, шардированных по арендатору, а квоты и справедливое планирование держат шумных соседей в узде. Клиенты банковского верхнего уровня получают одноарендные развёртывания в изолированных облачных учётных записях с выделенными базами данных, ключами шифрования на арендатора и договорными гарантиями местонахождения данных и изоляции, прописанными в рамочном соглашении. Платформенная возможность переносит арендатора между уровнями без простоя, когда он растёт или меняются его потребности соответствия. Стоимость каждого арендатора относится через пометки, так что финансы знают истинную маржу по каждому счёту, а наблюдаемость с пометками арендаторов позволяет дежурному инженеру за секунды сказать, касается ли оповещение одного арендатора или всего парка.
Государственный сектор. Национальный платформенный провайдер размещает многие государственные ведомства как отдельных арендаторов и воспринимает изоляцию как юридическое требование, а не предпочтение. Закон о местонахождении данных привязывает данные каждого ведомства к регионам внутри страны, принуждаемый политикой-как-кодом, блокирующей любой ресурс в запрещённом регионе (глава 3.11). Классификация определяет модель: ведомства, работающие с чувствительными материалами, получают полностью изолированные (silo) развёртывания в отдельных учётных записях со своей границей аудита, тогда как нагрузки низшей классификации делят управляемый пул. Каждое ведомство отдельный арендатор со своей интеграцией идентичности, своими правилами хранения и экспорта и следом аудита в рамках своей границы, так что аудиторы одного ведомства никогда не видят активность другого. Отключение даёт заверенный экспорт данных и доказуемое удаление, потому что записи подпадают под законы о государственных записях и приватности.
Бизнес-обоснование: мотивы, ROI и TCO
Главное бизнес-обоснование мультиарендности маржа. Одноарендная модель, где вы разворачиваете свежую копию на клиента, означает, что стоимость инфраструктуры и эксплуатации растёт примерно линейно с числом клиентов, а ваши инженеры проводят дни, патча много копий. Общая мультиарендная модель разрывает эту связь: вы патчите один раз, масштабируете одну систему и упаковываете клиентов достаточно плотно, чтобы предельная стоимость следующего арендатора приближалась к нулю. Это то, что позволяет бизнесу SaaS расти по выручке гораздо быстрее, чем по затратам, и поэтому инвесторы и советы директоров воспринимают чистую мультиарендную архитектуру как показатель масштабируемой компании.
Отдача проявляется в трёх местах: эксплуатационный рычаг (одна команда ведёт весь парк), более быстрая поставка (исправление выходит ко всем арендаторам сразу, так что скорость не затухает с добавлением клиентов) и вариативность цен (общий тариф для длинного хвоста и премиальный изолированный тариф для корпораций, оба из одной кодовой базы). Сопоставьте их с затратами, которые нужно финансировать честно: инженерия для построения принудительной изоляции арендаторов, квот, автоматизации жизненного цикла и наблюдаемости на арендатора плюс дисциплина удержания границы в целостности. Цена ошибки асимметрична и сурова, потому что одна утечка данных между арендаторами может вызвать регуляторные штрафы, массовый отток и репутационный ущерб, затмевающий инфраструктуру, которую вы сэкономили разделением. Формулируйте обоснование для руководства как маржу и масштабируемость в плюсе и экзистенциальный риск в минусе. Привязывайте соглашение об уровне обслуживания и договорные гарантии данных к модели аренды, которую вы действительно можете обеспечить, потому что обещание, которое ваша архитектура не может выполнить, это обязательство, а не продажа.
Антипаттерны и ловушки
- Ограничение по арендатору по соглашению. Надежда на то, что разработчики помнят фильтр арендатора в каждом запросе, без страховки на уровне базы данных или слоя доступа к данным; одно упущение это нарушение.
- Доверие идентификатору арендатора, пришедшему от клиента. Принятие арендатора из ввода запроса для авторизации вместо вывода его из аутентифицированной идентичности, что позволяет вызывающему попросить чужие данные.
- Неограниченная фоновая работа. Задания, кэши, веб-хуки и экспорты, теряющие контекст арендатора, потому что кто-то ограничил только синхронный путь запроса.
- Форки кода на арендатора. Особые случаи для крупного клиента в пути кода, пока вы не сопровождаете много расходящихся продуктов под одним именем, а каждое изменение стоит в десять раз больше.
- Нет защиты от шумного соседа. Работа общего пула без квот на арендатора или справедливости, так что первый всплеск арендатора роняет всех.
- Отключение как запоздалая мысль. Построение без экспорта данных и доказуемого удаления с последующим провалом пункта о выходе клиента или запроса по закону о приватности, потому что общая схема делает извлечение болезненным.
- Полёт вслепую по арендаторам. Журналы, метрики и стоимость без измерения арендатора, так что вы не можете сказать, чей это инцидент или какой арендатор убыточен.
Модель зрелости
- Уровень 1, Начальный: Мультиарендность импровизирована и реактивна. Разделение арендаторов держится на фильтрах, написанных вручную, без страховки, модель одна для всех, квот нет, подключение ручное, а журналы и стоимость не несут измерения арендатора. Команда узнаёт о шумном соседе и чуть не случившейся утечке из инцидентов.
- Уровень 2, Развитие: Появляются базовые практики, непоследовательные между командами. Модель аренды выбрана, а контекст арендатора передаётся по основному пути запроса, страховка на уровне базы данных или доступа к данным принуждает к ограничению на основных таблицах, существуют базовые квоты на арендатора. Подключение частично автоматизировано, а журналы несут идентификатор арендатора, но фоновые пути, экспорт и отнесение затрат различаются от сервиса к сервису и нигде не записаны.
- Уровень 3, Стандартизация: Подход к аренде документирован и соблюдается по организации. Многоуровневая аренда отображается на цены с общим пулом для малых арендаторов и изолированными развёртываниями для корпоративных и регулируемых, ограничение по арендатору принуждается в глубину и тестируется намеренно, квоты и справедливое планирование сдерживают шумных соседей, жизненный цикл арендатора, включая экспорт и доказуемое удаление, автоматизирован, а наблюдаемость и стоимость разрезаются по арендаторам. Каждая команда следует одному стандарту аренды, а не своему.
- Уровень 4, Управление: Хозяйство аренды измеряется и контролируется относительно базовых значений. Изоляция, справедливость, задержка и стоимость на арендатора отслеживаются как метрики с согласованными целями: покрытие тестами между арендаторами, доли нарушений квот и инцидентов шумного соседа, время подключения и отключения и маржа на арендатора сообщаются относительно базовых значений, а решения перевести арендатора между уровнями или переоценить убыточного принимаются на этих свидетельствах, а не по анекдоту. Соответствие местонахождению и классификации мониторится непрерывно, а дрейф от стандарта запускает документированную реакцию.
- Уровень 5, Оркестрация: Аренда непрерывно улучшается и интегрирована по организации. Границы между арендаторами упражняются регулярными учениями красной команды, арендаторы переходят между уровнями без простоя по мере роста или смены потребностей соответствия, маржа на арендатора питает ценообразование и планирование мощности, а правила местонахождения и классификации принуждаются политикой, а не рецензией. Модель адаптируется по мере сдвигов состава клиентов и регуляторной картины, а уроки питают продукт, безопасность и финансы как один контур.
Идеи для обсуждения
- Где на спектре изоляции и эффективности сегодня находится каждый из ваших уровней клиентов и не находится ли какой-то уровень в неверной модели для проданных гарантий или нужной вам маржи?
- Если бы вам нужно было доказать аудитору, что арендатор A не может получить доступ к данным арендатора B, какие свидетельства вы могли бы предъявить прямо сейчас и какая их доля автоматизирована, а какая лишь заявлена?
- Какие из ваших асинхронных путей (задания, кэши, веб-хуки, экспорты, индексы поиска) восстанавливают контекст арендатора, а какие лишь наследуют его или доверяют вызывающему?
- Когда арендатор перерастает справедливое разделение, есть ли у вас поддерживаемый оценённый путь перевода в развёртывание bridge или выделенное, или ответ по умолчанию инцидент?
- Можете ли вы относить стоимость инфраструктуры на отдельных арендаторов достаточно хорошо, чтобы назвать вашего наименее прибыльного клиента, и изменило бы это ваши цены?
- Можете ли вы для государственного или регулируемого арендатора принуждать политикой к местонахождению данных и изоляции по классификации и отключать с заверенным экспортом и доказуемым удалением?
Главные выводы
- Мультиарендность, один экземпляр, обслуживающий многих арендаторов, экономический двигатель SaaS: она определяет ваши маржи и ставит изоляцию между арендаторами в центр вашей архитектуры.
- Воспринимайте изоляцию против эффективности как спектр и делите по уровням: упаковывайте малых арендаторов в эффективный общий пул, изолируйте крупных и регулируемых в развёртываниях bridge или silo, за которые они заплатят.
- Никогда не опирайте ограничение по арендатору на фильтр, написанный вручную; принуждайте к нему в глубину безопасностью на уровне строк или слоем доступа к данным и тестируйте границу намеренно.
- Передавайте контекст арендатора через каждый запрос, задание, кэш и журнал и защищайте асинхронные пути, где прячутся утечки.
- Сдерживайте шумных соседей квотами на арендатора, ограничениями частоты и справедливым планированием и переводите арендаторов, перерастающих пул, а не позволяйте им его деградировать.
- Гните продукт конфигурацией на арендатора, а не кодом на арендатора, и делайте жизненный цикл арендатора, а также наблюдаемость и отнесение затрат на арендатора первоклассными.
Источники и дополнительное чтение
- Tom Kwok, Thao Nguyen, and Linh Lam, A Software as a Service with Multi-tenancy Support for an Electronic Contract Management Application (IEEE International Conference on Services Computing)
- Frederick Chong and Gianpaolo Carraro, Architecture Strategies for Catching the Long Tail (Microsoft)
- Amazon Web Services, SaaS Lens, AWS Well-Architected Framework and SaaS Tenant Isolation Strategies
- Microsoft, Multitenant SaaS architecture and patterns (Azure Architecture Centre)
- Google Cloud, Architecture for Multi-tenant SaaS Applications
- Cor-Paul Bezemer and Andy Zaidman, Multi-Tenant SaaS Applications: Maintenance Dream or Nightmare? (Proceedings of the Joint ERCIM Workshop on Software Evolution)
- The Open Web Application Security Project, OWASP Application Security Verification Standard (access-control and multi-tenancy requirements)
- Martin Kleppmann, Designing Data-Intensive Applications (partitioning, sharding, and data isolation)