SaaS におけるマルチテナント分離モデル

tty
Belong blog
Published in
13 min readOct 20, 2021

--

tty です。

SaaS を構築する場合に開発者が最も気にする点はテナントに関する実装ではないでしょうか?

個別のユーザー向けアプリケーションの場合はユーザー単位でのアクセススコープを考えますが、テナントモデルの場合、各ユーザー・同一テナント全員・テナント内の役割(管理者・一般ユーザー)など多くの切り口でのアクセススコープを気にする必要があります。
特にテナント間の分離は特に気をつける部分であり、テナントを超えたデータのアクセスは起こるべきではありません。

テナント分離についての整理を行った資料を社内で共有したので、Belong ではこういった議論が行われているということを知ってもらうため抜粋してこちらにも公開します。

TL;DR

  • SaaS のように 1 サービスで複数の組織を対応する場合にはマルチテナントを考慮する必要がある
  • マルチテナントにはデータのアクセススコープやうるさい隣人の課題がある
  • マルチテナントを実現するためには Silo モデルや Pool モデル、複合モデルなどが考えられ、選ぶべき方法は要求によって異なる

マルチテナント について

SaaS モデルのサービスで顧客はライセンスを購入して個別のソフトウェアを起動するような形ではなく、代わりにサービスのテナントとなる。つまりマルチテナント (複数の顧客(組織)が同居すること) が前提となる。
ユーザー視点では自身と自らが所属する組織のリソースのみに焦点が当たるが、サービスプロバイダーとしては複数の組織の複数のユーザーがサービス内に同居する状況で、適切な人が適切なリソースのみにアクセスするようコントロールする必要がある。

マルチテナントを行う場合に考慮するべき点

  • リソースのアクセススコープ
    ** テナントは自身のリソースのみ閲覧・変更が可能
    ** 他のテナントのデータは見えない
  • うるさい隣人 (Noisy Neighbor)
    ** 他のユーザーの挙動がサービス利用に影響する
    *** NW トラフィック
    *** DB に対する重たい処理
  • 拡張性
    ** テナント数
    ** テナントごとのストレージ量
    ** 全体でのストレージ量
  • 運用の複雑さ
    ** 管理・監視
    ** バージョン更新
  • カスタマイズ性

SaaS にとってテナント分離は最も重要な課題の一つである。テナントの分離方法によってサービスの運用コストや管理コスト、更にはテナント間を跨いだデータのアクセスが可能かどうかが決まる。

以下では考えられるテナント分離方式を挙げ、それぞれの特徴や利点・欠点に触れる。テナントの分離方法に正解はなく、サービスに対する要求や達成したいコンプライアンス要件、開発側のリソースを考慮した上でサービス毎に実現方法は異なる。

基本的な考え方

  • テナントの分離は「選択肢」ではなく SaaS には根本的に必要なもの
  • 「認証・認可は分離ではない」と AWS は定義している[1][[5]。認証・認可は分離の要素の1つであり、それだけで分離を実現はできない。
  • 分離はサービス(ソフトウェア)開発者のみの責任範囲にするべきではなく、インフラを含めたメカニズムで実現するべき

Silo モデル

Silo モデルはサービスのフルスタックをテナントごとに用意し、各テナントは独自のアプリケーション、ネットワーク、データストアを利用。

Silo モデルの Pros/Cons は以下の通り。

Pros

  • 複雑なコンプライアンスの要求にも個別に対応がしやすい
    ** テナントごとに環境が分離しているため個別設定がしやすい
  • うるさい隣人の懸念がない
    ** NW や ストレージを共有しないため影響がない
  • テナント毎のコストの追跡が容易
    ** テナントごとでまとめやすい
  • スコープの侵略リスクが低い
    ** 環境が別れているので、実装ミス等での不適切なデータなど、他テナントへのアクセスは起こりづらい

Cons

  • スケーリング
    ** テナントごとにアカウントやVPCなど環境分けると、管理が大変になり、切り口よっては最大数に限りが出てくる可能性がある
  • コストが高い
    ** 利用規模に関わらず個別の環境を用意すると一定のコストが必ずかかる
  • 機動性 (Agility) が低い
    ** ソフトウェアや設定の変更が必要な場合には個別の環境に適用する必要がある
  • 利用開始の自動化
    ** 利用開始ごとにアプリケーション・NW・DB・その他ストレージの新規デプロイが必要となり、依存が多いため自動化の工数が多い
  • 分散した管理と監視が必要
    ** 環境の分散に伴い管理や監視の粒度も細かくなり分散する
[5] より引用

Silo モデルの実現方法

プロジェクト・アカウントごと

テナントごとにプロジェクトやアカウントを分離する。GCP の場合はプロジェクトを分けると IAM レベルでアクセススコープを分離して同じ構成を再現可能。 AWS の場合は AWS Control Tower を用いてアカウントごとにクラウドのセットアップを分離可能。

VPC ごと

同一のアカウント・プロジェクト上で VPC (Virtual Private Cloud) をテナントごとに分離。VPC 内でアプリケーションやDBを立ち上げることが可能で、それぞれは分離されている。

サブネットごと

テナントごとに同一 VPC 内でサブネットを作成し、ネットワークのルーティングによりテナント毎の分離を行う。

この他にも Kubernetes を利用しているような場合には Tenant 毎に Namespace を作成し、それぞれにサービスのフルスタックをデプロイするようなモデルも考えられる

Pool モデル

Pool モデルはアプリケーションや DB のリソースを共有しながらテナントの分離を行う。コスト効率がよく機動性も高いため SaaS プロバイダにとっては魅力的なモデルだが、分離の実現はアプリケーションの実装に依存する部分が大きくなり、より複雑になる。

Pool モデルの Pros/Cons は以下の通り。

Pros

  • コスト効率が良い
    ** 利用量が少ないにも関わらずテナントごとにリソースを確保する必要がない
    ** DB などのリソースを共有するため実際の利用量や利用負荷に応じたスケーリングが行いやすい
  • 機動性がある
    ** 共有されているリソースの更新があった場合は更新すればサービス利用者全体にその変更が行き渡る
  • シンプルな管理と監視が可能
    ** 扱うリソースが集中するので管理や監視が行いやすい

Cons

  • 個別のコンプライアンスの要求への対応は難しい
    ** 複数のテナントが共存するため個別の対応は難しい
    ** ソフトウェアで解決できるものも在るが、物理的なデータストレージの分離等の対応は出来ない
  • うるさい隣人の懸念
    ** 特定のテナントが大きなデータを扱い NW の帯域を圧迫したり、重い処理を行い CPU/メモリの負荷を高めることで他のテナントのサービス利用に影響が出る可能性がある
  • テナント毎のコストの追跡が難しい
    ** リソース内に複数テナントが共存するためテナントごとのコストの計算は複雑になる
  • スコープの侵略リスクが実装依存
    ** 共有リソースにあるリソースを論理的に分離する形になるため設計・実装ミスでスコープの侵略は起こりうる
[5] より引用

Pool モデルの実現方法

Pool モデルでは基本的に分離ポリシーを共有することでテナントの分離を行う。

分離ポリシーはログインしたユーザーと紐付いたユーザープロファイルや、IAM を利用して分離方法を定める。

[5] より引用

Pool モデルにおけるストレージ分離戦略

データ分離は Pool モデルにおいて最も考慮するべきポイントである。

DB の分離戦略は以下のような例が考えられる

DB インスタンス分離

テナント毎に異なる DB インスタンスを用いることでデータの分離は実現できる。

この方法ではテナント毎に DB のアカウントが別れ、リクエスト毎にユーザープロファイルから DB アカウントを解決し利用する。

この方法はアプリケーション側は Pool モデルで機動性が高いが、DB は Silo モデルの側面が強く、スコープ侵略は起こりづらいが、新規アカウント毎に DB インスタンスの作成が求められ、テーブルカラムに変更があった場合には全 DB インスタンで適用が必要になる。

DB (Schema) の分離

テナント毎に同一の DB インスタンス内で別の DB (スキーマ)を用いる。

この方法では `SELECT * from {TENANT_ID} .user` のような形で、ユーザープロファイルから DB を解決し、SQL での利用が考えられる。

この場合、DB アカウントは共有可能(i.e. Grant により選択肢がある)かつ新規ユーザーごとに DB インスタンスを作る手間は無いため DB インスタンス分離モデルよりはメンテナンスコストは低いが、変更発生時には各 DB で同じ変更を適用する必要がある。
この方法は ORM によっては対応ができない可能性がある。

Table の分離

テナントごとに Table を作成することでデータの分離を行う。

この方法では SQL のクエリ先テーブルをユーザープロファイル毎に解決する。

この方法は ORM を用いると、テーブルごとに DAO 的なモデルが生成された場合に、ユーザー毎に利用するモデルを変更する実装が複雑になる可能性が高い。

Row Level Security による分離

RLS は DB 内のテーブルの行でテナントごとのデータの分離を行う。

RLS の場合は新規ユーザー作成時のコストは最も低く、新たな行を既存の DB のテーブルに差し込むだけで良い。

この方法の実現方法は複数あり例としては以下のものが挙げられる

  • SQL の WHERE 句に必ずテナント ID を含める
  • TenantID でパーティションを分ける
  • 利用している DB でサポートされている RLS の機能を使う

SQL の WHERE 句で制御する場合は実装依存になり、柔軟な対応はしやすいが、実装が煩雑になりやすくミスも起こりうる。パーティションを分ける場合も実装では WHERE 句のアプローチと近いが、クエリ速度は早くなることが期待される。

DB でサポートされている RLS を用いる場合、例えば PostgreSQL ではユーザーアカウン毎、若しくはコネクションのメタデータの設定で行レベルの閲覧権限が設定できる。設定は下記の形でテナントID を用いたポリシーをテーブルに適用する。

CREATE POLICY tenant_policy ON device USING (tenant_id = current_setting(‘app.tenant_id’));

クエリ時は下記 の形で、生成したコネクションにテナント ID のメタデータ を設定することで実現でき、(テナントIDの発行されていない INSERT 以外の) SQLはテナントを意識せずともスコープの侵略を防ぐ事ができる。

SELECT set_config(‘app.tenant_id’, :tenantId, false);

AWSの場合、 DynamoDB が RLS をサポートしている。MySQL はバージョン 8.0 の時点で RLS のサポートはない。

Bridge モデル

Bridge モデルは Silo モデルと Pool モデルを組み合わせてデータ分離を行うハイブリッドアプローチである。

例えば、テナントを利用プランごとで Personal/Team/Enterprise のような形で Tiering を行い、Personal/Team Tier は Pool モデルを用いてリソースの共有を行い、Enterprise Tier は Silo モデルでテナントごとに専用のリソースを用いるという形である。

Pros/Cons は適用するそれぞれのモデルと同じになる。

おわりに

開発者はどのような手段を選ぼうとも、テナントの分離は実現するべきであり妥協して良いポイントではない。本ドキュメントでは Silo モデル、 Pool モデル、Bridge モデルの紹介をしたが、サービスへの要求や、開発側の要望を考慮した上で、サービス毎に合うモデルを構築することが望ましい。

References

  1. SaaS Tenant Isolation Strategies
  2. SaaS Storage Strategies
  3. Modeling SaaS Tenant Profiles on AWS | AWS Partner Network (APN) Blog
  4. Understanding Multi-tenancy, the Keystone of SaaS — CloudGeometry
  5. AWS re:Invent 2019: SaaS tenant isolation patterns (ARC372-P)
  6. AWS re:Invent 2019: [REPEAT] Serverless SaaS deep dive: Building serverless SaaS on AWS (ARC410-R)
  7. AWS re:Invent 2019: SaaS migration: Real-world patterns and strategies (ARC371-P)
  8. AWS SaaS Factory プログラムのメリット
  9. PostgreSQL の行レベルのセキュリティを備えたマルチテナントデータの分離 | Amazon Web Services
  10. マルチテナント SaaS パターン — Azure SQL Database

--

--

tty
Belong blog

CTO at Belong Inc. Software engineer interested in server side apps and cloud architecture. (Twitter:ttyfky)