Open4

AWSサーバレスパターンを理解する

mocknmockn

ゴール

  • AWS公式が出しているサーバレスパターンを理解し、サーバレスアプリケーションの設計・実装をできるようになる

背景

  • 今のプロジェクトでLambdaを中心としたサーバレスアプリの構築に携わることになり、サーバレスアプリケーション、サーバレスアーキテクチャについて人に説明できる位に理解するため

TODO

  • サーバレスアプリケーション・サーバレスアーキテクチャとは何かを調べる
  • 代表的なサーバレスアーキテクチャのパターンそれぞれのユースケースと実装方法を理解する
  • 各サーバレスパターンのチュートリアルを実施する

AWSサーバレスパターン

https://aws.amazon.com/jp/serverless/patterns/serverless-pattern/

1. 動的 Web / モバイルバックエンド

用途

  • バックエンドから取得したデータの表示やデータ更新を行うWebアプリケーション。
  • 認証認可や会員管理機能を持つ。
  • 動的Webと同様の機能を持つモバイル向けバックエンド。

主な技術スタック

  • Lambda、API Gateway、DynamoDB、Cognito、Amplify(特にモバイル向け)

2. リアルタイムモバイル / オフライン対応

用途

  • リアルタイムチャット
  • 自動更新フィード
  • Push通知
  • オフラインでのデータ読み込み・更新

主な技術スタック

  • AppSync、Lambda, DynamoDB、Kinesis Data Steams

3. 業務系 API / グループ企業間 API

用途

  • 企業の業務向けに利用されるAPI。
  • 企業内もしくは企業外に向けての利用が想定されている。

主な技術スタック

  • CloudFront、Cognito、AWS WAF、API Gateway、Lambda, DynamoDB

4. Push 配信系・インタラクティブ API

用途

  • WebSocketによる双方向通信。
  • チャットアプリケーション、コラボレーションプラットフォーム、マルチプレイヤーゲーム、金融取引プラットフォームなどのリアルタイムアプリケーションなど。

主な技術スタック

  • WebSocket API, API Gateway

5. 画像処理 / シンプルなデータ加工

用途

  • S3バケットにファイルが配置されたことをトリガーに加工処理を実行するバッチ。
  • 画像の圧縮やリサイズ、簡単な数値計算、文字変換など。

主な技術スタック

  • S3、Lambda

6. 分散並列処理

用途

  • S3バケットにファイルが配置されたことをトリガーに加工処理を実行するバッチ。
  • 画像の圧縮やリサイズ、簡単な数値計算、文字変換など。

主な技術スタック

  • S3、Lambda

7. イベント駆動の業務処理連携

用途

  • オンラインオークションでの入札システム
  • ECサイト(注文後から決済を経て発送やメール通知などをイベント通知として処理する)
  • コメント投稿サイト(アプリケーションで軽快な動作を実現したい場合)

主な技術スタック

  • SQS、SNS、EventBridge、AmazonMQ、Kinesis Data Stream、Amazon Managed Streaming for Apache Kafka

8. アプリケーションフロー処理

後ほど記載

9. 流入データの連続処理

後ほど記載

10. IoT バックエンド

後ほど記載

11. チャットボット / Alexa スキル

後ほど記載

12. データ変更トリガー処理

後ほど記載

13. ログデータ収集処理

後ほど記載

14. データレイク周りのデータ加工

後ほど記載

15. 機械学習/ETLデータパイプライン

後ほど記載

16. スケジュール・ジョブ / SaaS イベント

用途

  • 定期的に実行するバッチジョブ
  • Saas

主な技術スタック

  • EventBridge、CloudWatch

対象

現在のプロジェクトで実装が必要な以下パターンについて最優先で学習を行う。

    1. 動的 Web / モバイルバックエンド
    1. 業務系 API / グループ企業間 API
    1. イベント駆動の業務処理連携
    1. スケジュール・ジョブ / SaaS イベント
mocknmockn

1. 動的 Web / モバイルバックエンド & 3. 業務系 API / グループ企業間 API

概要

  • 会員制Webサイト。非会員が使用できるメニューもある。
  • 商品の購入ができ、商品の購入履歴やアカウント情報、決済情報を閲覧できる。
  • オンプレミスDBと外部決済APIと接続。

構成

  • CloudFront、AWS WAF - API Gateway、Lambda、Cognito、DynamoDB
  • ユーザーがサイトにアクセスすると、オンプレミスのWebサーバーからコンテンツを取得する。
  • 会員制サービスはAWS上に構築されており、CloudFrontからJavscriptを読み込み処理を実行する。
  • CloudFrontにはWAFが設定されている。
  • 会員情報はCognitoで管理しており、商品や購入履歴の情報はオンプレDBに格納している。
  • 会員メニューの処理を担うAPIへのリクエストはCognitoによる認証が必須となっており、会員のみが利用できるようになっている。

構築メモ

実際に構築した際に詰まったところなどのポイントを記載。

CloudFront - API Gateway - Lambdaの設定

CORS

  • 単純でない・資格情報を含むCORSリクエスト
  • API GatewayでCognito Authorizerによる認証を行っているため必要な設定の対応に躓いた。

対応

  • API Gateway
    • Lambdaプロキシ統合とCORS設定を行った。
    • 対象メソッドのレスポンスヘッダーとして以下を設定した。(CloudFront Functionsで上書きするが設定しないとエラーになるため)
    • Access-Control-Allow-Credentials: 'true' // 資格情報付(JWT)のリクエストのため必要
    • Access-Control-Allow-Headers: 'Content-Type, Authorization' // AuthorizationヘッダにJWTを設定しているため必要
    • Access-Control-Allow-Methods: 'OPTIONS'
    • Access-Control-Allow-Origin: 'https:/example.com' // 資格情報付リクエストの場合は"*"は設定できないため仮の値を一つ設定
  • CloudFront
    • キャッシュポリシー:Managed-CachingDisabled
      • 動的コンテンツのため。
    • オリジンリクエストポリシー、レスポンスヘッダーポリシー:なし
    • CloudFrontでCloudFront Functionsを実装し、レスポンスヘッダーを上書きするようにした。

詳細

https://zenn.dev/mockn/articles/b52350541696f5

CloudFront - AppRunnerの設定

CORS

  • 資格情報のないCORSリスクエスト。
    • IdTokenはAuthorizationヘッダーではなくリクエストボディのパラメータでAPIに送信し、API内で検証を行っている。

対応

  • CloudFront
    • キャッシュポリシー:Managed-CachingDisabled
      • 動的コンテンツのため。
    • オリジンリクエストポリシー:Managed-CORS-CustomOrigin
      • オリジンを転送
    • レスポンスヘッダーポリシー:カスタムポリシー
      • オリジンを指定のドメインで上書き。サブドメイン含む。

Cognito設定

  • ローカルユーザー(メールアドレス・パスワード)に加えて、ソーシャルIdpユーザーでのサインアップ・サインインにも対応した。

まとめ

今回、PublicなWebアプリケーションであったため、APIアクセスに認証機能が必要なることや、それによるCORSの対応方法について経験することができて良かった。

Cognitoの設定は複雑で設定項目が多いためできればCloudFormationなどでテンプレート化したい。
CloudFront-S3はテンプレート化していて、AppRunnerとAPIGateway-Lambdaはデプロイパイプラインを構築しているが、全体的なIaCやCI/CDパイプラインの構築はまだ対応できていないため今後の課題としたい。

参考

https://developer.mozilla.org/ja/docs/Web/HTTP/CORS
https://qiita.com/yana1316/items/34ee351adb6091ea7fc1
https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/how-to-cors.html#:~:text=があります。-,プロキシ統合の CORS サポートを有効にする,-Lambda プロキシ
https://github.com/aws-samples/amazon-cloudfront-functions/blob/main/add-cors-header/index.js
https://zenn.dev/syo_yamamoto/articles/445ce152f05b02

mocknmockn

7. イベント駆動の業務処理連携

概要

以下機能についてイベント駆動の処理を実装した。

  • 通知
    • エンドユーザー向け
      • ログイン関連
    • 運用チーム向け
      • ログイン関連
      • APIでのエラー
  • データ更新
    • バックアップ取得

構成

通知・データ更新(バックアップ取得)

  • データ更新
    • EventBridge Ruleを設定しイベント発生時にLambdaをトリガーしDynamoDBにデータ更新を行う。
  • 通知
    • エンドユーザー向け
      • EventBridge Ruleを設定しイベント発生時にLambdaをトリガーしSESを利用してメール送信。
    • 運用チーム向け
      • EventBridge Ruleを設定しイベント発生時にSNSトピックをトリガーしChatbotを利用してSlackの対象チャネルにメッセージ投稿。

構築メモ

実際に構築した際に詰まったところなどのポイントを記載。

Slack通知

  • Lambdaを使用する方法があったが、メッセージの高度なカスタマイズ不要だったため簡単に構築できるChatbotを利用する方法を採用した。
  • 構築の流れ
    • Cloud Watch ログメトリクスフィルターの作成 -> メトリクスフィルターをもとにCloudWatch Alarmを作成 -> SNSトピックへのイベント送信設定 -> チャットボットの設定(Slackチャネル連携、SNSトピック紐づけ)
  • 設定
    • メトリクスフィルターはAWSマネージドのものとカスタムのものを使用。
      • 基本的にはマネージドを使用するが、ログに出力された任意の文字列を条件にする場合はカスタムを使用。

Lambdaのトリガー作成

  • 構築の流れ
    • Cloud Watch ログメトリクスフィルターの作成 -> メトリクスフィルターをもとにCloudWatch Alarmを作成 -> SNSトピックへのイベント送信設定 -> チャットボットの設定(Slackチャネル連携、

Cognitoの認証イベントの通知とトリガー設定

  • Cognitoの認証イベントを利用して通知を行ったりLambdaをトリガーしてデータ更新を行う必要があった。
  • 通知
    • AWSマネージドではCloudWatchLogsには必要なメトリクスが用意されていないが、CloudTrailにイベントログが出力されるようになっている。既定ではCloudWatchLogsでそのイベントログを使用することができないため、CloudTrailで証跡を作成しログをCloudWatchLogsに転送する必要がある。
    • ログを転送した後は、カスタムのメトリクスフィルターを作成しCloudWatchAlarmを設定することで通知ができる。
  • Lambaのトリガー
    • CloudTrailで証跡を作成することで、EventBridgeからCloudTrail経由で直接イベントログを参照できるようになる。
    • EventBridgeで対象のイベントパターンをJson形式で設定しターゲットをLambdaにすることでトリガーできるようになる。
    • 記載するイベントパターンには対象イベントのJson構造を把握している必要があり、公式ドキュメントやCloudTrailのイベント履歴で確認する必要がある。

まとめ

はじめはCloudWatchとEventBridge、CloudTrailの違いや使い分けが理解できておらず混乱したが、通知やトリガー設定に関しては以下の使い分けと今は理解している。

  • ログのメトリクスの閾値に基づき通知を行いたい場合
    • CloudWatch
  • イベントの発生に基づいてAWSサービスをトリガーしたい場合
    • EventBridge
      • CloudWatchAlarm+SNSトピックを設定することでAWSサービスをトリガーすることも可能だが、EventBridgeの方が設定が少なくシンプルのため基本的にはEventBridgeを利用するのが良さそう。
  • AWSマネージドで存在しないイベントログをCloudWtchやEventBridgeで使用したい場合、証跡を作成する。

参考

https://docs.aws.amazon.com/ja_jp/cognito/latest/developerguide/logging-using-cloudtrail.html
https://docs.aws.amazon.com/ja_jp/awscloudtrail/latest/userguide/cloudtrail-aws-service-specific-topics.html
https://dev.classmethod.jp/articles/log-aws-api-call-via-cloudtrail-using-eventbridge/
https://aws.amazon.com/jp/builders-flash/202006/slack-chatbot/?awsf.filter-name=*all
https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/Create_alarm_log_group_metric_filter.html

mocknmockn

16. スケジュール・ジョブ / SaaS イベント企業

概要

  • マーケティング部門向けに、ユーザー情報を格納したテーブルからデータを抽出・加工しCSVを出力するバッチ。
  • データは個人が特定できない最低限の情報のみを残す。

構成

  • EventBridge、Lambda、DynamoDB、S3
  • EventBridgeで毎日業務開始前の時刻にLambdaをトリガー。
  • Lambda上でDynamoDBのデータを取得し加工したうえでS3にCSVを出力する。

構築メモ

定期実行設定

  • EventBridgeを利用したスケジュールトリガーの設定は2種類ある。(はじめは2種類あると把握しておらず混乱した。)
    • EventBridge Rule
      • 先発のサービス。スケジュール以外のトリガールール設定も基本的にこちらで行う。
    • EventBridge Scheduler
      • 後発のサービス。タイムゾーンやリトライ、DLQ、暗号化など柔軟な設定ができる。
  • タイムゾーンやリトライの設定ができるため、今回はEventBridge Schedulerを利用。
  • AWS SAMテンプレート上では"Type: ScheduleV2"と指定することで利用可能。
  • デフォルトのリトライ回数は185回。今回DyanamoDBに対してスキャンを行う処理があること、Slack通知があるため処理失敗時に何十、何百とリトライする必要はない(されると困る)ため、リトライ回数は数回に設定した。

詳細

https://zenn.dev/mockn/articles/029a736708b1c9

まとめ

EventBridgeを利用すると簡単に柔軟なスケジュールトリガーを設定することができることが分かった。
スケジュールトリガーの設定方法に2種類あることにはじめは戸惑ったが、設定の労力に特にさはなく、タイムゾーンやリトライなど便利な機能があるため、基本的にはEventBridge Schedulerを使うのが良いと考えている。
AWS SAMでLambdaを定義する際にEventBridge Schedulerの設定もシンプルにかけるのがとても良いと感じた。

参考

https://dev.classmethod.jp/articles/eventbridge-scheduler-and-event-bridge-rule-difference/
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-events-rule.html
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-scheduler-schedule.html
https://docs.aws.amazon.com/ja_jp/eventbridge/latest/userguide/eb-use-sam.html
https://docs.aws.amazon.com/ja_jp/serverless-application-model/latest/developerguide/sam-property-function-schedulev2.html
https://docs.aws.amazon.com/ja_jp/serverless-application-model/latest/developerguide/sam-property-function-eventbridgerule.html
https://docs.aws.amazon.com/ja_jp/eventbridge/latest/userguide/eb-cron-expressions.html
https://docs.aws.amazon.com/ja_jp/eventbridge/latest/userguide/eb-rules-best-practices.html
https://zenn.dev/robon/articles/81f4cf35b3a32c
https://qiita.com/baku2san/items/2514ce485731ff7068c5