

# サーバーレス SaaS
<a name="serverless-saas"></a>

 SaaS 提供モデルへの移行には、コストと運用の効率を最大限にしたいという動機が伴っています。テナントのアクティビティの予測が難しい、マルチテナントの環境では、これは特に困難となります。テナントのアクティビティをリソースの実際の消費量に合わせるようスケーリング戦略のバランスを取ることは困難です。今は機能している戦略も、将来は機能しなくなるかもしれません。 

 これらの要因により、サーバーレスモデルにおいて SaaS が説得力のある選択となります。SaaS アーキテクチャからサーバーの概念を取り除くことで、組織はアプリケーションが消費する正確な量のリソースをスケーリングして提供するための、マネージドサービスを活用できます。これにより、アプリケーションのアーキテクチャと運用上のフットプリントが簡素化され、スケーリングのポリシーに継続的に追われ管理する必要性がなくなります。また、運用上のオーバーヘッドと複雑さも低減され、運用上の責務をマネージドサービスに任せることができます。 

 AWS は、サーバーレスの SaaS ソリューションを実装するために使用できる幅広いサービスを提供しています。図 1 はサーバーレスのアーキテクチャの例を示しています。 

![\[サーバーレス SaaS アーキテクチャ\]](http://docs.aws.amazon.com/ja_jp/wellarchitected/latest/saas-lens/images/image2.png)


*図 1: サーバーレス SaaS アーキテクチャ*

 サーバーレス SaaS アーキテクチャの稼動部は、従来のサーバーレスのウェブアプリケーションアーキテクチャとさほど変わらないことがわかります。この図の左側では、Amazon S3 バケットからホストおよび配信される、ウェブアプリケーションがあることがわかります (おそらく、React や Angular などの最新のクライアントフレームワークのいずれかを使用しています)。 

 このアーキテクチャでは、アプリケーションは Amazon Cognito を SaaS ID プロバイダーとして活用しています。認証サービスは、JSON Web Token (JWT) を介して提供される SaaS のコンテキストを含むトークンを生成します。このトークンはその後、すべてのダウンストリームのアプリケーションサービスとのやり取りに挿入されます。 

 サーバーレスアプリケーションのマイクロサービスとのやり取りは、Amazon API Gateway によって調整されます。ここで、ゲートウェイは複数の役割を果たします。受信するテナントのトークンを (Lambda オーソライザーを介して) 検証し、各テナントのリクエストをマイクロサービスにマッピングするほか、(使用プランを介して) 異なるテナント層の SLA の管理に使用できます。 

 SaaS アプリケーションのマルチテナントの IP を実装するさまざまなサービス用のプレースホルダーである、一連のマイクロサービスも示されています。各マイクロサービスは、マイクロサービスの契約を実装する 1 つ以上の Lambda 機能から構成されます。マイクロサービスのベストプラクティスに合わせて、これらのサービスは自身が管理するデータのカプセル化も行います。これらのサービスは、必要な場所にテナントのコンテキストを取得して適用するために、受信された JWT トークンを使用します。 

 また、各マイクロサービスのストレージも示されています。マイクロサービスのベストプラクティスに従うために、各マイクロサービスは自身が管理するリソースを有しています。例えば、データベースは 2 つのマイクロサービスが共有することはできません。マルチテナントのデータの提示はサービスごとに変化する性質のため、SaaS はここでも力を発揮します。あるサービスでは各テナントに対する個別のデータベースがあり (サイト)、一方他のサービスでは同じテーブル内のデータを混在させる場合があります (プール)。ここで行われるストレージの選択は、コンプライアンス、他のテナントによる影響、隔離、パフォーマンスの考慮事項によって決定します。 

 最後に、この図の右側には一連の共有サービスがあります。これらのサービスは、図の左側で稼動するすべてのテナントによって共有された、すべての機能を提供します。これらのサービスは、通常はテナントのオンボード、管理、運用が必要な、独立したマイクロサービスとして構築される一般的なサービスを表しています。 

 一般的なサーバーレス Well-Architected のベストプラクティスの詳細は、[サーバーレスアプリケーションレンズのホワイトペーパー](https://docs.aws.amazon.com/wellarchitected/latest/serverless-applications-lens/welcome.html)でご確認いただけます。 

# クロステナントのアクセスの防止
<a name="preventing-cross-tenant-access"></a>

 各 SaaS アーキテクチャでは、テナントが他のテナントのリソースにアクセスするのを防止する方法についても考慮する必要があります。設計上は、特定のタイミンで Lambda 機能を実行できるのは 1 つのテナントのみであるため、AWS Lambda を使用してテナントを隔離する必要性について疑問に思われるかもしれません。確かにそのとおりですが、隔離において、機能を実行しているテナントが、他のテナントに属する可能性のある他のリソースにアクセスしないようにする必要もあります。 

 SaaS プロバイダーにおいて、サーバーレス SaaS 環境に隔離を実装するための基本的なアプローチが 2 つあります。この最初のアプローチでは、サイロのパターンに従い、各テナントの Lambda 機能の個別のセットをデプロイします。このモデルでは、各テナントの実行ロールを定義し、各テナントの個別の機能をその実行ロールとともにデプロイします。この実行ロールは、特定のテナントでどのリソースがアクセス可能なのかを定義します。このモデルで一連のプレミアム層のテナントをデプロイするとします。しかし、これは管理が困難で、アカウントの制限に達する可能性があります (システムがサポートするテナント数による)。 

 もう 1 つのアプローチは、プールモデルにより合わせられています。ここでは、すべてのテナントからの呼び出しを受け入れるために十分な範囲を持つ実行ロールとともに、機能がデプロイされます。このモデルでは、マルチテナントの機能の実装でのランタイムで、隔離を適用する必要があります。図 2 は、これがどのようにして行われるかを示しています。

![\[Multi-tenant architecture diagram showing isolation context, AWS Lambda, and IAM integration.\]](http://docs.aws.amazon.com/ja_jp/wellarchitected/latest/saas-lens/images/image3.png)


*図 2: サーバーレス環境での隔離*

 この例では、一連の Lambda 機能にアクセスする 3 つのテナントがあることがわかります。これらの機能は共有されているため、すべてのテナントをカバーする実行ロールとともにデプロイされます。これらの機能の実装の中で、AWS Security Token Service (AWS STS) からの新たな一連のテナント範囲の認証情報を取得するために、現在のテナントのコンテキスト (JWT を介して提供される) が使用されます。これらの認証情報があれば、テナントのコンテキストでリソースにアクセスするために使用できます。この例では、ストレージにアクセスするためにこれらの範囲が指定された認証情報を使用します。 

 このモデルでは、隔離モデルの一部が Lambda 機能のコードにプッシュされるという点に注意してください。デベロッパーの視野外でこの概念を導入できる、機能ラッパーなどのテクニックがあります。これらの認証情報の取得の詳細を Lambda レイヤーに移動させ、さらにシームレスで中央管理された構造にすることもできます。 

# レイヤーがテナントの詳細を隠す
<a name="layers-hide-tenant-details"></a>

 あらゆる SaaS アーキテクチャにおける目標の 1 つとして、デベロッパーにテナントの詳細を意識させないことがあります。サーバーレス SaaS 環境では、デベロッパーの視野外でマルチテナントのポリシーを実装できる、共有コードを作り出すための方法として、Lambda レイヤーを使用できます。 

 図 3 は、これらのマルチテナントの概念を実現するために Lambda レイヤーをどのように使用できるのかの例を示しています。ここで、ログと指標のデータを発行する必要がある、2 つの異なるマイクロサービス (生産と注文) があります。重要な点として、両方のサービスが、テナントのコンテキストをログメッセージと指標イベントに挿入する必要があります。しかし、各サービスにこれらのポリシーをそれぞれ実装することは理想的ではありません。代わりに、このデータの発行を管理するコードを含むレイヤーを導入しました。 

![\[alt text not found\]](http://docs.aws.amazon.com/ja_jp/wellarchitected/latest/saas-lens/images/image4.jpg)


*図 3: Lambda レイヤーがテナントの詳細を隠す*

 レイヤーに、JWT トークンを受け入れるログと指標のヘルパーが含まれていることがわかります。これにより、マイクロサービスがどのテナントを取り扱っているのかを心配することなく、各マイクロサービスがシンプルにこれらの機能を呼び出し、トークンを供給できるようになります。その後、レイヤー内で、コードが JWT トークンを使用してテナントのコンテキストを解決し、ログメッセージと指標イベントに挿入します。 

 これは、テナントのコンテキストを隠すためにレイヤーを適用する方法の一例にすぎません。テナントのコンテキストを挿入するためのポリシーとメカニズムを、デベロッパーは一切意識しなくてよいことに真の価値があります。これらはまた個別に更新、バージョン管理、デプロイされます。遅延とボトルネックの原因となる恐れがある個別のマイクロサービスを導入することなく、環境内でこれらのポリシーをさらに中央的に管理できるようになります。 