SAM(Serverless Application Model)とは
サーバーレスアプリケーション構築用のオープンソースフレームワーク
https://aws.amazon.com/jp/serverless/sam/
簡単にまとめると
- Lambda開発の手間を削減
- ローカル上でLamabdaを再現してテスト、デバッグができる
- SAM 構文のテンプレートでサーバーレスアプリケーションの構築を高速化
実行環境
Windowsで実施
AWS SAMを使用するためのCLIをインストール
$ sam --version
SAM CLI, version 1.94.0
前提
Ubuntu 環境導入済み
Docker 導入済み
AWS CLI 導入済み
プロジェクト作成
sam init
コマンドでアプリケーションの初期設定
--runtime
オプションでLamabdaのランタイムを設定(今回はpython3.9)
$ cd [作業ディレクトリ] #カレントディレクトリ配下にプロジェクトが作成されるためあらかじめ移動しておく
$ sam init --runtime python3.9
Which template source would you like to use?
1 - AWS Quick Start Templates
2 - Custom Template Location
Choice: 1
Choose an AWS Quick Start application template
1 - Hello World Example
2 - Hello World Example with Powertools for AWS Lambda
3 - Infrastructure event management
4 - Multi-step workflow
5 - Lambda EFS example
6 - Serverless Connector Hello World Example
7 - Multi-step workflow with Connectors
Template: 1
Based on your selections, the only Package type available is Zip.
We will proceed to selecting the Package type as Zip.
Based on your selections, the only dependency manager available is pip.
We will proceed copying the template using pip.
Would you like to enable X-Ray tracing on the function(s) in your application? [y/N]: n
Would you like to enable monitoring using CloudWatch Application Insights?
For more info, please view https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/cloudwatch-application-insights.html [y/N]: n
Project name [sam-app]: sample-app
-----------------------
Generating application:
-----------------------
Name: sample-app
Runtime: python3.9
Architectures: x86_64
Dependency Manager: pip
Application Template: hello-world
Output Directory: .
Configuration file: sample-app\samconfig.toml
Next steps can be found in the README file at sample-app\README.md
Commands you can use next
=========================
[*] Create pipeline: cd sample-app && sam pipeline init --bootstrap
[*] Validate SAM template: cd sample-app && sam validate
[*] Test Function in the Cloud: cd sample-app && sam sync --stack-name {stack-name} --watch
デプロイ確認までしたいので今回は1 - Hello World Example
を選択し、ガイド通りに進みプロジェクト名を入力
プロジェクトディレクトリが作成されているのでカレントディレクトリを移動&構造を確認
(今後コマンドはsample-app/ で実施)
sample-app
│ .gitignore
│ README.md
│ samconfig.toml
│ template.yaml #samのテンプレートファイル
│ __init__.py
│
├─events
│ event.json #テストで使用するイベント
│
├─hello_world #アプリのディレクトリ
│ app.py
│ requirements.txt
│ __init__.py
│
└─tests
│ testsは省略
template.yamlのResourcesセクション
Transform: AWS::Serverless-2016-10-31
SAMのテンプレートでは上記のTransform宣言がされている
template.yamlのResourcesセクション
Resources:
HelloWorldFunction: #リソース名 ※CFN内でのみ使用される名前
Type: AWS::Serverless::Function #リソースの種別はLambda関数
Properties: #リソースの設定
CodeUri: hello_world/ #アプリソースのディレクトリ
Handler: app.lambda_handler #Lambdaハンドラーの指定
Runtime: python3.9
Architectures:
- x86_64
Events: #関数をトリガーするイベントのを指定
HelloWorld: #イベント名 ※CFN内でのみ使用される名前
Type: Api #イベントの種別
Properties: #イベントの設定
Path: /hello #呼び出される URI パス
Method: get #HTTPメソッド
テンプレートを検証
SAMテンプレートが有効かどうか検証
$ sam validate
template.yaml is a valid SAM Template
検証結果問題なし
試しにサポートされていないリソースタイプで実施
Resources:
HelloWorldFunction:
- Type: AWS::Serverless::Function
+ Type: AWS::Serverless::ValidateTest
$ sam validate
E3038 Serverless Transform required for Type AWS::Serverless::ValidateTest for resource HelloWorldFunction
Error: Linting failed. At least one linting rule was matched to the provided template.
template.yamlを変更してもビルドやデプロイ前に構文エラーを発見できるので初めのうちはお世話になりそう👍
ビルド
$ sam build
成功するとビルドされたモジュールが.aws-sam/
に生成
テスト(省略可)
まずは期待される結果を確認
{"message": "hello world"}をボディとしてstatusCode: 200で返すアプリ
import json
def lambda_handler(event, context):
return {
"statusCode": 200,
"body": json.dumps({
"message": "hello world",
}),
}
Lambda関数のローカル実行してテスト実施
$ sam local invoke
Invoking app.lambda_handler (python3.9)
Local image is up-to-date
Using local image: public.ecr.aws/lambda/python:3.9-rapid-x86_64.
Mounting ~~~\sample-app\.aws-sam\build\HelloWorldFunction as /var/task:ro,delegated, inside runtime container
START RequestId: 011dd512-cd77-4599-8ed8-0a4d88403790 Version: $LATEST
END RequestId: 011dd512-cd77-4599-8ed8-0a4d88403790
REPORT RequestId: 011dd512-cd77-4599-8ed8-0a4d88403790 Init Duration: 0.32 ms Duration: 185.27 ms Billed Duration: 186 ms Memory Size: 128 MB Max Memory Used: 128 MB
{"statusCode": 200, "body": "{\"message\": \"hello world\"}"}
START RequestIdの行からREPORT RequestIdの行までがLambdaが出力したログ
最後の{"statusCode": 200, "body": "{"message": "hello world"}"}がレスポンス内容
ローカルでapigwを起動して実際にAPIを叩いてみる
$ sam local start-api --port 6000
~
~
~
* Running on http://127.0.0.1:6000
2023-08-05 18:19:47 Press CTRL+C to quit
最後の2行がこのように表示されたらローカルでapiを叩く準備は完了
template.yamlでapiの設定値は下記だったのでcurlコマンドを用意してテスト実施
Path: /hello
Method: get
$ curl http://127.0.0.1:6000/hello
{"message": "hello world"}
期待通りの内容が出力を確認
パッケージング
$ sam package --template-file template.yaml --output-template-file packaged.yaml
~
Successfully packaged artifacts and wrote output template to file packaged.yaml.
~
sam package
--template-file テンプレートファイルを指定
--output-template-file デプロイ用に出力されるテンプレートファイル名を指定
Successfully packaged ~~~ が表示されていたら成功
デプロイ
$ sam deploy --template-file packaged.yaml --stack-name sample-app-stack --region ap-northeast-1 --guided
~
Stack Name [sample-app-stack]:#そのままEnter
AWS Region [ap-northeast-1]:#そのままEnter
#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]: n
The resource AWS::Serverless::Function 'HelloWorldFunction' has specified S3 location for CodeUri. It will not be built and SAM CLI does not support invoking it locally.
Save arguments to configuration file [Y/n]: y
SAM configuration file [samconfig.toml]:#そのままEnter
SAM configuration environment [default]:#そのままEnter
~
~
Deploy this changeset? [y/N]: y
~
~
Successfully created/updated stack - sample-app-stack in ap-northeast-1
sam deploy
--template-file パッケージングで出力されたファイルを指定
--stack-name スタック名を指定
--region リージョンを指定
--guided ガイド付きでデプロイ
Successfully ~~~ が最後に出力されていれば完了
コマンドライン上ではstackの差分やデプロイ状況など表示されている。
ローカル上での操作が完了したのでAWSコンソールでCloudFormationの画面を開きスタックのステータスを確認
また、スタックごと削除すれば紐づいているリソースなどを綺麗に削除できる
逆にスタックで消さないとめんどくさくなる?
動作確認
API Gatewayから作成されたAPIのProdステージのURLを取得
https://*****.execute-api.[リージョン].amazonaws.com/Prod[path]
[path]は/helloにしてGetメソッドでapiを叩く
curl https://*****.execute-api.[リージョン].amazonaws.com/Prod/hello
StatusCode : 200
StatusDescription : OK
Content : {"message": "hello world"}
~
~
~
レスポンス内容はAPI Gatewayの設定により変更されているが{"message": "hello world"}とレスポンス自体を確認できたので動作確認完了