Lock in $30 Savings on PRO—Offer Ends Soon! ⏳

AWS Lambda Web Adapterを活用する新しいサーバーレスの実装パターン

AWS Lambda Web Adapterを活用する新しいサーバーレスの実装パターン

AWS Lambda Web Adapter (LWA)は、AWS Lambda上で従来のウェブアプリフレームワークをそのまま動かすためのLambda Extensionです。このセッションでは、LWAの機能を取り上げ、それらが必要となる背景や従来実用が困難だった実装パターンをどのように実現できるのかを解説します。「LWAは便利だ」「Lambdalithも選択肢の一つかも」と感じていただければ幸いです。

ServerlessDays Tokyo 2024で発表した資料です。

Masashi Tomooka

September 21, 2024
Tweet

More Decks by Masashi Tomooka

Other Decks in Programming

Transcript

  1. © 2024, Amazon Web Services, Inc. or its affiliates. All

    rights reserved. Amazon Web Services Japan G.K. Sr. Prototyping Engineer AWS Lambda Web Adapterを活⽤する 新しいサーバーレスの実装パターン S E R V E R L E S S D A Y S T O K Y O 2 0 2 4 Masashi Tomooka
  2. © 2024, Amazon Web Services, Inc. or its affiliates. All

    rights reserved. 本⽇の内容 話すこと • Lambda Web Adapterの知られざる機能とそれらを活⽤するパターンの紹介 話さないこと • Lambda上でウェブフレームワークを使うことの是⾮ • 結局「場合による」ことなので、ぜひ本発表も参考に判断軸を得てください︕ 想定聴講者 • AWS Lambdaを使ったウェブアプリ開発をする⽅ 3
  3. © 2024, Amazon Web Services, Inc. or its affiliates. All

    rights reserved. 友岡 雅志 (Masashi Tomooka) Sr. Prototyping Engineer Amazon Web Services Japan G.K. プロトタイピング開発によるお客様⽀援 → プロトタイピングのススメ (AWS Summit Tokyo 2023) 好きなAWSサービス 4 ⾃⼰紹介 近影: 沖縄うるまにて 𝕏: @tmokmss ブログ: tmokmss.hatenablog.com AWS Lambda AWS Cloud Development Kit (CDK)
  4. © 2024, Amazon Web Services, Inc. or its affiliates. All

    rights reserved. • AWS Lambdaでのアプリ開発の特徴 § Lambda専⽤のインターフェース § 特にレスポンスストリーミングは… 🙄 5 モチベーション export const handler = awslambda.streamifyResponse( async (event, responseStream, context) => { responseStream.setContentType(“text/plain”); responseStream.write(“Hello, world!”); responseStream.end(); } ); export const handler = async (event, context) => { return { // API Gateway統合の場合 statusCode: '200’, body: 'success’, }; }; • 慣れた開発体験から遠ざかる • ローカル環境での実⾏に⼀⼯夫必要 など • ポータビリティの低下 • Lambda → ECS移⾏時に⼊出⼒の リファクタが必要になる など ⚠
  5. © 2024, Amazon Web Services, Inc. or its affiliates. All

    rights reserved. AWS Lamba Web Adapter (LWA) • Rust製のLambda拡張機能 (extension) オープンソースソフトウェア • ⾮Lambda⽤のウェブアプリをそのままAWS Lambda上で動かすためのツール • 動かせるアプリの例: Next.js, FastAPI, Spring Boot, nginx, etc… 6 GitHub awslabs/aws-lambda-web-adapter
  6. © 2024, Amazon Web Services, Inc. or its affiliates. All

    rights reserved. LWAの嬉しい点 • 導⼊の簡単さ: 最低限は既存のDockerfileに⼀⾏追加するだけ • ポータビリティ: コンテナイメージはLambda以外の環境でもそのまま利⽤できる • ECSでも、EKSでも、 ローカル環境でも可 (= ローカルでの動作確認が楽︕) • ⼩さなオーバーヘッド: ランタイムパフォーマンスへの影響は軽微 • とあるベンチマーク結果: https://aws.amazon.com/jp/builders-flash/202301/lambda-web-adapter/ 7 FROM node:20 # LWAのインストール (Lambda extension) 最低限はこの1⾏のみ必要 COPY --from=public.ecr.aws/awsguru/aws-lambda-adapter:0.8.4 /lambda-adapter /opt/extensions/lambda-adapter # 環境変数経由でLWAの設定を変更 ENV AWS_LWA_PORT 3000 ENV AWS_LWA_INVOKE_MODE response_stream # 以下省略... CMD [ "node", "server.js" ] ※ LWAは⾮コンテナ(zip)Lambdaでも同様に利⽤可能 (本セッションではContainer Lambdaにフォーカスする)
  7. © 2024, Amazon Web Services, Inc. or its affiliates. All

    rights reserved. LWAを活⽤するアーキテクチャ Lambda上のウェブアプリをLWA + 関数URL + CloudFrontで公開する 8 AWS Lambda@Edge Request signer (Origin request) Users Amazon CloudFront AWS Lambda Lambda Web Adapter 関数URL Webapp
  8. © 2024, Amazon Web Services, Inc. or its affiliates. All

    rights reserved. このアーキテクチャのポイント 9 AWS Lambda@Edge Request signer (Origin request) Users Amazon CloudFront AWS Lambda Lambda Web Adapter 関数URL Webapp 関数URLが レスポンスストリーミングを可能に ⽣成AIやSSRには⽋かせない要件 タイムアウトは最⻑15分に IAM認証で保護された関数URLに CloudFront OACで透過的なアクセス LWAがレスポンスストリームのI/Fを抽象化 アプリ側はLambdaを意識する必要なし IAM認証に必要な ペイロードのハッシュ 計算はLambda@Edgeで LWAによりNext.jsなど ⾮Lambda向けの フレームワークがそのまま動く
  9. © 2024, Amazon Web Services, Inc. or its affiliates. All

    rights reserved. 1. CloudFrontを経由する効果 • キャッシュによるLambdaへのリクエスト量抑制 • レスポンスの圧縮 • WAFやカスタムドメインの設定が可能に • 関数URLはIAM認証により、CloudFrontを通したアクセスのみ可能にする • OAC利⽤時でもリクエストボディのハッシュ値計算は必要のため、Lambda@Edgeを利⽤ [1] • クライアントからはIAM認証を気にせず 透過的にアクセス可能 • 実際の認証処理はウェブアプリ内部の 処理に任せる 10 [1] CloudFront + Lambda 関数 URL 構成でPOST/PUT リクエスト を⾏うため Lambda@Edge でコンテンツハッシュを計算する
  10. © 2024, Amazon Web Services, Inc. or its affiliates. All

    rights reserved. (補⾜) OACとSigV4と関数URL IAM認証 11 AWS Lambda@Edge Request signer (Origin request) Amazon CloudFront AWS Lambda Function URL (IAM Auth) Users POST /foo Body: {“key”: “value”, …} Headers: foo: bar 1. 元々のリクエスト POST /foo Body: {“key”: “value”, …} Headers: foo: bar x-amz-content-sha256: hash Authorization: SigV4_signature 3. OACがSigV4署名したリクエスト POST /foo Body: {“key”: “value”, …} Headers: foo: bar x-amz-content-sha256: Hex(SHA256(Body)) 2. Lambda@EdgeがBodyのハッシュを付けたリクエスト 4. Sigv4で認証︕ 詳細はドキュメントを参照 https://docs.aws.amazon.com/AmazonS3/ latest/API/sig-v4-header-based-auth.html
  11. © 2024, Amazon Web Services, Inc. or its affiliates. All

    rights reserved. 備考: AuthorizationヘッダーをSigV4と共存させる 問題 • 関数URLのIAM認証モードでは、SigV4のためAuthorizationヘッダーを利⽤する * • → ウェブアプリ側でもAuthorizationヘッダーを使うには不都合 (SigV4に上書きされるため) LWA + Lambda@Edgeで解決する⽅法 (環境変数 LWA_AUTHORIZATION_SOURCE を利⽤) 1. Lambda@Edgeで元のAuthorization ヘッダーを別名に置換 (例: Authorization2) 2. OAC はAuthorizationヘッダーに SigV4署名を付与 3. 関数URLはAuthorizationの値からSigV4認証 4. LWAがヘッダー名を置換 (例: Authorization2→Authorization) 5. ウェブアプリは透過的に、元々の Authorizationヘッダーを参照できる 12 *) クエリストリングを使う⽅法もある (OACではAuthorizationヘッダーのみ) AWS Signature Version 4 – Authentication methods 4. LWAがヘッダー名を変更し直す 例: Authorization2 → Authorization 0. Authorization header 付きのリクエスト 1. L@Eがヘッダー名を変更 例: Authorization → Authorization2 2. OACがAuthorization ヘッダーにSigv4署名を追加 3. 関数URLのIAM認証 5. Webappは元々の Authorizationヘッダー を参照できる
  12. © 2024, Amazon Web Services, Inc. or its affiliates. All

    rights reserved. 2. レスポンスストリーミング • レスポンスをチャンクごとに順次返せる通信⽅法 • 最近は⽣成AIアプリやNext.js App Routerの台頭により重要に • LLMのトークン⽣成ごとにクライアントに順次返す • SSRでコンポーネント描画ごとに順次返す • 2023年にLambdaでも実現可能に (関数URLのみ対応) 13 出典: Next.js 13 の SSR Streaming を AWS Lambda Response Streaming で実装する⽅法 出典: GenU
  13. © 2024, Amazon Web Services, Inc. or its affiliates. All

    rights reserved. LWAとレスポンスストリーミング • LWAでは環境変数 AWS_LWA_INVOKE_MODE: response_stream で機能を有効化 • LWAを使うと嬉しい点: • ウェブアプリからはLambdaを意識する必要がない • ウェブフレームワークに準じたストリームのコードそのままでOK • Next.jsならRSC、他のフレームワークにもストリーム機能が (たいてい) ある 14 exports.handler = awslambda.streamifyResponse( async (event, responseStream, context) => { responseStream.setContentType(“text/plain”); responseStream.write(“Hello, world!”); responseStream.end(); } ); ← こういうコードを書かなくて良い 参考: AWS Lambda response streaming 実装前にしりたいやつ
  14. © 2024, Amazon Web Services, Inc. or its affiliates. All

    rights reserved. 3. その他、本アーキテクチャの嬉しい点 • リクエストは15分間まで持続可能 • ↔ Amazon API Gatewayの29秒タイムアウト (デフォルト値) • ⽣成AIアプリでは1回の⽣成が30秒を超えることもよくある • ローカルでの検証が⾮常に容易 • ↔ 単⼀責務Lambda • Lambdaランタイムへの依存はLWAが吸収するので、ウェブアプリ⾃体は ローカル環境でもそのまま動作する 15
  15. © 2024, Amazon Web Services, Inc. or its affiliates. All

    rights reserved. LWAを活⽤するアーキテクチャ (派⽣形) 16 AWS Lambda@Edge Request signer (Origin request) Users Amazon CloudFront AWS Lambda foo service AWS Lambda bar service Path: /foo Path: /bar CloudFrontによるルーティングを利⽤し Lambdaを適切な粒度で分割する Users Amazon CloudFront AWS Lambda POST/PUTを使わない場合、クライアント側でハッシュ 計算できる場合は、Lambda@Edgeは不要 AWS WAF AWS ACM Users Amazon CloudFront AWS Lambda WAFやカスタムドメインの設定も容易
  16. © 2024, Amazon Web Services, Inc. or its affiliates. All

    rights reserved. 本アーキテクチャの制約・限界 • 🚧 Lambda実⾏環境の制約 • /tmp以外はread only、リクエストサイズの上限 (Lambda@Edgeは1MB) など • 回避策: /tmpを使うよう⼯夫。ファイルアップロードはS3 pre-signed URLを利⽤ • 💸 Lambdaの分離モデルがコスト効率へ与える影響 • I/Oバウンドな処理 (例: レスポンスストリームの横流し) は、Lambdaの分離モデルでは コスト効率低下↓ (リクエスト間でCPUを共有できないため) • 回避策: I/Oバウンド処理のみ省メモリなLambdaに切り出し / ECSなどへの移⾏ • ⏱ Lambdaのコールドスタート時間 • 単⼀Lambdaにすべての処理を詰め込む (Lambdalith) ことで、初期化時にロードすべき ライブラリの量が増え、コールドスタートが⻑時間化する • 回避策: コールドスタート軽減措置の実装 / Lambdaの分割 17
  17. © 2024, Amazon Web Services, Inc. or its affiliates. All

    rights reserved. 代表的なコールドスタート対策 • モジュールのロードを遅延させる (以下はPythonの例) • Lambda関数を分割する • API routeによって使うライブラリが偏る場合に有効 18 参考: Python Lambdaのコールドスタートが遅いときの対処法 import foo def func(): foo.bar() # fooモジュールのインポートを遅延 def func(): import foo foo.bar() Route A Route B /A /B ライブラリX ロード時間3秒 ライブラリY ロード時間2秒 cold start 5秒 Route A Route B /A /B cold start 3秒 cold start 2秒 ※ XとYは完全に独⽴したものとする
  18. © 2024, Amazon Web Services, Inc. or its affiliates. All

    rights reserved. LWA_ASYNC_INIT: false (default) ⚠ 10秒⽬に初期化フェーズが中断され、 初期化フェーズが再実⾏される 初期化に10秒以上掛かる場合、必ず追加で 10秒必要になる LWA_ASYNC_INIT: true ✅ 10秒を超える初期化フェーズも⼀回で完了 LWAがライフサイクルを制御し、ウェブアプリの 初期化を待たずに初期化フェーズを完了させる LWA_ASYNC_INIT 10秒を超える初期化フェーズを効率化するための仕組み 19 引⽤元: Lambda実⾏環境のライフサイクル Init フェーズは 10 秒に制限されています。3 つのタスクすべてが 10 秒以内に完了しない場合、Lambda は最初の関数呼び出し時に、 設定された関数タイムアウトで Init フェーズを再試⾏します。 初期化 10秒 初期化 (retry) 呼び出し 10秒 初期化 呼び出し 20秒 ※ そもそもコールドスタート10秒超が許容できるのかという議論は必要
  19. © 2024, Amazon Web Services, Inc. or its affiliates. All

    rights reserved. 類似アーキテクチャとの⽐較 1. 本アーキテクチャ 2. API Gateway + Lambda 3. ELB + ECS ✅ Pros • Lambdaのマネージド性 • ローカルでの動作容易 • Scale to zero • レスポンスストリーム • タイムアウト15分 • Lambdaのマネージド性 • Scale to zero • API Gatewayに様々な機能 をオフロード • 実績が多く枯れている • I/Oバウンド処理における ⾼いコスト効率 • 制約の少ない実⾏環境 • レスポンスストリーム • ローカルでの動作容易 • タイムアウト制限なし ⚠ Cons • I/O boundのコスト効率 • Lambda実⾏環境の制約 • コールドスタート • 「閉域化」は不可 • I/O boundのコスト効率 • Lambda実⾏環境の制約 • コールドスタート • レスポンスストリーム 不可 (2024年9⽉現在) • タイムアウト29秒 (default) • オートスケールの管理必要 • スパイク耐性に課題 • Scale to zeroしない 20
  20. © 2024, Amazon Web Services, Inc. or its affiliates. All

    rights reserved. FAQ Q. 実装例を⾒せてください • CDKで実装したコード: https://github.com/tmokmss/dify-on-aws-cdk/tree/lwa_furl • こちらも参照: LLMアプリ開発プラットフォームDifyをAWSで可能な限りマ ネージド化したかった Q. このアーキテクチャ⾃体は、LWAなしでも使えますよね︖ • はい。Lambdaのレスポンスストリームにも対応しているウェブアプリフレー ムワークとして、HonoやOpenNextなどがあるようです。 • LWAはそれ以外のフレームワークもそのまま動かしうる点で魅⼒的 21
  21. © 2024, Amazon Web Services, Inc. or its affiliates. All

    rights reserved. まとめ • Lambda Web Adapterでウェブアプリ開発・運⽤を更に楽にできます • 特にLWA + 関数URL + CloudFrontの組み合わせは相性が良いです 22 AWS Lambda@Edge Request signer (Origin request) Users Amazon CloudFront AWS Lambda Lambda Web Adapter 関数URL Webapp
  22. © 2024, Amazon Web Services, Inc. or its affiliates. All

    rights reserved. 参考資料 • AWS Lambda の上でいろんなWEB フレームワークを動かそう︕ • Lambda Web Adapter でウェブアプリを (ほぼ) そのままサーバーレス化する • LWAの紹介・パフォーマンス調査など • Monolith First Serverless Development • Lambdalithパターンの紹介・Deep dive • AWS Lambda Performance Tuning Deep Dive • コールドスタート⾼速化などのパフォーマンスチューニング技法のまとめ 23
  23. © 2024, Amazon Web Services, Inc. or its affiliates. All

    rights reserved. Thank you! Masashi Tomooka [email protected] 𝕏 / GitHub: @tmokmss