AWS

【初心者向け】AWS SAMを使ってAPI GatewayとLambdaのデプロイとローカルで検証してみた

AWS
この記事は約9分で読めます。

はじめに

インプルの矢島です。

AWS DVAの勉強でSAMを使ってデプロイとローカルでの検証をした内容をまとめます。

こちらは、超初心者向けです。また、このような内容はすでに素晴らしい記事は多いかと思いますが、勉強の一貫でまとめたので、最後まで読んでいただけますと嬉しいです。

AWS SAMとは

正式名称はServerless Application Modelといいます。サーバーレス構築をするためのオープンソースのフレームワークのようです。

Dockerをマシンにインストールしているのであれば、ローカルでの検証も可能になります。

SAMはCloudFormationの拡張機能です。そのため、デプロイするとCloudFormationを使用してリソースを定義できるほか、組み込み関数やテンプレート機能といったものを一式使えます。

詳細はこちらをお読みください。(公式 AWS SAMについて

やること

  • SAMを使ってテンプレートを作成してAPI GatewayとLambdaをデプロイする
  • SAMを使ってローカル環境で検証する

つかってみる

AWS SAM CLIのインストール

下記公式の記事を参考にインストールして、セットアップします。

ERROR: The request could not be satisfied

バージョンが表示されればOKです。

$ sam --version
> SAM CLI, version 1.70.0

SAMをデプロイする時のために、AWSのコンソールからアクセスキーを作成しておきます。

今回はユーザーにアタッチするポリシーは最強にしておきます。(練習のためです。本番ではこのような運用はおすすめしません)

SAMでテンプレートを作成

sam initコマンドを実行すると、簡単なサーバーレス環境を構築するテンプレートを構築してくれます。

sam init --runtime nodejs16.x

コマンドを打つと、色々質問されます。今回は以下のように質問に回答します。

以下のようなファイル構成が完成しました!

作成されたtemplate.yamlを確認していきます。

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
  lambda_test

  Sample SAM Template for lambda_test
  
# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst
Globals:
  Function:
    Timeout: 3
    MemorySize: 128

Resources:
  HelloWorldFunction:
    Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
    Properties:
      CodeUri: hello-world/
      Handler: app.lambdaHandler
      Runtime: nodejs16.x
      Architectures:
        - x86_64
      Tracing: Active
      Environment:
        Variables:
          POWERTOOLS_SERVICE_NAME: helloWorld
          POWERTOOLS_METRICS_NAMESPACE: lambda_test
          LOG_LEVEL: INFO
      Events:
        HelloWorld:
          Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api
          Properties:
            Path: /hello
            Method: get
    Metadata: # Manage esbuild properties
      BuildMethod: esbuild
      BuildProperties:
        Minify: true
        Target: "es2020"
        # Sourcemap: true # Enabling source maps will create the required NODE_OPTIONS environment variables on your lambda function during sam build
        EntryPoints: 
        - app.ts

Outputs:
  # ServerlessRestApi is an implicit API created out of Events key under Serverless::Function
  # Find out more about other implicit resources you can reference within SAM
  # https://github.com/awslabs/serverless-application-model/blob/master/docs/internals/generated_resources.rst#api
  HelloWorldApi:
    Description: "API Gateway endpoint URL for Prod stage for Hello World function"
    Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello/"
  HelloWorldFunction:
    Description: "Hello World Lambda Function ARN"
    Value: !GetAtt HelloWorldFunction.Arn
  HelloWorldFunctionIamRole:
    Description: "Implicit IAM Role created for Hello World function"
    Value: !GetAtt HelloWorldFunctionRole.Arn

Transformというセクションは、SAMテンプレートの変換方法を指定するための指示です。この場合は、AWS::Serverless-2016-10-31を使用しています。

Globalsというセクションは、すべての関数リソースに適用される共通設定を指定するための指示です。この場合は、関数のタイムアウトとメモリサイズを指定しています。

Resourcesというセクションは、AWSリソースの定義を指定するための指示です。ここでは、HelloWorldFunctionという名前のAWS Lambda関数を定義しています。この関数は、Node.jsランタイムを使用し、hello-world/ディレクトリにあるapp.lambdaHandlerをハンドラー関数として指定されています。また、API GatewayでHTTP GETリクエストを処理するためのHelloWorldイベントも設定されています。

Metadataというセクションは、Lambda関数のビルド方法を指定するための指示です。この場合は、esbuildというツールを使用する設定になっており、TypeScriptファイルをJavaScriptに変換して最適化するように設定されています。

Outputsというセクションは、スタックを作成する際に自動的に作成されるリソースの情報を出力するための指示です。ここでは、API GatewayのエンドポイントURLやLambda関数のARN、IAMロールのARNなどが指定されています。

ビルド

sam buildコマンドを実行して、依存関係を解決していきます。

sam build

buildの結果、.aws-samディレクトリが構築されました。

デプロイ

aws環境にデプロイしていきます。

–guildオプションをつけることで対話的にデプロイすることができます。
今回は以下のように質問に回答していきます。

デプロイに成功しました!

AWSマネジメントコンソールからもCloudFormationにスタックが構成されていることが確認できます。

aws-sam-cli-managed-defaultというスタックもできていますが、sam deployの過程で作成され、ソースを保存するS3バケットとバケットポリシーが生成されます。

curlでapiを叩いてみると、ちゃんとレスポンスが返ってきていることを確認できました!

ローカルで検証してみる

2種類の方法があります。

  • Lambda関数を直接実行する
  • ローカルHTTPサーバーを構築して実行する

Lambda関数を直接実行する

以下コマンドを打つことで実行することができます。

sam local invoke

無事想定通りのレスポンスが返ってきていることを確認できました!

また、以下のようにFUNCTION_IDENTIFIERをつけてLambda関数を指定して、実行することもできます!

sam local invoke HelloWorldFunction

ローカルHTTPサーバーを構築して実行する

以下のコマンドを実行すると、ローカルのHTTPサーバーを構築できます。アクセスされると、Dockerコンテナをローカルで起動して関数を呼び出します。

sam local start-api

curlで叩くと、ちゃんとレスポンスが返ってきます。

オプションをついけることによって、ローカルホスト名や、ポート番号を変えること、Lambda環境関数の設定ファイルの読み込みなどもできるようになります。

sam local start-api --host '192.168.11.5' -p 9000

このように想定通りのレスポンスが返ってきました。

参考

AWS Serverless Application Model (AWS SAM) とは - AWS Serverless Application Model
AWS Serverless Application Model (AWS SAM) を使用してサーバーレスアプリケーションを構築する方法について説明します。
sam build - AWS Serverless Application Model
AWS SAM CLI からの sam build コマンドを使用して AWS SAM アプリケーションを構築します。
Running AWS SAM projects locally get error
I am trying to run an AWS Lambda project locally on Ubuntu. When I run the project with AWS SAM Local it shows me this error: Error: Running AWS SAM projects l...