AWS SAM (Serverless Application Model)はAWS公式の サーバーレスアプリケーションのビルドツール。 CloudFormationのテンプレートを設定ファイルに書くことでLambda関数と共にイベントトリガーや他のリソースも含めてデプロイでき、 その点でServerless Frameworkと立ち位置が近いが、向こうがLambda以外のサーバーレス環境にも対応していたり、 プラグインによって機能拡張できるようになっている一方、こちらは比較的薄いツールになっている。 ただ、Serverless Application Repositoryで公開するにはSAMの形式にする必要があり、 Serverless FrameworkにもSAMのテンプレートを出力するプラグインがある。
Serverless FrameworkでLambdaをデプロイする - sambaiz-net
SAM CLIのインストール
$ brew tap aws/tap
$ brew install aws-sam-cli
$ sam --version
SAM CLI, version 0.11.0
init
initすると次の構成のディレクトリが作られる。
$ sam init --runtime go1.x -n test-sam
$ cd test-sam/
$ ls
Makefile README.md hello-world template.yaml
template.yaml
の中に関数の設定やCloudFormationのテンプレートを書く。
$ cat template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
test-sam
Sample SAM Template for test-sam
# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst
Globals:
Function:
Timeout: 5
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: hello-world
Runtime: go1.x
Tracing: Active # https://docs.aws.amazon.com/lambda/latest/dg/lambda-x-ray.html
Events:
CatchAll:
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
Environment: # More info about Env Vars: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#environment-object
Variables:
PARAM1: VALUE
Outputs:
HelloWorldAPI:
Description: "API Gateway endpoint URL for Prod environment for First Function"
Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello/"
HelloWorldFunction:
Description: "First Lambda Function ARN"
Value: !GetAtt HelloWorldFunction.Arn
HelloWorldFunctionIamRole:
Description: "Implicit IAM Role created for Hello World function"
Value: !GetAtt HelloWorldFunctionRole.Arn
ローカルで実行
sam build
するとartifactが .aws-sam/build
に生成される。
その後 sam local
でコンテナ内で実行できる。
$ make build
$ sam local start-api
$ curl localhost:3000/hello
Fetching lambci/lambda:go1.x Docker container image.....
package
アプリケーションをS3にアップロードし、そのURIを含むテンプレートを出力する。
$ sam package --output-template-file packaged.yaml --s3-bucket <bucket_name>
$ cat packaged.yaml
AWSTemplateFormatVersion: '2010-09-09'
Description: 'test-sam
Sample SAM Template for test-sam
'
Globals:
Function:
Timeout: 5
Outputs:
HelloWorldAPI:
Description: API Gateway endpoint URL for Prod environment for First Function
Value:
Fn::Sub: https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello/
HelloWorldFunction:
Description: First Lambda Function ARN
Value:
Fn::GetAtt:
- HelloWorldFunction
- Arn
HelloWorldFunctionIamRole:
Description: Implicit IAM Role created for Hello World function
Value:
Fn::GetAtt:
- HelloWorldFunctionRole
- Arn
Resources:
HelloWorldFunction:
Properties:
CodeUri: s3://<bucket_name>/c97948866b9a6fb535aeb5fa092a633d
Environment:
Variables:
PARAM1: VALUE
Events:
CatchAll:
Properties:
Method: GET
Path: /hello
Type: Api
Handler: hello-world
Runtime: go1.x
Tracing: Active
Type: AWS::Serverless::Function
Transform: AWS::Serverless-2016-10-31
deploy
CloudFormationのStackを作成する。
$ sam deploy --template-file packaged.yaml --stack-name test-sam-app --capabilities CAPABILITY_IAM --region us-east-1
Successfully created/updated stack - test-sam-app
$ aws cloudformation describe-stacks --stack-name test-sam-app --query 'Stacks[].Outputs'
[
[
{
"Description": "Implicit IAM Role created for Hello World function",
"OutputKey": "HelloWorldFunctionIamRole",
"OutputValue": "arn:aws:iam::*****:role/test-sam-app-HelloWorldFunctionRole-1TEAXP5ELXA9V"
},
{
"Description": "API Gateway endpoint URL for Prod environment for First Function",
"OutputKey": "HelloWorldAPI",
"OutputValue": "https://gr67rdb1qj.execute-api.us-east-1.amazonaws.com/Prod/hello/"
},
{
"Description": "First Lambda Function ARN",
"OutputKey": "HelloWorldFunction",
"OutputValue": "arn:aws:lambda:us-east-1:*****:function:test-sam-app-HelloWorldFunction-1QOX2RNRJ7G4L"
}
]
]
$ aws cloudformation delete-stack --stack-name test-sam-app
Serverless Application Repositoryに公開
template.yaml
にServerless Application Repository用のMetadataを追加して再packageする。
Metadata:
AWS::ServerlessRepo::Application:
Name: test-sam
Description: hello world
Author: test
SpdxLicenseId: Apache-2.0
LicenseUrl: s3://<bucket-name>/LICENSE.txt
ReadmeUrl: s3://<bucket-name>/README.md
Labels: ['tests']
HomePageUrl: https://github.com/test/test
SemanticVersion: 0.0.1
SourceCodeUrl: https://github.com/test/test
最初、LicenseUrlとReadmeUrlを単にLICENSE.txt、README.mdとしたところ、次のエラーがでてpublishできなかった。
一見packageに失敗しているように見えて原因が分からず困ったが、--debug
を付けて実行するとどこで失敗しているかが分かる。
Error: Your SAM template contains invalid S3 URIs. Please make sure that you have uploaded application artifacts to S3 by packaging the template: 'sam package --template-file <file-path>'.
バケットポリシーに次のStatementを追加する。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "serverlessrepo.amazonaws.com"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::<your-bucket-name>/*"
}
]
}
$ sam publish -t packaged.yaml
Publish Succeeded
デフォルトではprivateになっていて、AWSアカウントを指定して限定公開することもできる。
デプロイボタンを押すとStackが作成されデプロイされる。