マルチテナント構成の設計 — 顧客ごとの分離をどこまでやるか

マルチテナント設計の核心は「どこまで分離するか」という問い方ではなく、「何を混在させてよいか」という逆算の判断にある。顧客ごとにインフラを完全に分けることはセキュリティ上有利だが、テナント数が増えるほど運用コストが比例して膨らむ。行レベルの分離で済ませると構成はシンプルになる反面、実装ミスが情報漏洩に直結するリスクを抱える。本稿では、データ・ネットワーク・権限の三層でどこに境界を引くかという設計判断と、現場で起きやすい落とし穴を先に整理し、運用・コストとのトレードオフを論じる。

テナントを混ぜて載せて情報が漏れる構造

分離なき共有が引き起こすアンチパターン

マルチテナント設計で最初に行き詰まるのは、「DB接続を共有しつつ、アプリ層のフィルタだけでテナントを分ける」という構成だ。現場では、テナントID列をWHERE句に付け忘れた単一クエリで他社データが取得可能になるという事例をよく聞く。特にORMのグローバルスコープを各開発者任せにした場合、条件の付け忘れがコードレビューをすり抜けやすい。行レベルの分離を採用するなら、アプリ層の制御に頼るのではなく、データベース側でRow Level Security(RLS)を有効化することを前提に設計する必要がある。論理的な分離はコードの規律に依存するため、DBエンジンのメカニズムで強制することが設計の信頼性を担保する最低ラインになる。

セッションとキャッシュの境界崩壊

セッションストアやキャッシュ層(RedisやMemcachedなど)を全テナント共有で使う場合、キャッシュのキー設計にテナントIDが含まれていないと、別テナントのレスポンスが返るインシデントが発生しうる。CDNやリバースプロキシのキャッシュでは、URLが同一でもテナントが異なる場合に誤ったコンテンツが返ることがある。これを防ぐには、テナントを識別するHTTPヘッダー(X-Tenant-IDなど)をVaryに含めるか、テナントごとに異なるサブドメインを割り当ててCDNがドメイン単位でキャッシュを分けるよう設計する。後からキャッシュ設計を変えると既存テナントへの影響が広範囲に及ぶため、最初の設計時に決定しておくことが重要だ。

ログと監査証跡の混濁

全テナントのアクセスログが単一ストリームに流れ込む設計は、テナントごとの監査証跡を出力する際に後から集計フィルタをかけることになる。構成管理が甘い場合、ログの分離漏れで他テナントの操作履歴が混入しかねない。金融・医療など、テナントごとの監査が契約条件になっているケースでは、ログ収集の段階からテナントIDを必須フィールドとして埋め込む設計が求められる。後付けでログ構造を変更するとデプロイ全体に影響が及ぶため、初期設計時に確定させておくべき判断のひとつだ。ログ設計と分離モデルは連動しており、分離方針を決めた段階でログの粒度も同時に決めることが、実装後の混乱を防ぐ。

データ・ネットワーク・権限のどこで分離するかの判断

データ層の分離粒度

データ層の分離には大きく三段階ある。インスタンスを分ける「完全分離」、同一DBインスタンス内でスキーマを分ける「スキーマ分離」、同一スキーマ内でテナントID列で分ける「行レベル分離」だ。テナント数が5社以下かつ各社のデータ量・負荷が大きい場合は完全分離を選びやすい。一方、テナントが100社を超えると、インスタンス数の増加がそのまま運用工数に直結し、完全分離は非現実的になってくる。スキーマ分離はその中間に位置し、PostgreSQLのschema機能を活用することで、接続先の切り替えだけでテナント分離を実現できる。この選択は後から変更するコストが非常に高いため、将来のテナント上限を見据えた初期判断が不可欠だ。

ネットワーク層での隔離判断

ネットワーク層の分離は、VPC・サブネット・セキュリティグループの設計として現れる。テナントごとにVPCを立てる構成はセキュリティ上最も強固だが、VPCピアリングやTransit Gatewayを介した管理コンポーネントとの接続設計が複雑になる。多くの構成では単一VPC内でセキュリティグループとサブネットを使った分離を採用し、ネットワーク層よりも上位のアプリ・DB層での分離に重点を置く。判断の軸は「テナント間のネットワーク到達性をゼロにする必要があるか」で、コンプライアンス要件がそこまで問われない場合はセキュリティグループ制御で十分なケースが多い。ネットワーク分離のコストと管理複雑性は分離の強度と比例して増すため、要件に対して過剰な分離を避けることも設計判断に含まれる。

権限モデルとIAM設計の分岐

クラウドのIAMでテナントを分離する場合、テナントごとにAWSアカウントを分けるのか、単一アカウント内でIAMロールを使い分けるのかの判断が必要になる。AWSのOrganizationsを使ったマルチアカウント構成はSCP(Service Control Policy)によってアカウント横断の制御が可能だが、デプロイパイプラインとアカウントの対応付けが複雑になる。一方、単一アカウント内でのロール分離はシンプルだが、IAMポリシーの管理ミスが全テナントに影響する。重要なのは、権限の分離設計をアプリの分離モデルと一致させることで、DBが完全分離なのにIAMが共有という構成上の矛盾は、後から予期しないアクセス経路を生む原因になる。

比較表:完全分離・スキーマ分離・行レベル分離の選択基準

各モデルの特徴と適用条件

分離モデルの選択は初期設計で決定し、後から変更するコストが非常に高い。行レベル分離からスキーマ分離への移行は、データ移行・アプリ改修・テスト環境の再構築を伴い、テナント数が50社を超えた規模では数ヶ月単位の工数が発生しうる。下表は三つのモデルを主要な判断軸で整理したものだ。初期設計の段階で将来のテナント数と契約要件の上限を見据えた選択が求められる。

比較項目 完全分離(インスタンス分離) スキーマ分離 行レベル分離(RLS)
セキュリティ強度 最高(物理的に隔離) 高(スキーマ境界で分離) 中(アプリ・DB設定に依存)
テナント数の上限目安 〜10社程度 〜数百社 数百〜数千社
DB管理コスト 高(インスタンス数に比例) 中(スキーマ数に比例) 低(単一インスタンス)
テナント削除の容易さ インスタンス削除で完結 DROP SCHEMAで完結 全テーブルのDELETE文が必要
コンプライアンス適合 物理分離要件を満たしやすい 要件次第で対応可 論理分離のみ。規制業種では不可の場合あり
スキーママイグレーション テナント数分の実行が必要 テナント数分の実行が必要 一括で全テナントに適用可能

セキュリティ要件とモデルの対応

医療・金融・法律など、データの物理的分離を契約・規制上求められる業種では、行レベル分離は採用できない場合がある。「論理分離ではなく物理分離であること」を顧客と契約書レベルで取り決めているケースでは、スキーマ分離ですら不十分と判断されることがある。一方、SaaS型の汎用ツールで各テナントのデータ感度が低い場合は、行レベル分離で十分なセキュリティ要件を満たせる。設計の出発点は「どの分離が楽か」ではなく、「テナントと交わした契約・準拠すべき法規制が何を求めているか」から逆算することが重要だ。

分離レベルとコスト・運用負荷のトレードオフ

インフラリソースとスケールの現実

完全分離構成でテナントが50社になると、RDSインスタンスだけで50台、ECSクラスタやEC2も同数立てると管理対象リソースは数百単位に膨れ上がる。これをTerraformで管理しようとすると、モジュール設計と状態ファイルの管理が複雑化し、IaCのメンテナンスだけで1〜2名の工数を恒常的に要するケースがある。テナントごとにTerraformワークスペースやCloudFormationスタックを分ける設計は初期の整合性は高いが、共通コンポーネントの変更を全テナントスタックに伝播させる際の工数が累積していく。この累積コストを設計段階で試算せずに完全分離を選ぶと、運用開始後にチームの人的リソースを圧迫する。

運用手順の複雑度と設計の整合性

行レベル分離を採用するとDB管理の操作はシンプルになる一方で、アプリのバグがテナント境界を越えやすくなる。テナントごとの障害切り分けも、ログやメトリクスにテナントIDが一貫して付与されていなければ困難だ。運用設計は分離モデルと連動して最初から決める必要があり、「とりあえず動かして後からテナント対応する」という順序は、後工程で設計の根幹からやり直しになるリスクが高い。特に監視・アラート・ダッシュボードはテナントIDを軸にした集計が可能かどうかが、運用品質を左右する重要な設計判断だ。

SLAとテナント分離の関係

高可用性が求められるテナントと、開発・検証用の低優先テナントを同一インフラに混在させると、ノイジーネイバー問題(隣接テナントの負荷が性能に波及する問題)が生じる。テナントのSLAが99.9%と99.5%で異なる場合、同一構成で両方を満たそうとすると設計が歪む。SLAのレベルごとにクラスタやインスタンスを分ける「ティアリング」設計を初期から組み込むことで、分離の粒度と運用コストのバランスを取りやすくなる。ティアリングはテナントを完全に分離するほど強固ではないが、共有リソースの影響を限定的にする現実的な選択肢だ。

テナント追加・削除をどう設計に織り込むか

オンボーディングの自動化設計

テナント追加を手動で行う設計は、テナント数が10社を超えたあたりから対応漏れが目立ち始める。典型的な失敗は「DBスキーマの初期化は自動化したが、IAMロールとS3バケットのACL設定は手作業で残った」というパターンだ。テナント追加に必要なリソース(DB・IAM・ネットワーク・監査設定・通知先・ログストリーム)をすべてIaCテンプレートで一括プロビジョニングできるよう設計しておくことが重要で、手順書ベースの対応は担当者の異動・増員のたびに品質がぶれる。オンボーディングをコード化することで、テスト環境のセルフサービス化やCI/CDへの組み込みも現実的になる。

テナント削除とデータ完全消去の設計

テナントが解約した際のデータ扱いは、契約前から設計に含める必要がある。物理削除・論理削除・アーカイブ保持の選択は、法的保管義務と顧客との契約によって変わる。特に行レベル分離では「テナントAのデータをすべて削除してください」という要求に対し、テナントIDで絞り込んだDELETEを全テーブルに確実に適用できるか、外部キー制約や非正規化テーブルの見落としがないか、事前に削除スクリプトの網羅性を検証しておく必要がある。スキーマ分離ならDROP SCHEMAで完結するため、削除設計がシンプルになるという点も、分離モデル選択の判断材料になる。

テナントごとのバージョン差分管理

大規模SaaSでは、全テナントを同時に新バージョンへ移行できないケースがある。テナントAは新機能の早期アクセス中、テナントBはまだ旧バージョンという並行運用が発生することがあり、これをアプリ層のフィーチャーフラグで制御するのか、テナントごとに異なるデプロイ単位を持つのかは設計時に方針を決めておく必要がある。並行バージョンのサポートが長期化するほどテスト工数が掛け算的に増えるため、バージョン差分の許容期間と強制移行のタイミングも設計フェーズで定義しておくことが求められる。

分離しすぎ・共有しすぎの境界の見極め

過剰分離が生む運用の硬直

テナント10社それぞれに専用のアプリサーバー・DB・監視スタックを立てると、インフラの総量は大きくなる一方で、共通のセキュリティパッチ適用やミドルウェアの更新が全テナント分の作業に膨れ上がる。あるプロジェクトでは、共通コンポーネントのアップデートを全テナント環境に適用するだけで毎月20時間近い工数を要していたという話を聞く。分離設計はセキュリティ上有利だが、運用の維持可能性とのバランスで判断しなければ、チームの人的コストが設計の整合性を内側から崩していく。過剰分離は「安全に見える」だけで、長期的には脆弱性対応の遅延という別のリスクを生む。

共有しすぎによるテナント汚染

一方で、非同期ジョブキューを全テナントで共有している場合、テナントAが大量ジョブを投入すると他テナントのジョブ処理が遅延する「テナント汚染」が起きる。これを防ぐには、キューをテナントごとに分けるか、優先度付きキューで制御する必要があるが、後者は優先度設計が複雑になる。共有リソースの候補(キュー・ストレージ・CDN・ログ収集エンドポイント)をリストアップし、テナント間干渉が発生するリスクを一つずつ評価する設計フェーズが、実装前に欠かせない。

境界の判断基準となる問い

分離か共有かを迷った際の判断軸は「このコンポーネントで別テナントのデータが見えるリスクがあるか」と「テナントAの問題がテナントBの可用性・性能に波及するか」の二点に集約できる。両方にNoであれば共有してコストを下げる。いずれかにYesなら分離を検討する。設計の根拠をドキュメントに残しておくことで、テナント数が増えたときに境界の見直しが判断しやすくなる。この問いを各コンポーネントに対して繰り返す習慣が、過剰分離も過剰共有も避けた現実的な設計を支える。

マルチテナント設計チェックフレーム

設計前に確認すべき要件

設計に入る前に、テナントのデータ分離レベルに関する要件を契約・法規制・顧客との合意から明確にしておく必要がある。この確認を怠ると、実装後に「物理分離が必要だと判明した」という状況になり、大規模なリアーキテクトが発生する。特に確認すべきは、データの地理的保管要件(リージョン指定の有無)、業界規制(HIPAA・ISMS等)への準拠義務、テナントへの監査証跡の提供義務の有無だ。これらは分離モデルの選択を根本から制約する条件になる。要件が曖昧なまま設計を進めることが、後工程での最大のリスクになる。

マルチテナント設計チェックリスト

以下のチェックリストは設計フェーズで参照するものだ。「済」にならないまま実装に入った項目は、後から修正するコストが高くなる傾向がある。手を動かす前に各項目の判断根拠をドキュメントに残しておくことで、チームの認識齟齬を防ぎ、後から参照したときに設計意図が追える状態を保てる。

  • テナントのデータ分離要件(論理分離か物理分離か)を契約・規制から確認し、分離モデルを決定した
  • 行レベル分離を採用する場合、DBエンジン側のRow Level Security(RLS)を有効化することを設計に明記した
  • セッションストアとキャッシュのキー設計にテナントIDが含まれている
  • CDN・リバースプロキシのキャッシュがテナント間で混在しない設計になっている(サブドメイン分離またはVaryヘッダー設定)
  • ログ・監査証跡にテナントIDが必須フィールドとして含まれる設計になっている
  • テナント追加・削除がIaCテンプレートで自動化されており、手順書に依存していない
  • テナント削除時の全テーブルDELETEスクリプトを、外部キー制約・非正規化テーブルを含めて網羅的に検証した
  • 非同期キューやバッチ処理でノイジーネイバー問題への対策(テナント別キューまたは優先度制御)を設計した
  • SLAの異なるテナントをティアリングする方針(同一クラスタか別クラスタか)を決定した
  • IAMの分離モデルがDBの分離モデルと整合している(一方だけが共有という矛盾がない)
  • 各コンポーネントの分離判断の根拠を設計ドキュメントに記録し、テナント増加時に見直せるようにした

▶ 手を動かして本番まで到達する

その設計判断を、RHEL10の本番環境で手を動かして固めませんか

ここまでの設計判断は、読めば腹に落ちます。ですが「自分の手で本番まで通しきる自信」は、それとは別の話になります。

最大6名の少人数で、構築実務者の到達点まで引き上げます。座学で終わらせず、本番相当の環境で判断を検証する2日間です。

マルチテナント分離を本番環境で確かめる上級ハンズオンへ →

Linuxセミナー上級編(RHEL10)|最大6名の少人数ハンズオン