1
0

More than 1 year has passed since last update.

AWS SAMでアプリケーションをローカルテスト&デプロイ

Posted at

はじめに

こちらの記事で作成した環境をテンプレート化したい!と思ったので、
AWS SAMを使ってみました。
SAMはリソースをプロビジョニングできるだけでなく、ローカルでLambda、API Gatewayをテストできる便利ツールだったのでその使い方も紹介します。
途中、cloudformationコマンドとの比較もしていますのでご参考までに。

環境

  • mac OS:Monterey 12.0.1
  • AWS CLI:2.2.33
  • SAM CLI:1.35.0

SAMとは

  • AWS Serverless Application Modelの略
  • サーバーレスアプリケーション構築用のオープンソースフレームワーク
  • YAML,JSON形式でテンプレート記述
  • CloudFormationの拡張機能で、簡単にテンプレートを記述することが可能
  • SAM CLIあり

SAM CLIのインストール

こちらからどうぞ

SAM利用の流れ

  1. SAMテンプレートの記述
  2. パッケージング
  3. デプロイ

1. SAMテンプレートの記述

テンプレート構造

実際のコード

template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: AWS SAM Serverless demo
Resources:
  TranslateLambda:
    Type: AWS::Serverless::Function
    Properties:
      FunctionName: translation-function
      CodeUri: translation-function/
      Handler: translation-function.lambda_handler
      Runtime: python3.8
      Timeout: 5
      MemorySize: 256
      Policies:
        - TranslateFullAccess
      Events:
        GetApi:
          Type: Api
          Properties:
            Path: /translate
            Method: get
            RestApiId:
              Ref: TranslateAPI
  TranslateAPI:
    Type: AWS::Serverless::Api
    Properties:
      Name: translate-api
      StageName: dev
      EndpointConfiguration: REGIONAL
  TranslateDynamoDbTbl:
    Type: AWS::Serverless::SimpleTable
    Properties:
      TableName: tranlate-history
      PrimaryKey:
        Name: timestamp
        Type: String
      ProvisionedThroughput:
        ReadCapacityUnits: 1
        WriteCapacityUnits: 1

1. リソースタイプの選択

AWS::Serverless::Function
AWS::Serverless::Api
AWS::Serverless::SimpleTable
など

2. リソースタイプごとに必要なプロパティを記述

AWS::Serverless::Functionであれば、
Handler,Runtimeが必須
CodeUri,InlineCodeのいずれか必須 など

2. パッケージング 

デプロイするためにzip化し、S3にアップロードする

  • s3パスをSAMテンプレートのCodeUriに記載する必要がある
  • パッケージングコマンドで、アプリケーションをzip化し、CodeUriを書き換えている

パッケージングには2つの方法がある

  • cloudformationコマンド
  • SAM CLI

cloudformationコマンド実行

※AWS CLIインストールかつログイン済みであることが前提

aws cloudformation package \
--template-file template.yaml \
--s3-bucket serverless-sam-demo \
--output-template-file packaged-template.yaml

コマンド実行後、下記ファイルが出力される

packaged-template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: AWS SAM Serverless demo
Resources:
  TranslateLambda:
    Type: AWS::Serverless::Function
    Properties:
      FunctionName: translation-function
      CodeUri: s3://serverless-sam-demo/*************
      Handler: translation-function.lambda_handler
      Runtime: python3.8
      Timeout: 5
      MemorySize: 256
      Policies:
      - TranslateFullAccess
      Events:
        GetApi:
          Type: Api
          Properties:
            Path: /translate
            Method: get
            RestApiId:
              Ref: TranslateAPI
  TranslateAPI:
    Type: AWS::Serverless::Api
    Properties:
      Name: translate-api
      StageName: dev
      EndpointConfiguration: REGIONAL
  TranslateDynamoDbTbl:
    Type: AWS::Serverless::SimpleTable
    Properties:
      TableName: translate-history
      PrimaryKey:
        Name: timestamp
        Type: String
      ProvisionedThroughput:
        ReadCapacityUnits: 1
        WriteCapacityUnits: 1

パッケージ前

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: AWS SAM Serverless demo
Resources:
  TranslateLambda:
    Type: AWS::Serverless::Function
    Properties:
      FunctionName: translation-function
      CodeUri: translation-function/
      Handler: translation-function.lambda_handler

パッケージ後

Resources:
  TranslateLambda:
    Type: AWS::Serverless::Function
    Properties:
      FunctionName: translation-function
      CodeUri: s3://serverless-sam-demo/*************
      Handler: translation-function.lambda_handler

先ほどのyamlファイルのcodeuriの表記が変わっていることが確認できます

さらにS3を見ると、確かにアップされている!
スクリーンショット 2021-11-28 18.56.02.png

SAM CLIでビルド

コマンドはたったこれだけ

sam build

実行結果

(base) ~~~~~@~~~~~~~~~ sam-serverless-demo % sam build
Building codeuri: /Users/***********/sam-serverless-demo/translate-function runtime: python3.8 metadata: {} architecture: x86_64 functions: ['TranslateLambda']
requirements.txt file not found. Continuing the build without dependencies.
Running PythonPipBuilder:CopySource
Skipping copy operation since source /Users/ohsugiryoya/sam-serverless-demo/translate-function does not exist

Build Succeeded

Built Artifacts  : .aws-sam/build
Built Template   : .aws-sam/build/template.yaml

Commands you can use next
=========================
[*] Invoke Function: sam local invoke
[*] Deploy: sam deploy --guided

.aws-sam/buildが作成され、配下に下記テンプレートファイルが作成される

template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: AWS SAM Serverless demo
Resources:
  TranslateLambda:
    Type: AWS::Serverless::Function
    Properties:
      FunctionName: translation-function
      CodeUri: TranslateLambda
      Handler: translation-function.lambda_handler
      Runtime: python3.8
      Timeout: 5
      MemorySize: 256
      Policies:
      - TranslateFullAccess
      Events:
        GetApi:
          Type: Api
          Properties:
            Path: /translate
            Method: get
            RestApiId:
              Ref: TranslateAPI
  TranslateAPI:
    Type: AWS::Serverless::Api
    Properties:
      Name: translate-api
      StageName: dev
      EndpointConfiguration: REGIONAL
  TranslateDynamoDbTbl:
    Type: AWS::Serverless::SimpleTable
    Properties:
      TableName: tranlate-history
      PrimaryKey:
        Name: timestamp
        Type: String
      ProvisionedThroughput:
        ReadCapacityUnits: 1
        WriteCapacityUnits: 1

先ほどと異なりCodeUriがS3リンクになっていないが、バケットとオブジェクトが作成されていました
スクリーンショット 2021-11-28 19.10.57.png

3. デプロイ

デプロイコマンドで、cloudformation本来のテンプレートに変換されリソースが作成される

cloudformationコマンド実行

aws cloudformation deploy \
--template-file ./packaged-template.yaml
--stack-name serverless-sam-demo
--capabilities CAPABILITY_IAM

SAM CLIでデプロイ

インタラクティブに実行することが可能

sam deploy --guided
(base)  sam-serverless-demo % sam deploy --guided

Configuring SAM deploy
======================

        Looking for config file [samconfig.toml] :  Found
        Reading default arguments  :  Success

        Setting default arguments for 'sam deploy'
        =========================================
        Stack Name [sam-app-demo]: 
        AWS Region [ap-northeast-1]: 
        #Shows you resources changes to be deployed and require a 'Y' to initiate deploy
        #変更点の確認
        Confirm changes before deploy [Y/n]: y
        #SAM needs permission to be able to create roles to connect to the resources in your template
        Allow SAM CLI IAM role creation [Y/n]: y
        #Preserves the state of previously provisioned resources when an operation fails
        Disable rollback [Y/n]: y
        #パブリックに公開する
        TranslateLambda may not have authorization defined, Is this okay? [y/N]: y
        Save arguments to configuration file [Y/n]: y
        SAM configuration file [samconfig.toml]: 
        SAM configuration environment [default]: 

        Looking for resources needed for deployment:
         Managed S3 bucket: aws-sam-cli-managed-default-samclisourcebucket-w09u3i2wjkab
         A different default S3 bucket can be set in samconfig.toml

        Saved arguments to config file
        Running 'sam deploy' for future deployments will use the parameters saved above.
        The above parameters can be changed by modifying samconfig.toml
        Learn more about samconfig.toml syntax at 
        https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-config.html

できた!!

スクリーンショット 2021-11-28 19.17.46.png

ローカル環境でテスト実行

SAMを使って感じたことは、ローカルでテスト実行することができる点だと感じました。
lambda、api gatewayだけのようなシンプルな構成はローカルテスト可能です。
上記で作成したものはdynamoDBやtranslate apiを使用しているので、ローカル環境ではエラーがでます。

  • ソースコードの構文チェック
sam validate
  • 関数をローカルで呼び出す
sam local invoke
  • Lambda ローカルテスト
sam local start-lambda

#別ターミナルで以下コマンド叩く
aws lambda invoke --function-name "TranslateLambda" \
--endpoint-url "http://127.0.0.1:3001" \
--no-verify-ssl out.txt
  • API Gateway ローカルテスト
sam local start-api

#別ターミナルで以下コマンド叩く
curl -w "\n" http://127.0.0.1:3000/translate

(参考)ハマりポイント

  • 初回デプロイ時エラーからの再デプロイ
Initiating deployment
=====================
Uploading to sam-app-demo/ec906befd23684dfd9dd718c1f5d6539.template  1114 / 1114  (100.00%)
Error: Failed to create changeset for the stack: sam-app-demo, An error occurred (ValidationError) when calling the CreateChangeSet operation: Stack:arn:aws:cloudformation:ap-northeast-1:624840664351:stack/sam-app-demo/515b2930-49e5-11ec-865e-06680d75238d is in DELETE_FAILED state and can not be updated.

⇨スタックを削除してから再デプロイする

aws cloudformation delete-stack --stack-name hogehoge
  • FAILEDとなった時の対処法
aws cloudformation describe-stack-events \
--stack-name sam-app-demo \
| jq '.StackEvents[] \
| select(.ResourceStatus == "CREATE_FAILED") \
| .ResourceStatusReason' -r
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0