AWS SAMでアプリケーションをローカルテスト&デプロイを試してみた
AWS SAMのローカルテストとデプロイをデモンストレーションしてみました

TL;DR
☆ SAMの基本的な使い方
☆ ローカルデプロイの方法
☆ Cfnとの比較
はじめに
こちらの記事 で作成した環境をテンプレート化したい!と思ったので、 AWS SAMを使ってみました。 SAMはリソースをプロビジョニングできるだけでなく、ローカルでLambda、API Gatewayをテストできる便利ツールだったのでその使い方も紹介します。 途中、cloudformationコマンドとの比較もしていますのでご参考までに。
環境
- mac OS:Monterey 12.0.1
- AWS CLI:2.2.33
- SAM CLI:1.35.0
1. SAMとは
- AWS Serverless Application Modelの略
- サーバーレスアプリケーション構築用のオープンソースフレームワーク
- YAML,JSON形式でテンプレート記述
- CloudFormationの拡張機能で、簡単にテンプレートを記述することが可能
- SAM CLIあり
2. SAM CLIのインストール
こちらからどうぞ
3. SAM利用の流れ
1. SAMテンプレートの記述
1. パッケージング
1. デプロイ
3-1. SAMテンプレートの記述
テンプレート構造
実際のコード
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
のいずれか必須 など
3-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
コマンド実行後、下記ファイルが出力される
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を見ると、確かにアップされている!
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
が作成され、配下に下記テンプレートファイルが作成される
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リンクになっていないが、バケットとオブジェクトが作成されていました
3-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
できた!!
4. ローカル環境でテスト実行
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
まとめ
一通りSAMの基本的な使い方をまとめてみました。 ローカルデプロイはいろいろ使い道を見いだせそうですね。 今後は、実務で使う際の注意点やベストプラクティス等まとめてみたいと思います。