2️⃣

【CFn/API Gateway/DynamoDB/Lambda】API呼び出しでDynamoDBを操作する<デプロイ編>

2024/10/30に公開

1.はじめに

今回は実装編で作成したLambda関数をAWS環境にデプロイします。
加えて、各リソースをテンプレート化して、CloudFormationでまとめてデプロ
します。
紹介する内容としては以下の通りとなります。

  • template.yamlでLambda関数・DynamoDB・API Gateway・APIキーを定義する
  • CloudFormationからリソースを一括デプロイする
  • PowerShellからAPIを呼び出しDynamoDBに項目を登録する


この記事は実装編・デプロイ編・フロント編の3部構成となっています。

今回はデプロイ編ということでtemplate.yamlの記述方法やデプロイ時の動作確認方法の説明をします。

本記事で実装するものは以下リポジトリに上げています。
https://github.com/is0383kk/Python-Lambda-Sample

2.準備

本記事では以下を前提とします。

■ ディレクトリ構成

本記事では以下のディレクトリ構成で進めます。

親ディレクトリ
┣ samconfig.toml ← デプロイ編で作成
┣ template.yaml ← デプロイ編で作成
┣ common_layer
┃ ┗ requirements.txt ← 実装編で作成
┗ dynamo_lambda_function
 ┗ app.py ← 実装編で作成
 ┗ lambda_function.py ← 実装編で作成

3.template.yamlの作成

今回は「template.yaml」を元にCloudFormationから各リソースを作成します。
作成するリソースとしては以下の通りです。

作成するリソース 説明
S3バケット ファイル格納先となるS3バケットです
Lambda関数 S3へのファイル格納をトリガーとして実行する関数
S3に格納されたファイル内容を取得します

作成する「template.yaml」全体としては以下の通りです。

template.yamlの全体
template.yaml
AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Description: DynamoDB Lambda Application

# AWS SAM テンプレートを使ってサーバーレスアプリケーションをデプロイするための基本設定
Globals:
  Function:
    Timeout: 5               # デフォルトのタイムアウト(5秒)
    MemorySize: 128           # Lambda 関数のメモリサイズ(128MB)
    Runtime: python3.11       # 使用する Python ランタイムバージョン (Python 3.11)
    Architectures:
      - arm64                 # Lambda 関数を ARM64 アーキテクチャで実行
    LoggingConfig:
      LogFormat: JSON         # ログフォーマットを JSON に設定
      ApplicationLogLevel: INFO # ログレベルを INFO に設定
    Environment:
      Variables:
        POWERTOOLS_SERVICE_NAME: DynamoApplication   # AWS Lambda Powertools で使うサービス名
        AWS_REGION_NAME: ap-northeast-1              # デフォルトの AWS リージョン名

# パラメータセクション:テンプレートに対して外部から渡される引数
Parameters:
  OverridesParam:
    Type: String              # パラメータの型 (String)
    Description: OverridesParam # パラメータの説明
  Stage:
    Type: String              # ステージ名のパラメータ(例:dev, prod)
    Default: dev              # デフォルト値として dev を設定
    Description: Stage Name   # ステージ名の説明

# リソースセクション:サーバーレスアプリケーションに必要な AWS リソースを定義
Resources:
  # API Gateway を定義
  Api:
    Type: AWS::Serverless::Api
    Properties:
      Name: !Sub ApiGateway-${OverridesParam} # API Gateway 名を OverridesParam でカスタマイズ
      StageName: !Ref Stage                   # ステージ名を指定
      EndpointConfiguration:
        Type: REGIONAL                       # エンドポイントをリージョン限定に設定

  # 共通の Lambda Layer を定義
  CommonLayer:
    Type: AWS::Serverless::LayerVersion
    Properties:
      LayerName: CommonLayer                # レイヤーの名前を定義
      Description: Common Layer             # レイヤーの説明
      ContentUri: common_layer/             # レイヤーのソースコードパス
      CompatibleRuntimes:
        - python3.11                       # レイヤーが対応するランタイム
      RetentionPolicy: Delete              # 不要になったレイヤーは削除するポリシー
    Metadata:
      BuildMethod: python3.11              # SAM がレイヤーをビルドするためのランタイム
      BuildArchitecture: arm64             # ARM64 アーキテクチャ用にビルド

  # DynamoDB と連携する Lambda 関数
  DynamoLambdaFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: app.lambda_handler          # Lambda 関数のハンドラ
      CodeUri: src/dynamo_lambda_function  # 関数コードの場所
      Description: DynamoDB lambda handler # 関数の説明
      Layers:
        - !Ref CommonLayer                 # CommonLayer を Lambda 関数に追加
      Events:
        ApiEvent:
          Type: Api
          Properties:
            RestApiId: !Ref Api            # API Gateway を参照
            Path: /{proxy+}                # プロキシ統合(すべてのパスを処理)
            Method: Any                    # HTTP メソッド(GET, POST など全て)
            Auth:
              ApiKeyRequired: true         # API キーが必要
      Environment:
        Variables:
          DYNAMO_TABLE_NAME: !Ref DynamoDBLambdaTable # DynamoDB テーブル名を環境変数で設定
      Policies:
        - DynamoDBCrudPolicy:              # DynamoDB に対する CRUD 権限
            TableName: !Ref DynamoDBLambdaTable
      Tags:
        Name: "dynamo-lambda-function"     # タグとして関数の名前を設定
      Timeout: 300                         # タイムアウト(300秒)

  # DynamoDB テーブルを定義
  DynamoDBLambdaTable:
    Type: AWS::DynamoDB::Table
    Properties:
      TableName: !Sub "dynamo-${OverridesParam}" # DynamoDB テーブル名をパラメータに基づき設定
      AttributeDefinitions:
        - AttributeName: dynamo_id           # パーティションキーとして使用する属性名
          AttributeType: S                   # 属性タイプ(S:文字列)
      KeySchema:
        - AttributeName: dynamo_id           # パーティションキー(HASHキー)
          KeyType: HASH
      BillingMode: PAY_PER_REQUEST           # リクエストごとの課金モデル(オンデマンド)

  # API キーを定義
  ApiKey:
    Type: AWS::ApiGateway::ApiKey
    Properties:
      Name: !Sub ApiKey-${OverridesParam}  # API キー名
      Description: APIKey                 # API キーの説明
      Enabled: true                       # API キーを有効化
      StageKeys:
        - RestApiId: !Ref Api             # API Gateway ID
          StageName: !Ref Stage           # ステージ名
    DependsOn:
      - Api
      - ApiStage

  # API の利用制限設定
  ApiUsagePlan:
    Type: AWS::ApiGateway::UsagePlan
    Properties:
      ApiStages:
        - ApiId: !Ref Api                 # API ID
          Stage: !Ref Stage               # ステージ名
      Throttle:
        BurstLimit: 100                   # バースト制限(リクエストの瞬間最大数)
        RateLimit: 100                    # レート制限(リクエストの毎秒最大数)
      UsagePlanName: !Sub UsagePlan-${OverridesParam} # 使用プランの名前
    DependsOn:
      - Api
      - ApiStage

  # ApiKey と ApiUsagePlan の紐づけ設定
  ApiUsagePlanKey:
    Type: AWS::ApiGateway::UsagePlanKey
    Properties:
      KeyId: !Ref ApiKey                  # API キーの ID
      KeyType: API_KEY                    # キータイプ(API キー)
      UsagePlanId: !Ref ApiUsagePlan       # 使用プランの ID

4.samconfig.tomlの作成

続いて「samconfig.toml」を作成します。
「samconfig.toml」はAWS SAM (Serverless Application Model) を使用する際に、SAM CLI コマンドの設定を管理するためのファイルです。
このファイルにより、デプロイ・ビルド時のオプションや設定を明示的に指定することができます。

主な用途としては以下が挙げられます。

  • デプロイ設定の自動化:「samconfig.toml」にデプロイ設定を保存しておくことで、簡単に同じ設定を使ってデプロイを行えます。
  • 環境ごとの設定:開発環境・本番環境など、異なる環境に応じた設定を分けて管理できます。

作成する「samconfig.toml」全体としては以下の通りです。

samconfig.tomlの全体
samconfig.toml
# More information about the configuration file can be found here:
# https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-config.html
version = 0.1

[default]
[default.global.parameters]
stack_name = "dynamo-application"

[default.build.parameters]
cached = true
parallel = true

[default.validate.parameters]
lint = true

[default.deploy.parameters]
capabilities = "CAPABILITY_IAM"
confirm_changeset = true
resolve_s3 = true
parameter_overrides = ["OverridesParam='20241030'"]

[default.package.parameters]
resolve_s3 = true

[default.sync.parameters]
watch = true

[default.local_start_api.parameters]
warm_containers = "EAGER"

[default.local_start_lambda.parameters]
warm_containers = "EAGER"

5.ビルド&デプロイ

それでは、実装物のビルドとデプロイを行います。
※AWS SAM CLIが使用できることを前提としています

以下のコマンドを実行することでビルドとAWS環境へのデプロイができます。

$ sam build
$ sam deploy --config-file samconfig.toml

Successfully created/updated stack - dynamo-application in ap-northeast-1
上記が表示されデプロイが正常終了したことを確認します。


続いてAWSのマネジメントコンソールから以下画面に移動します。

  • CloudFormation → スタック → dynamo-application

ステータスが「CREATE_COMPLETE」となっていることを確認します。

また、デプロイした各リソースが作成されていることを確認します。

Lambda関数

Lambda → 関数 → dynamo-application-DynamoLambdaFunction-XXX

DynamoDB

DynamoDB → テーブル → dynamo-20241029

API Gateway

API Gateway → API → ApiGateway-20241029

6.動作確認

それではLambda関数の動作確認を行います。
今回は以下手順で動作確認を行います。

  • API Gatewayの画面からAPIを呼び出す際のURLを確認する
  • API Gatewayの画面からAPIキーを確認する
  • PowerShellからAPIを呼び出す
  • DynamoDBに項目が登録されていることを確認する

手順1:API Gatewayの画面からAPIを呼び出す際のURLを確認する

APIを呼び出す際のURLを確認します。
マネジメントコンソールの以下画面から、APIを呼び出す際のURLをメモしておきます。

  • API Gateway → API → ApiGateway-20241029 → ステージ

手順2:API Gatewayの画面からAPIキーを確認する

API呼び出しに必要なAPIキーを確認します。
マネジメントコンソールの以下画面から、APIキーを確認しメモしておきます。

  • API Gateway → API → API キー

手順3:PowerShellからAPIを呼び出す

PowerShellからAPIを呼び出します。
実装編で作成したlambda_functionが以下の形で実装されているため、

以下コマンドで呼び出すことができます。

Invoke-WebRequest -Uri "https://手順1でメモしたURL/data/00001" -Method Post -Headers @{"Content-Type"="application/json";"x-api-key"="手順2でメモしたAPIキー"} -Body '{"name": "登録したい名称"}'

実行時のログは以下の通りです。

$ Invoke-WebRequest -Uri "https://手順1でメモしたURL/data/00001" -Method Post -Headers @{"Content-Type"="application/json";"x-api-key"="手順2でメモしたAPIキー"} -Body '{"name": "登録したい名称"}'
                                                                                                                                                                                                                                                                                                                                                                                                                  StatusCode        : 200                                                                                                                                                                                  
StatusDescription : OK                                                                                                                                                                                   
Content           : {"ResponseMetadata": {"RequestId": "ダミー", "HTTPStatusCode": 200, "HTTPHeaders": {"server": "Server", "date": "Tue, 29 Oct 2024 15:3
                    1:01 GMT", "content-...
RawContent        : HTTP/1.1 200 OK
                    Connection: keep-alive
                    x-amzn-RequestId: ダミー
                    x-amz-apigw-id: ダミー
                    X-Amzn-Trace-Id: ダミー
Forms             : {}
Headers           : {[Connection, keep-alive], [x-amzn-RequestId, ダミー], [x-amz-apigw-id, ダミー], [X-Amzn-Trace-Id, Root=ダミー;
                    Parent=ダミー;Lineage=ダミー]...}
Images            : {}
InputFields       : {}
Links             : {}
ParsedHtml        : System.__ComObject
RawContentLength  : 414

手順4:DynamoDBに項目が登録されていることを確認する

最後にDynamoDBに項目が登録されているか確認します。
マネジメントコンソールの以下画面から項目が登録されているか確認します。

  • DynamoDB → 項目を探索 → dynamo-20241029

7.おわりに

今回のデプロイ編では、実装編の成果物をAWS環境にデプロイし以下を確認しました。

  • API GatewayにAPIキーを設定
  • PowerShellからAPIを呼び出す
  • API呼び出しによるDynamoDBへの項目登録

実装編とデプロイ編を合わせた内容になりますので実装編も目を通していただけると嬉しいです。
https://zenn.dev/is0383kk/articles/63679129e8dd96

Discussion