📖

re:Invent 2024: AWSによるサーバーレスSaaSアーキテクチャ構築入門

に公開

はじめに

海外の様々な講演を日本語記事に書き起こすことで、隠れた良質な情報をもっと身近なものに。そんなコンセプトで進める本企画で今回取り上げるプレゼンテーションはこちら!

📖 AWS re:Invent 2024 - Getting started building serverless SaaS architectures (SEG209)

この動画では、Serverlessを活用したSaaSアプリケーションの構築について、具体的な実装方法が解説されています。AWS Lambdaが10周年を迎え毎月数十兆のリクエストを処理している現在、ServerlessはSaaSアーキテクチャの標準となっています。メカニック管理ソフトウェアを例に、Amazon CloudFront、API Gateway、DynamoDB、EventBridgeなどを組み合わせたマルチテナント構成の実装方法や、テナントコンテキストの維持、データアクセスの制御、非同期通信パターンなどの技術的な詳細が説明されています。また、プール型モデルへの移行戦略やリスク軽減のためのデプロイメント手法など、実践的なノウハウも共有されています。
https://www.youtube.com/watch?v=5TBzdDV60wE
※ 動画から自動生成した記事になります。誤字脱字や誤った内容が記載される可能性がありますので、正確な情報は動画本編をご覧ください。
※ 画像をクリックすると、動画中の該当シーンに遷移します。

re:Invent 2024関連の書き起こし記事については、こちらのSpreadsheet に情報をまとめています。合わせてご確認ください!

本編

Serverlessが変えるSaaSの世界:イントロダクション

Thumbnail 0

おはようございます。SEG 209へようこそ。皆さん、朝9時からMandalay Bayに来て、この会場を見つけられたことを称賛したいと思います。私も苦労しました。今朝5キロを走った方はいますか?誰もいませんね。現在、かつては運用チーム全体を必要としたエンタープライズグレードのアプリケーションを、1人の開発者が構築してデプロイできる時代に私たちは生きているといえるでしょう。Serverlessがゲームチェンジャーとなったのです。今では、ゼロから数百万ユーザーまでスケールできるSaaSアプリケーションを構築でき、アイドル状態での課金もなく、サーバーの管理も必要ありません。

Serverlessは新しい技術ではありません。実際、Serverlessの先駆者であるAWS Lambdaは今年で10周年を迎え、現在では毎月数十兆のリクエストを処理しています。Serverlessは現代のSaaSアーキテクチャの標準となっています。私はThomas Mooreと申します。イギリスのSenior Solution Architectで、Serverlessのスペシャリストとしてソフトウェアベンダーと協力して仕事をしています。日々お客様とお話しする中で、3つの共通したニーズがあります。それは、モダナイゼーション、コストの最適化、そして本当に重要なことに集中するための時間の確保です。このセッションでは、Serverless SaaSを通じてそれらの実現方法をお示ししたいと思います。

Thumbnail 130

Thumbnail 140

SaaSはビジネスの変革だけでなく、技術とビジネスの両面での変革であり、成功するためにはその両方が調和することが重要だということを覚えておいてください。ただし、これは技術的なトークですので、技術面に焦点を当て、主に3つのポイントについてお話しします。 1つ目は、ServerlessとSaaSの推進要因について理解することです。 また、顧客とのマルチテナンシーの実装方法についての技術的な詳細に焦点を当て、カスタマーパターンを使用してアーキテクチャの課題を解決していきます。すべてを実世界の例を用いて説明していきます。

AnyCompanyの事例:従来型ソフトウェアからSaaSへの進化

Thumbnail 150

Thumbnail 190

では、その例を紹介しましょう。車やバイク、バンなどの車両を所有している、もしくは所有したことがある方はいらっしゃいますか?その中で、整備や修理で良くない経験をしたことがある方は手を挙げたままでお願いします。私もよく、予約を取るために何カ所も電話をかけまわったり、電話で予定調整のやり取りを何度もしたり、修理に出しても状況報告の連絡がなく、最後に大きな請求書が来たりした経験があります。 AnyCompanyのメカニック管理ソフトウェアは、整備士のビジネスが顧客により良い体験を提供できるように設計されています。エンドカスタマーにとっては、オンライン予約、整備リマインダー、電子的な請求書発行と支払いが可能になるという素晴らしいメリットがあります。整備士側にとっては、部品と在庫の管理、技術者のシフト管理、そしてソフトウェア内での診断機能を利用できます。

Thumbnail 240

これは今日の例として使用するものですが、セッションを通じて、これらがご自身のビジネスにどのように当てはまるかを考えていただければと思います。AnyCompanyがどこから始まったのか見てみましょう。会場にいらっしゃるISV(Independent Software Vendor)の方々にとっては、馴染みのある話かもしれません。 このソフトウェアは2000年代初頭にダウンロード版としてリリースされました。整備士たちはオンラインで永続ライセンス料を支払い、ソフトウェアをダウンロードして自分でインストールして使用していました。整備士の事業者は車の修理は得意ですが、ITインフラの運用は得意ではないかもしれません。AnyCompanyにとって、これはサポートの悪夢でした。様々な方法でインストールされ、あらゆる種類の奇妙なハードウェアで動作していたのです。

Thumbnail 270

Thumbnail 280

Thumbnail 290

Thumbnail 300

この問題を解決し、クラウドの発明へと進むため、AnyCompanyは自社のお客様に代わってソフトウェアをホスティングすることを決定しました。 この時点で、AnyCompanyはManaged Service Provider(MSP)と呼べる存在となりました。 ただし、後ほど説明する課題があるため、彼らは実際にはSaaS企業としては運営していませんでした。これらの課題については後で詳しく説明しますが、将来的には、来年にServerlessプロダクトとSaaSプロダクトをローンチすることを目指しています。

Thumbnail 320

Thumbnail 330

Thumbnail 340

Thumbnail 350

AnyCompanyのお客様は、従業員が数人の小規模な家族経営の企業から、大規模な国内企業や国際企業まで、さまざまな規模で存在します。これ以降、これらのお客様のことを「Tenant」と呼ばせていただきます。 Tenantは、あらゆるSaaSソリューションを構築する上での基本的な概念です。Tenantは、そのSaaSソフトウェアのユーザーを指します。皆さんのビジネスにおいて、誰がTenantになるのか考えてみてください。 特に大規模な国際企業を考えると、この定義はかなり複雑になる可能性があります。 時間とともに複数の企業買収を通じて有機的に成長してきた場合、Tenantは親会社なのか、子会社なのか、あるいは単一の拠点なのか、という疑問が生じます。

Thumbnail 370

Thumbnail 390

Thumbnail 400

Tenantをどのように定義するかは実はそれほど重要ではありませんが、データの認証やパーミッションの実装に関わる基本的な要素となるため、できるだけ早い段階で定義することが重要です。これが現在のホスティングソリューションの状態です。各Tenantはソフトウェアのコピーを持ち、 それぞれが独自のリソースを持っています。現在はAmazon EC2上で稼働しており、アプリケーションは一部のEC2インスタンス上に、データベースは別のEC2インスタンス上に存在します。AnyCompanyはソフトウェアのセキュリティ、 パフォーマンス、および耐障害性の確保に責任を持っています。Tenant1はソフトウェアのバージョン1.2を実行しており、 Tenant2ははるかに新しいバージョン3.23を実行しています。そしてTenant3は、大口顧客の1つであり、マーケティングシステムとの統合のためのカスタムプラグインを要求したため、カスタマイズされたバージョン1.46を実行しています。

マルチテナント環境におけるデータアクセスとセキュリティの実現

Thumbnail 440

Thumbnail 460

Thumbnail 470

これは、MSPとSaaSプロバイダーの違いを示す症状あるいは特徴の1つです。私たちはTenantに対して、実行するバージョンの選択権を与え、カスタマイズも提供してきました。SaaSソリューションを構築する際は、シームレスなオンボーディングを伴う統一されたエクスペリエンスを目指し、通常はすべてのTenantが同じバージョンを実行することになります。 では、他の現在の課題は何でしょうか?Tenant1は新機能がいつ提供されるのかについて不満を持っています。機能自体はすでにリリースされていますが、古いバージョンを使用しており、アップグレード方法がわからないか、アップグレードが困難な状況です。Tenant2は最新バージョンを使用していますが、 AnyCompanyの競合他社がより優れた機能をより低コストで提供しています。そしてTenant3は、オンボーディングにかかる時間が長すぎる、つまりソフトウェアの導入から実際の使用開始までの時間について不満を持っています。

Thumbnail 480

Thumbnail 500

Thumbnail 520

AnyCompanyも低い利用率に悩んでいます。Tenantはコストがかかります。一部のTenantがソフトウェアをほとんど使用していない場合でも、24時間365日の可用性と耐障害性を確保するために、複数のAvailability Zoneにわたって最低限のEC2インスタンスを維持する必要があります。Tenantはアップグレードするまで最新機能を使用できません。 セキュリティ修正のロールアウトも困難です。数十、数百、あるいは数千のTenantがいる場合、優れた自動化があっても、オペレーティングシステムの更新、ランタイムの更新、アプリケーションの更新をロールアウトする必要があり、時間がかかります。また、データからインサイトを得ることも困難です。なぜなら、 Tenantごとにデータベースインスタンスがあり、データがサイロ化されているからです。

Thumbnail 530

Thumbnail 540

Thumbnail 560

これらの課題は3つの将来のビジョンにまとめることができます。1つ目は市場投入までの時間短縮、2つ目はコスト削減、そして3つ目はイノベーションの促進です。これを実現するために、AnyCompanyはすべてのテナントが同じバージョンのソフトウェアを使用することを目指します。共有リソースを活用したマルチテナントソリューションへの移行を進め、より多くの責任をAWSに移管し、データサイロを減らしていきます。つまり、私たちが話しているのはSaaSについてです。では、なぜServerlessなのでしょうか?サーバーの管理は大変です。私は10年以上サーバーを管理してきましたが、OSの設定やハードニング、セキュリティパッチの展開を自動化するための作業に多くの時間を費やしてきました。そして、それはエンドカスタマーにとってはほとんど価値のない膨大な労力でした。Serverlessはサーバーを取り除き、お客様が求める機能や価値を直接実装することができます。また、リクエストに応じて自動的にスケールアップし、リクエストがなくなるとゼロまでスケールダウンします。さらに、3つのAvailability Zoneにまたがって構築されているため、最初から高可用性が確保されており、私たちはそのことを考える必要がありません。

このServerlessのメリットは、現代のお客様の期待と企業の目標に合致しています。現代のお客様は最新の機能を求めており、しかもそれを素早く手に入れたいと考えています。アップグレードについて心配する必要もありません。AnyCompanyとしては、シームレスなオンボーディング、運用効率の向上、市場の変化への適応力が求められています。

Thumbnail 640

SaaSは製品を作ることではなく、サービスを構築することだということを忘れないでください。お客様のオンボーディングの方法、価値実現までの速さ、そしてニーズに応える新機能の導入方法について考えてください。車の修理を例に考えてみましょう。もちろん修理の品質は重要ですが、同時にサービスの質も重要です。つまり、修理にかかる時間、予約のしやすさ、コミュニケーションの取り方などです。

Thumbnail 670

Thumbnail 700

SaaSソリューションでサービスを提供する際、AWSでSaaSについて話すとき、私たちはコントロールプレーンの構築の重要性を強調します。これはアプリケーションの外側にあって、メトリクス、オンボーディング、管理、課金などを制御するサービス群のことです。これによって、期待されるサービスを実現できます。今日は、アプリケーションプレーンに焦点を当て、サービスを使用してマルチテナントアプリケーションプレーンを構築する方法についてより深く掘り下げていきます。

Thumbnail 720

Thumbnail 730

まずはServerlessの概要から始めましょう。基本的な概念を確認した後、エントリーポイント、権限データの管理方法、統合パターンを使用したサービス間通信、そして更新と移行について見ていきながら、アーキテクチャを組み立てていきます。それでは、Serverlessの紹介から始めましょう。まず、Serverlessアプリケーションを構築するためにAWSで利用できるサービスについて見ていきましょう。

Serverlessアーキテクチャの構成要素とエントリーポイントの設計

Thumbnail 770

Thumbnail 780

Amazon CloudFrontは静的コンテンツの配信のためのサービスです。これは世界中に450以上のEdge Locationを持つコンテンツデリバリーネットワークで、静的コンテンツをエンドユーザーの近くに配置することができます。また、リージョンまでアクセスするよりもずっと高速にAWSのバックボーンへのネットワークアクセスを可能にします。マルチテナントソリューションでは、動的なオリジンルーティングやエッジでのセキュリティポリシーの制御なども行うことができます。APIについては、RESTful APIの構築とWebSocketsのプロビジョニング用にAmazon API Gateway があり、GraphQL APIのプロビジョニング用にはAWS AppSyncがあります。認証にはAmazon Cognitoを使用します。

Thumbnail 790

Thumbnail 810

Amazon Cognitoには、ここ数ヶ月で多くの新機能が追加されています。これは、アイデンティティ、ユーザー、権限を管理する場所です。 冒頭で触れたAWS Lambdaは基本的なサービスです。ここでビジネスロジックやカスタムコードを記述し、Python、.NET、Java、Node.jsなどのマネージドランタイムのいずれかでコードを書くことができます。ストレージについては、超低レイテンシーのキーバリューストアとしてAmazon DynamoDB、高耐久性のオブジェクトストアとしてAmazon S3があります。

Thumbnail 820

中央には、多くの統合サービスがあります。 これはマイクロサービス間の連携を実現するための接着剤のような存在です。AWS Step Functionsでオーケストレーションを行い、一連の手順でワークフローを構築できます。Amazon EventBridgeはイベントルーティングを行い、イベント駆動型アーキテクチャの構築を支援します。Amazon SNSはパブリッシュ-サブスクライブモデルを提供し、トピックに送信して複数のサブスクライバーにファンアウトできます。そしてAmazon SQSはメッセージキュー機能を提供します。

まとめると、これらのサービスはすべてサーバーレスです。自動的にスケールし、アイドル状態での課金はなく、複数のアベイラビリティーゾーンにわたって高可用性を実現します。整備士が休暇シーズンで店舗を閉める際にシステムの使用率が低下すると、自動的にスケールダウンしてコストを削減します。1人の整備士がオンラインになって過去5-10年分の部品や在庫、予約の報告を実行し始めると、自動的にスケールアップし、他のテナントに影響を与えることはありません。また、小規模なDevOpsチームを持つ企業にとっては、サーバーの保守、管理、パッチ適用の必要がありません。

Thumbnail 920

これらの構成要素を組み合わせることで、実質的にどのようなアプリケーションでも構築することができます。一般的な出発点は、サーバーレスWebアプリケーションです。整備士が作業を管理するためにログインする ポータル、受付スタッフが予約を管理するためのポータル、そしてエンドユーザーが予約を行うための場所が必要になるからです。

Thumbnail 940

Thumbnail 960

Thumbnail 970

アーキテクチャの構成はこのようになっています。ユーザーは、エントリーポイントであるAmazon CloudFrontディストリビューションにアクセスし、その背後にはAmazon S3バケットに静的コンテンツが配置されています。これは、ReactなどのモダンなWebフレームワークから生成されたHTML、CSS、JavaScriptなどの静的コードです。JavaScriptがブラウザにダウンロードされ、ブラウザは動的コンテンツを取得するために再度アクセスを行います。この動的コンテンツは、フロントドアとしてのAPI Gatewayを経由します。その背後には一連のAWS Lambda関数があり、Amazon DynamoDBからデータの読み書きを行います。

Thumbnail 980

Thumbnail 1000

これは、よく目にする一般的なパターンです。シンプルで構築も容易です。このモデルを、現在多くの企業が採用しているホステッドソリューションと同じように展開すると、このような形になります - 各テナントがリソースのコピーを取得することになります。これは既存のアーキテクチャと比べて、スケーラビリティが高く、責任をAWSに移行できるというメリットがありますが、管理面で課題が生じてきます。これを数十や数百のテナントユーザーにスケールアップすると、このような状況になります。監視と管理が分散化され、アップデートを展開する際には何度も同じ作業を繰り返す必要があります。優れた自動化を実現していても、監視する必要のあるコンポーネントが多数存在し、データの重複も発生する可能性があります。

Thumbnail 1030

Thumbnail 1050

Thumbnail 1070

これでは運用効率の向上は望めません。そこで、この問題を解決するために検討するのが、すべてのテナントが同じリソースセットを共有するプールドモデルです。このモデルは、より効率的で、展開が速く、運用が簡素化されるというメリットがあります。ただし、どのようなアーキテクチャでもそうですが、トレードオフは存在します。課題となるのは、テナント分離をどのように管理するかということです - あるテナントが他のテナントのデータにアクセスするのをどのように防ぐのか?Noisy Neighborの問題についてはどうか?あるテナントが他のテナントの利用体験に影響を与えるのをどのように防ぐのか?そして、影響範囲の問題 - アップデートが失敗した場合、すべてのテナントに影響が及んでしまうのではないか?

Thumbnail 1080

Thumbnail 1100

Thumbnail 1110

Thumbnail 1120

これらの課題をどのように解決するのか、順を追って見ていきましょう。まずはエントリーポイントから見ていきます。テナントがシステムにアクセスする際、先ほど説明したWeb UIを通じてアクセスするか、大規模テナントの場合は直接APIを統合して利用することになります。いずれの場合も標準的なHTTPSを使用し、そのためにドメイン名が必要になります。ドメイン名については、いくつかのオプションがあります。すべてのテナントが共有する汎用的な名前(portal.anycompany.comなど)を作成する方法があります。また、URLのパス内にテナントのコンテキストを含める方法や、各テナントに独自のサブドメインを提供する方法もあります。これらのオプションでは、エントリーポイントの時点でテナントのコンテキストを把握できます。さらに、各テナントに独自のカスタムドメインを提供することもできます - 例えば、カスタムブランディングを行いたい場合などです。

非同期処理とイベント駆動型アーキテクチャの活用

Thumbnail 1130

Thumbnail 1150

これらの実装方法はどうなるでしょうか?最初の2つのオプションは同じ方法で実装します - Amazon Route 53のDNS内にCloudFrontディストリビューションを指すエイリアスを作成します。そして、AWS Certificate Manager(ACM)を使用して無料の公開証明書を発行し、それをCloudFrontディストリビューションに関連付けます。2番目のオプションを実装する場合は、やや複雑になります。テナントをオンボードするたびに新しいDNSエントリを作成し、オフボードする際には削除する必要があります。ACM証明書は、ソリューションのスケーラビリティを確保するためにワイルドカード証明書に移行することになります。最後のオプションが最も複雑な実装となります。なぜなら、テナントが自身でDNSをCloudFrontディストリビューションに向ける必要があるか、私たちがテナントに代わってDNSを管理する必要があるためです。証明書に関しては、ACMで複数のSubject Alternative Names(SAN)を作成する必要がありますが、これにはスケールの制限があり、さらに複数のCloudFrontディストリビューションを作成する必要があります。これは有効なオプションですが、実装と保守がやや困難になります。

Thumbnail 1210

Thumbnail 1220

まずは、ドメインにテナントのコンテキストがない最初のオプションを見ていきましょう。ログインを通じてテナントのコンテキストをどのように取得するのか確認していきます。ユーザーがシステムにログインする際、ユーザー名の入力を求められます。このユーザー名を使って、どのテナントに所属しているかを検索することができます。

Thumbnail 1240

Thumbnail 1250

Thumbnail 1270

この時点ではまだパスワードの入力は求めていません。小規模なテナントに所属していることが分かった場合は、デフォルトのパスを選択し、パスワードの入力を求め、Amazon Cognitoのようなシステムに組み込まれたIdentity Providerで認証を行います。これは標準的なOpenID Connectプロトコルを使用します。その結果、JSON Web Token(JWTまたは「ジョット」と呼ばれる)が返されます。JWTは他のサービスへのアクセスを可能にする署名付きトークンです。Identity Providerのキーで署名され、その整合性が検証されます。また、有効期限や、名前、所属テナント、役割などのアイデンティティに関する情報(クレーム)が含まれています。

Thumbnail 1290

Thumbnail 1320

先ほどのユーザー名の検索に戻りますが、独自のIdentity Providerを使用したい大規模テナントに所属するユーザーであることが判明した場合、そのテナントが用意したIdentity Providerのログインページにリダイレクトすることができます。このページでは、例えばPINやMFAなどが求められる場合があります。OpenID Connectを使用している限り、同様にJWTが返されます。これで、エントリーポイントとログイン、そして有効なJWTを手に入れることができました。次は、これらを使ってサービスに対する認証をどのように行うのか見ていきましょう。

Thumbnail 1330

Thumbnail 1350

Thumbnail 1370

WebアプリケーションはこのJWTトークンをAPI Gatewayに渡します。これはHTTPヘッダー、具体的には認証ヘッダーまたはBearer tokenとして行われます。ここで、Lambda authorizerと呼ばれる新しいコンポーネントをアーキテクチャに追加する必要があります。Lambda authorizerはPython、Node.js、Java、.NETなどのカスタムランタイムで使用できる小さなカスタムコードで、リクエストを許可するか拒否するかを判断する役割を担います。その中でどのようなロジックを実装するかは自由です。JWTの検証が必要で、これにはIdentity Providerとの通信、カスタムキーの取得、整合性の検証、有効期限の確認、そして特定のAPIコールに対する認証権限を持っているかどうかのユーザーロールの確認が含まれます。

Thumbnail 1390

Thumbnail 1430

Lambda authorizerからは、コンテキストオブジェクトと呼ばれる、任意のキーと値のペアを返すこともできます。SaaSアプリケーションにとって重要なテナントIDもここに含めることができます。テナントIDはJWTから直接抽出するか、DynamoDBテーブルで検索することができます。Lambda authorizerはこのテナントIDと他のコンテキストオブジェクトをAPI Gatewayに返し、API Gatewayはそれらを下流のサービスに送信するように設定できます。これらの情報は、HTTPヘッダー、クエリ文字列、パスの一部として送信することができ、Lambdaを使用している場合は、イベントペイロードの入力の一部として送信されます。

Thumbnail 1440

Thumbnail 1470

みなさん、ここまでついてきていただけましたでしょうか。ドメインを取得し、ログインして認証を行い、JWTを受け取り、そのトークンを使ってAPIを通じて認可を行い、そしてTenant IDをダウンストリームのマイクロサービスに返しました。では、このTenantのコンテキストを使ってデータをどのように保存しアクセスするのか見ていきましょう。アーキテクチャでお話ししたように、 私たちはDynamoDBとS3という2つのサービスを使用しています。プールドモデルを採用しているため、データを書き込む際にはTenantのコンテキストが確実に存在している必要があります。

Thumbnail 1480

Thumbnail 1500

DynamoDBでは、Tenant IDをパーティションキーまたはプライマリーキーの一部として使用できます。このテーブルは全てのTenantで共有されていることを覚えておいてください。実際の運用では、ホットパーティションを避けるためにTenant IDの末尾にランダムな要素を追加しますが、ここでは簡略化のため省略しています。

Amazon S3については、Tenant毎にプレフィックスを使用します。Tenant毎にバケットを使用することも可能で、S3では最近、アカウントあたりのデフォルトクォータを100から10,000バケットに引き上げ、さらに100万までリクエスト可能になりましたが、Tenantのオンボーディングやオフボーディング時にバケットの作成や削除を行うのはやはりオーバーヘッドが大きいです。そのため、スケーラビリティを考慮して、Tenant毎のプレフィックスを使用する方法を採用します。

Thumbnail 1530

Thumbnail 1540

Thumbnail 1560

これがデータの保存方法ですが、 どのように安全にアクセスするのでしょうか?Lambda関数でデータにアクセスする場合、 Execution Roleと呼ばれるものがあります。Execution RoleはLambda関数に他のサービスへのアクセス権限を与えます。この場合、Jobsテーブルに対するDynamoDB GetItemアクセス、つまりDynamoDBテーブルへの読み取りアクセスを与えています。 コード内では、データにアクセスする際に、対象のTenantに制限するためのフィルター式やWHERE句を作成します。しかし、コードにバグがあったり何か問題が発生したりすると、誤って他のTenantのデータにアクセスしてしまう可能性があり、これは企業の評判に致命的なダメージを与えかねません。

Thumbnail 1590

Thumbnail 1620

では、これをどのように解決するのでしょうか?API Gatewayから渡されるTenant IDを活用することができます。 このTenant IDを使って、実行時に動的にロールを引き受けることができます。Lambda内で動的にIAMポリシーを作成し、Execution Role以外のロールを引き受けてデータにアクセスします。IAM内のLeading Keysと呼ばれる機能を使用して、テーブル内の特定のTenant IDのデータにのみアクセスを制限します。 これにより、Tenant 2のデータにアクセスしようとしても、アクセス拒否となります。これは一つの方法ですが、Session TagsやAssume Role with Web Identityなど他の方法もあり、このトピックに関する多くのブログ記事が公開されています。

Thumbnail 1650

Thumbnail 1660

Thumbnail 1670

S3でも同じことができます。データにアクセスする際、リソース内にTenant IDを配置し、そのテナントのファイルに対してのみパーミッションを制限することで、他のテナントの請求書へのアクセスを防ぐことができます。ここまでは、トランザクションデータの保存とアクセスについて見てきました。次は、分析をどのように行うかについて簡単に見ていきましょう。以前お話ししたように、どの企業もデータサイロの問題を抱えており、これらを解消してソフトウェアの使用状況を理解し、価格設定に活かし、新機能の開発に役立てたいと考えています。

Thumbnail 1690

Thumbnail 1710

Thumbnail 1730

例えば、故障率に基づいて最適な部品ブランドを顧客が選択できるような機能を作りたいかもしれません。これは、現在のアーキテクチャでは答えるのが非常に難しい分析的な問題です。なぜなら、中央の分析用ストアに対して多数のETLジョブが必要になるからです。しかし今は、共有のDynamoDBテーブルとバケット内のファイルを持つプール型データベースがあります。DynamoDBはトランザクションストアとしては優れていますが、複雑なJoinを伴う分析クエリには適していません。より適しているのは、S3バケット内のData Lakeにデータを保存することです。

Thumbnail 1740

Thumbnail 1760

Thumbnail 1770

では、どのようにしてデータをそこに取り込むのでしょうか?DynamoDBの組み込み機能を使用して、データを直接Amazon Kinesis Data Streamsにストリーミングすることができます。これはChange Data Captureストリームなので、テーブルにCreate、Read、Update、Delete操作が入ってくると、ほぼリアルタイムでKinesisに直接ストリーミングされます。KinesisをAmazon Data Firehoseに接続すると、Lambdaで変換を行い、S3に動的にパーティション分割してデータを保存できます。つまり、DynamoDB内のこのような状態からS3内でこのような状態に変換されるということです。データは必要に応じてテナントごとにパーティション分割されたままですが、Amazon Athenaを使用してデータ全体に対してクエリを実行することもできます。最新のS3 Data Tablesのアナウンスにより、Amazon Data FirehoseからS3上のApache Icebergテーブルに直接ストリーミングすることも可能になりました。ここで少し視点を変えてみましょう。

AWS Step Functionsを用いたワークフローオーケストレーション

Thumbnail 1810

Thumbnail 1830

ここまでは同期型APIについて見てきましたが、統合についてはどうでしょうか?私たちが構築するマイクロサービス間でどのように通信すればよいのでしょうか?最も効率的な方法で、これをどのように実現すればよいのでしょうか?これまで見てきたものはすべて同期型でした - リクエストを送信し、レスポンスを待ちます。これはシンプルで、素早く失敗が分かり、レイテンシーも低いです。しかし、レシーバーが失敗した場合はどうでしょうか?ビジネスを失いたくないので、サービスや修理の予約は引き続き受け付けたいものです。レシーバーの処理に時間がかかる場合はどうでしょうか?支払いを受け付けて請求書を作成する場合、データの受信に数分、あるいは数時間かかるかもしれません。レシーバーが突然大量のリクエストを受けて処理が追いつかなくなった場合はどうでしょうか?来週の猛暑予報で、みんながエアコンのガス補充を予約しようとした場合はどうでしょうか?

Thumbnail 1870

Thumbnail 1900

これらの問題を解決するために非同期アーキテクチャを検討できます。可能な限り非同期を使用するべきです。ここでは、中間にキューを導入しました。送信者がメッセージを送信すると、それは直接キューに入り、データは永続化されます。そのため、レシーバーが失敗してもキュー内にメッセージが残ります。レシーバーは自分のペースでメッセージを処理できます。失敗した場合は再処理が可能で、より効率的に処理するためにバッチ処理もできます。Publish/Subscribeも使用できます。これも非同期ですが、今度は同じメッセージに複数の関係者が興味を持っている場合です。メッセージをトピックに送信すると、それが複数のサブスクライバーにファンアウトされます。

Thumbnail 1930

Thumbnail 1940

それでは、メカニック管理ソフトウェアの例を使って、これらのパターンをどのように活用できるか見ていきましょう。 修理工場のメカニックがオイル交換を終えて、ソフトウェアで作業完了のマークを付けようとしているシーンを想像してください。 これにより、API Gatewayを通じてLambda関数にリクエストが送られ、DynamoDB内のデータベースが更新されます。ここで、お客様への支払い請求も行いたいとします。請求書を作成し、PDFを生成して、支払いリクエストを送信する必要があります。これには少し時間がかかる可能性があります。

Thumbnail 1960

Thumbnail 1970

Thumbnail 1980

Thumbnail 1990

これは、Amazon SQSにメッセージを送信することで非同期的に処理できます。 SQSキューをサブスクライブするLambda関数を作成し、これはEvent Source Mappingと呼ばれ、請求書を生成してAmazon S3に保存します。これはこの例を処理する方法の一つに過ぎません。 もう一つの例を見てみましょう。技術者が車の診断ビデオを録画する場合です。 これは、必要な修理や車の下部で完了した修理を見せることで、お客様との信頼関係を築くのに役立ちます。

Thumbnail 2000

Thumbnail 2010

ビデオが録画されると、Amazon S3バケットに保存されます。 そして、S3のEvent Notifications機能を使用して、ファイルが到着したときに自動的にキューにメッセージを送信できます。ここでも、キューをサブスクライブするLambda関数があり、これがビデオを処理し、セキュアなダウンロードリンクを作成し、Amazon SESを使用してお客様にビデオリンクをメールで送信します。

Thumbnail 2030

Thumbnail 2050

ここで、Poolモデルで何が起きているか考えてみましょう。 すべてのTenantが同じリソースセットを共有している状態では、すべてのメッセージが同じキューに入ります。Tenant 1、Tenant 2、Tenant 3と、到着順に処理されます。Amazon SQSには、このTenantのコンテキストを維持するのに役立つMessage Attributesという機能があります。 Message Attributesを使用してメッセージに関する情報(メタデータ)を追加でき、ここでTenant IDを保存できます。

Thumbnail 2060

Thumbnail 2080

Lambda関数をSQSキューにサブスクライブしてEvent Source Mappingを設定する際、デフォルトでバッチサイズが設定されています。ここではバッチサイズが10に設定されており、これはLambda関数が一度に10個のメッセージを受け取り、1回の呼び出しですべてを処理することを意味します。なぜこれが重要なのでしょうか? 先ほどの例で、データに安全にアクセスするためにRoleを引き受けた場合を考えてみましょう。1回の呼び出しで複数のTenantのメッセージがある場合、ループ処理する必要があります。これはキューのスループットに依存します。

Thumbnail 2110

バッチサイズを1に設定して、一度に1つのテナントだけを受け取るようにすることもできますが、これは最も効率的な方法ではないかもしれません。各テナントに独自のSQSキューを割り当てることで、公平性を管理し、権限の問題も回避できます。ただし、キューのプロビジョニングや削除、監視、メンテナンスが必要になるため、オンボーディングとオフボーディングの管理がより複雑になります。

Thumbnail 2130

Thumbnail 2150

Thumbnail 2160

統合についてさらに考えると、イベントについて考える必要があります。サービスアーキテクチャについて話す際、サービスの構築方法としてイベント駆動型アーキテクチャについてよく言及します。整備士が修理完了をマークした時のことを考えてみましょう。それはLambda関数に送られ、DynamoDBを更新しましたが、ここでイベントが発生しました - つまり、作業が完了したということです。このイベントに関心を持つ他のサービスがあるかもしれません。請求書の送信や、顧客への通知、修理に関する社内文書の作成、使用した部品の在庫更新などが必要です。

Thumbnail 2180

Thumbnail 2190

Thumbnail 2210

そこで、イベントをAmazon EventBridgeに送信できます。EventBridge内では、イベントバスと呼ばれるものを作成します。イベントバス内では一連のルールを作成でき、これらのルールは基本的にイベントのパターンマッチングを行い、並行して様々なアクションをトリガーします。AWS Step Functionsを使用して支払い処理を開始したり、Lambda関数内で次の作業の準備ができたことを示すようにワークショップの容量を更新したりできます。素晴らしいのは、拡張性があることです。将来、複雑な修理を理解するためのドキュメント更新など、新機能を追加したい場合、既存のコードを変更することなく、新しいルールを作成するだけで実現できます。このように、非常に拡張性が高く、新機能の追加が容易です。

Thumbnail 2230

Thumbnail 2250

イベントのスキーマは以下のようになります。EventBridgeには、source、detail-type、detailオブジェクトなどの必須フィールドがあります。detailオブジェクト内には、好きな情報を入れることができます。コンテキストを維持するために、tenant IDを含めることを忘れないでください。先ほどの例でAWS Step Functionsを使用しましたが、Step Functionsはオーケストレーションに使用できると言いましたね。これがどのように役立つか見てみましょう。作業完了のイベントがEventBridgeに送られ、顧客の支払いワークフローを開始するルールが設定されています。

Thumbnail 2270

Thumbnail 2340

まず、データベースから作業自体の詳細を取得します。Lambdaを使用して請求書を生成し、車の引き取り準備ができたことを顧客にメールで通知し、その後待機状態に入ります。ここがStep Functionsの強力な点で、最大1年間待機することができます。また、標準ワークフローでは遷移に対して課金されますが、待機状態の間は料金が発生しません。支払いが完了すると、ワークフローは継続し、データベースを更新し、全員が5段階評価で5を付けるアンケートを送信できます。Step Functionsを使用してオーケストレーションを複数のセクションに分割し、それらを組み合わせることができます。また、サービスと直接統合しているため、ほぼすべてのAWSサービスに対して直接SDKコールを行うことができます。Lambda関数とカスタムコードの管理を避けるために、tenant IDがイベントからEventBridge経由でStep Functionsに入力として渡されることを覚えておいてください。このIDはワークフロー全体で使用できます。

Serverless SaaSへの移行戦略とチャレンジ

Thumbnail 2360

Thumbnail 2370

Thumbnail 2380

Thumbnail 2390

Thumbnail 2400

別の例を見てみましょう。先ほどの整備士による車の診断ビデオについて考えてみます。こちらがワークフローの例です。 Amazon Transcribeを使用してビデオの音声からコメントを取得してテキストに変換し、そのテキストをS3バケットに保存します。 そしてAmazon Bedrockに送信して、Large Language Modelを使用してコメントを要約します。その後、Lambdaを使用してデータベースから修理見積もりを取得し、お客様にビデオのリンク、ビデオ全体を見たくない場合のためのテキスト要約、そして修理の見積もりをメールで送信します。

次にアップデートについて見ていきましょう。デプロイメント時にすべてのテナントに影響を与えることを避けたいと言いましたね。今回はプール型モデルを採用しています。

Thumbnail 2410

Thumbnail 2420

では、このStackをバージョン1からバージョン2にどのように移行すればよいでしょうか?この例ではAmazon SQSを追加していることに注目してください。

Thumbnail 2430

Thumbnail 2440

Thumbnail 2450

Infrastructure as Codeを使用していることを期待しています。CloudFormation、Terraform、AWS SAM、CDKなどですね。Gitリポジトリなどを使用したバージョン管理を導入し、デプロイメントの自動化も行っています。CI/CDパイプラインを使用して、アプリケーションとインフラストラクチャのコードをより密接に連携させています。この成果物を複数のステージを通して、本番環境へ向かう過程で複数のアカウントにアーキテクチャをデプロイしていきます。テストは潜在的な問題の除去に役立ちますが、私たちが知っているように、本番環境に勝るものはありません。

Thumbnail 2480

Thumbnail 2510

これをどのように解決すればよいでしょうか?リスクを軽減する一つの方法は、リージョンごとのデプロイメントを行うことです。このソフトウェアを世界中にデプロイする場合、おそらく複数のリージョンにデプロイすることになるでしょう。これはデータレジデンシーの要件を満たすため、あるいはエンドユーザーの待ち時間を短縮するためかもしれません。小規模なリージョンから始めて、ソフトウェアの使用率が低いサンライズモデルに従うことで、本番環境へのロールアウトのリスクを軽減できます。また、インフラストラクチャの複数のコピーを持つセルラーアーキテクチャを使用することもできます。

これは、各テナントがインフラストラクチャのコピーを持つサイロ型モデルほど複雑ではありません。数十や数百ではなく、2つか3つ、あるいは4つのStackを持つだけかもしれません。しかし、これもリスクを軽減します。なぜなら、テナントの50%にデプロイし、それが問題ないことを確認してから残りのデプロイを行うことができるからです。次のステップに進む前に、適切な自動化と指標を用いて監視し、成功を確実にすることが重要です。

Thumbnail 2550

Thumbnail 2570

Thumbnail 2580

SaaSへの顧客移行について見ていきましょう。 従来型のマネージドホスティングの顧客がいる旧世界と、ServerlessなSaaSという新世界があります。では、どのように顧客を新しいアーキテクチャに移行させればよいのでしょうか?両方を並行して管理することは避けたいところです。それでは状況がさらに悪化してしまいますから。完全な機能パリティを実現し、 新世界を旧世界と全く同じようにしてから顧客を移行するという方法もあります。ただし、これは非常に達成が困難です。

Thumbnail 2600

Thumbnail 2610

インセンティブや割引を提供するという方法もあります。新世界には顧客を引きつける新機能があることが望ましいですね。また、コストを最適化することで企業としての効率を上げ、その節約分を顧客に還元することもできます。無料トライアル期間を提供するのも効果的です。ご存知の通り、顧客がソリューションを実際に使ってみると、 採用してもらえる可能性が高まります。同様に、教育とトレーニングも重要です。理解が深まれば深まるほど、 使ってもらえる可能性が高くなります。

Thumbnail 2630

データ移行のサポートは非常に重要です。新世界への移行が顧客にとって困難であれば、おそらく移行してもらえないでしょう。ワンクリックで全ての設定やデータが移行できるような仕組みを提供し、顧客の負担を軽減しましょう。 最後に、レガシーソフトウェアのサポート終了日を設定して、強制的に顧客を移行させるという方法もあります。

Serverless SaaSの利点と今後の展望

Thumbnail 2640

Thumbnail 2650

Thumbnail 2660

これまでの内容をまとめてみましょう。 確かに多くの内容を扱ってきました。以前のAnyCompanyには、テナントが整理されておらず、リソースがテナントの消費に合わせて配置されていないという課題がありました。 現在はServerlessを使用しているため、システムへのリクエストに応じて自動的にスケールします。 以前は新機能の提供に時間がかかっていましたが、Serverlessによって市場投入までの時間が短縮されました。サーバーのことを考える必要がなく、ビジネスロジックの作成に専念でき、Amazon EventBridgeなどで拡張可能なアーキテクチャを実現しています。

Thumbnail 2680

Thumbnail 2690

Thumbnail 2700

新規テナントのオンボーディングに時間がかかっていましたが、現在はリソースのプロビジョニング時間がゼロです。 テナント全体で同じリソースセットを共有しているため、テナントのサイジングを行う必要もありません。時間のかかるアップデートとメンテナンス作業は、 Serverlessを使用することでAWSに任せることができ、データサイロは共有データベースと簡素化されたパイプラインに置き換えられました。 Serverlessが非常に適していることを覚えておいてください。

Thumbnail 2710

では、今日お伝えしたい重要なポイントをまとめましょう。Serverlessは、SaaSにとって非常に適していることを覚えておいてください。なぜなら、テナントの消費パターンが、Serverlessサービスの設計思想や、自動的なスケールアップ・ダウンの特性と非常によく合うからです。テナントが私たちの予想とは異なる方法でソフトウェアを使用する可能性がありますが、Serverlessならその負荷に応じて自動的に対応してくれます。実際に使用した分だけを支払えばよいのです。

Thumbnail 2730

Thumbnail 2750

テナントのコンテキストは、マルチテナンシーの基本となります。認証からデータ、さらには統合方法に至るまで、システム全体を通してテナントが誰であるかを把握し続ける必要があります。これらのサービス統合パターンは、市場投入までの時間を短縮できる、スケーラブルなソリューションの構築に役立ちます。今日学んだことを、皆さんそれぞれのビジネスや状況に当てはめて、お客様を喜ばせるような素晴らしいものを作っていただければと思います。

Thumbnail 2760

これらの内容を実際に試してみたい方のために、GitHubでリファレンスアーキテクチャを公開しています。これらのコンセプトの構築方法を学べるハンズオン・ワークショップも用意されています。また、今日はお話しできなかったメトリクスの管理方法などの追加コンテンツも含まれています。本日は私の講演にお時間を割いていただき、ありがとうございました。質問がある方は、この後しばらく会場後方におりますので、お気軽にお声がけください。最後に、フィードバックアンケートへのご協力をお願いします。皆さんも同じことを言っているとは思いますが、アンケートは本当に重要です。それでは、残りの一週間もお楽しみください。ありがとうございました。


※ こちらの記事は Amazon Bedrock を利用することで全て自動で作成しています。
※ 生成AI記事によるインターネット汚染の懸念を踏まえ、本記事ではセッション動画を情報量をほぼ変化させずに文字と画像に変換することで、できるだけオリジナルコンテンツそのものの価値を維持しつつ、多言語でのAccessibilityやGooglabilityを高められればと考えています。

Discussion