CloudFormationはそれなりに書けるし、Lambda関数も書いたり動かしたり調査したり色々やってきたが、本職のデベロッパーでない悲しさか、AWS SAMは実は一度も触ったことがない(触る必要に迫られたことがない)。
苦手なままでは先々苦労しそうなので、このあたりで一度ウォークスルーしてみることにする。
やりたいこと
- AWS SAMをインストールする。
- 試し打ちしながら、できることを自分なりに整理してみる。
インストール
まずはインストール。
詳しくは公式を参照。
ローカル開発したい場合はDockerも必要らしい。
Dockerはもう入れてあるので、やることは以下。
% brew tap aws/tap
% brew install aws-sam-cli
入った。
% sam --version
SAM CLI, version 0.44.0
探索
まずはできることをまとめてみる。
コマンド | 内容 |
---|---|
sam init | SAMアプリケーションを初期化する。 |
sam validate | SAMテンプレートを検証するのに使う。 |
sam build | Lambda関数をビルドするのに使う。 |
sam local | サーバレスアプリケーションをローカル実行し、テスト等に使えるらしい。npm run serve的なものか? |
sam package | SAMアプリケーションをパッケージ?してくれるらしい。パッケージって具体的に何だ? |
sam deploy | SAMアプリケーションをデプロイしてくれるらしい。Lambda関数をクラウド上にデプロイするということだろう。 |
sam log | Lambda関数のログを取得してくれるようだ。 |
sam publish | AWSサーバーレスアプリケーションレポジトリに公開するために使う、らしい。 |
sam [コマンド] --help
でざっと用法を眺めてみたが、ドキュメント見た方が早そうだったので公式に目を通す。
なるほど。要するに、
-
sam init
でアプリのひな形を作り、 -
sam build
でビルドし、 -
sam deploy
でクラウド側にデプロイする
のだな。あれ、sam package
は?
と思ったら、ここを見る限り今は必須ではないらしい。sam local
でのローカル実行も今回はパス。
試し打ち
だいたいイメージができてきたので、試しにSAMアプリケーションとやらを作ってみる。
Amplifyで見たようなCUIが出てくるので、一番ラクそうなのを選んでいく。
% sam init
Which template source would you like to use?
1 - AWS Quick Start Templates
2 - Custom Template Location
Choice: 1
Which runtime would you like to use?
1 - nodejs12.x
2 - python3.8
3 - ruby2.7
4 - go1.x
5 - java11
6 - dotnetcore2.1
7 - nodejs10.x
8 - python3.7
9 - python3.6
10 - python2.7
11 - ruby2.5
12 - java8
13 - dotnetcore2.0
14 - dotnetcore1.0
Runtime: 2
Project name [sam-app]:
Cloning app templates from https://github.com/awslabs/aws-sam-cli-app-templates.git
AWS quick start application templates:
1 - Hello World Example
2 - EventBridge Hello World
3 - EventBridge App from scratch (100+ Event Schemas)
4 - Step Functions Sample App (Stock Trader)
Template selection: 1
-----------------------
Generating application:
-----------------------
Name: sam-app
Runtime: python3.8
Dependency Manager: pip
Application Template: hello-world
Output Directory: .
Next steps can be found in the README file at ./sam-app/README.md
出来上がったもの。
sam-app % ls -F
README.md events/ hello_world/ template.yaml tests/
sam-app % ls -lR
total 24
-rw-r--r-- 1 tnakatan staff 7490 6 5 14:51 README.md
drwxr-xr-x 3 tnakatan staff 96 6 5 14:51 events
drwxr-xr-x 5 tnakatan staff 160 6 5 14:51 hello_world
-rw-r--r-- 1 tnakatan staff 1623 6 5 14:51 template.yaml
drwxr-xr-x 3 tnakatan staff 96 6 5 14:51 tests
./events:
total 8
-rw-r--r-- 1 tnakatan staff 1997 6 5 14:51 event.json
./hello_world:
total 16
-rw-r--r-- 1 tnakatan staff 0 6 5 14:51 __init__.py
-rw-r--r-- 1 tnakatan staff 1151 6 5 14:51 app.py
-rw-r--r-- 1 tnakatan staff 8 6 5 14:51 requirements.txt
./tests:
total 0
drwxr-xr-x 4 tnakatan staff 128 6 5 14:51 unit
./tests/unit:
total 8
-rw-r--r-- 1 tnakatan staff 0 6 5 14:51 __init__.py
-rw-r--r-- 1 tnakatan staff 2579 6 5 14:51 test_handler.py
本体らしきapp.pyを見てみる。
sam-app % wc -l hello_world/app.py
42 hello_world/app.py
42行ほどのPythonスクリプト。中はほんとにhello worldだった(本筋から外れるので省略)。
単体テストっぽい名前のファイル('test/unit/test_handler.py')もあり、こちらはAPI Gatewayイベントを模したテストイベントを生成してくれるものようだ。省略。
次にSAMテンプレートらしきファイルを開く。
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
sam-app
Sample SAM Template for sam-app
# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst
Globals:
Function:
Timeout: 3
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.lambda_handler
Runtime: python3.8
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
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
なるほど。app.py
のlambda.handler()
を呼ぶPyhon3.8ベースのLambda関数を、AWS::Serverless::Function
というリソースとして作成してくれるようだ。
CloudFormationの書式に則っているが、AWS::Serverless::Funcion
とか見慣れないリソースがあるので、拡張キットのような感じか。
続いてビルド。
% sam build
Building resource 'HelloWorldFunction'
Running PythonPipBuilder:ResolveDependencies
Running PythonPipBuilder:CopySource
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
何か出た。
ビルドのイメージが掴めてなかったので、安心するために中を見てみる。
sam-app % ls -F .aws-sam/build
HelloWorldFunction/ template.yaml
template.yaml
はさっきのやつなので、新しく生成されたのはHelloWorldFunction
の方だ。
sam-app % ls -F .aws-sam/build/HelloWorldFunction
__init__.py chardet-3.0.4.dist-info/ requirements.txt
app.py idna/ urllib3/
certifi/ idna-2.9.dist-info/ urllib3-1.25.9.dist-info/
certifi-2020.4.5.1.dist-info/ requests/
chardet/ requests-2.23.0.dist-info/
なるほど。Lambda関数のコード本体(app.py
)と、依存関係のあるライブラリをひとまとめにしてくれているようだ。
これをzipすればそのままLambda関数をデプロイできそうな気配がしてきた。
最後にデプロイしてみる。
sam-app % sam deploy --guided
Configuring SAM deploy
======================
Looking for samconfig.toml : Not found
Setting default arguments for 'sam deploy'
=========================================
Stack Name [sam-app]:
AWS Region [us-east-1]: ap-northeast-1
#Shows you resources changes to be deployed and require a 'Y' to initiate deploy
Confirm changes before deploy [y/N]:
#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]:
Save arguments to samconfig.toml [Y/n]:
Looking for resources needed for deployment: Not found.
Creating the required resources...
Successfully created!
Managed S3 bucket: aws-sam-cli-managed-default-samclisourcebucket-1b1hnsqvj6mby
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
Deploying with following values
===============================
Stack name : sam-app
Region : ap-northeast-1
Confirm changeset : False
Deployment s3 bucket : aws-sam-cli-managed-default-samclisourcebucket-1b1hnsqvj6mby
Capabilities : ["CAPABILITY_IAM"]
Parameter overrides : {}
Initiating deployment
=====================
Uploading to sam-app/64f7e1a020d874114ae09ddedb09fe0e 534640 / 534640.0 (100.00%)
Uploading to sam-app/d4f5b52b0d855ee4384f4c34fea93509.template 1090 / 1090.0 (100.00%)
Waiting for changeset to be created..
CloudFormation stack changeset
---------------------------------------------------------------------------------------------------------------------
Operation LogicalResourceId ResourceType
---------------------------------------------------------------------------------------------------------------------
+ Add HelloWorldFunctionHelloWorldPermissio AWS::Lambda::Permission
nProd
+ Add HelloWorldFunctionRole AWS::IAM::Role
+ Add HelloWorldFunction AWS::Lambda::Function
+ Add ServerlessRestApiDeployment47fc2d5f9d AWS::ApiGateway::Deployment
+ Add ServerlessRestApiProdStage AWS::ApiGateway::Stage
+ Add ServerlessRestApi AWS::ApiGateway::RestApi
---------------------------------------------------------------------------------------------------------------------
Changeset created successfully. arn:aws:cloudformation:ap-northeast-1:016831194521:changeSet/samcli-deploy1591338862/fdb59513-7141-4326-8b8c-5231dbcc785c
2020-06-05 15:34:33 - Waiting for stack create/update to complete
CloudFormation events from changeset
---------------------------------------------------------------------------------------------------------------------
ResourceStatus ResourceType LogicalResourceId ResourceStatusReason
---------------------------------------------------------------------------------------------------------------------
CREATE_IN_PROGRESS AWS::IAM::Role HelloWorldFunctionRole -
CREATE_IN_PROGRESS AWS::IAM::Role HelloWorldFunctionRole Resource creation Initiated
CREATE_COMPLETE AWS::IAM::Role HelloWorldFunctionRole -
CREATE_IN_PROGRESS AWS::Lambda::Function HelloWorldFunction -
CREATE_IN_PROGRESS AWS::Lambda::Function HelloWorldFunction Resource creation Initiated
CREATE_COMPLETE AWS::Lambda::Function HelloWorldFunction -
CREATE_IN_PROGRESS AWS::ApiGateway::RestApi ServerlessRestApi -
CREATE_COMPLETE AWS::ApiGateway::RestApi ServerlessRestApi -
CREATE_IN_PROGRESS AWS::ApiGateway::RestApi ServerlessRestApi Resource creation Initiated
CREATE_IN_PROGRESS AWS::ApiGateway::Deployment ServerlessRestApiDeployment -
47fc2d5f9d
CREATE_IN_PROGRESS AWS::ApiGateway::Deployment ServerlessRestApiDeployment Resource creation Initiated
47fc2d5f9d
CREATE_IN_PROGRESS AWS::Lambda::Permission HelloWorldFunctionHelloWorl Resource creation Initiated
dPermissionProd
CREATE_IN_PROGRESS AWS::Lambda::Permission HelloWorldFunctionHelloWorl -
dPermissionProd
CREATE_COMPLETE AWS::ApiGateway::Deployment ServerlessRestApiDeployment -
47fc2d5f9d
CREATE_IN_PROGRESS AWS::ApiGateway::Stage ServerlessRestApiProdStage -
CREATE_IN_PROGRESS AWS::ApiGateway::Stage ServerlessRestApiProdStage Resource creation Initiated
CREATE_COMPLETE AWS::ApiGateway::Stage ServerlessRestApiProdStage -
CREATE_COMPLETE AWS::Lambda::Permission HelloWorldFunctionHelloWorl -
dPermissionProd
CREATE_COMPLETE AWS::CloudFormation::Stack sam-app -
---------------------------------------------------------------------------------------------------------------------
CloudFormation outputs from deployed stack
---------------------------------------------------------------------------------------------------------------------
Outputs
---------------------------------------------------------------------------------------------------------------------
Key HelloWorldFunctionIamRole
Description Implicit IAM Role created for Hello World function
Value arn:aws:iam::016831194521:role/sam-app-HelloWorldFunctionRole-MSA3RKSU6C23
Key HelloWorldApi
Description API Gateway endpoint URL for Prod stage for Hello World function
Value https://ixoyzu474a.execute-api.ap-northeast-1.amazonaws.com/Prod/hello/
Key HelloWorldFunction
Description Hello World Lambda Function ARN
Value arn:aws:lambda:ap-northeast-1:016831194521:function:sam-app-HelloWorldFunction-UY2UF7WMHXI4
---------------------------------------------------------------------------------------------------------------------
Successfully created/updated stack - sam-app in ap-northeast-1
おお、まじか。ファイルを生成するだけかと思ったら、いきなりCloudFormationのスタックまで作成された。
所要時間は約1分。
マネジメントコンソールでCloudFormationを開いてみる。
Rest APIとLambda関数、IAMロールが作られている(Lambdaでよく使う、AWSLambdaBasicExecutionRole
ポリシーがアタッチされていた)。
出力にAPIのエンドポイントが出ているので、これを叩けばよさそうだ。
無事Hello Worldしてくれた。
ちなみに、このLambda関数は「Lambdaアプリケーション」として構成されるようだ。
おまけ
ついでなので、ローカル実行をやってみた(Dockerはインストール済み)。
% sam local start-api
Mounting HelloWorldFunction at http://127.0.0.1:3000/hello [GET]
You can now browse to the above endpoints to invoke your functions. You do not need to restart/reload SAM CLI while working on your functions, changes will be reflected instantly/automatically. You only need to restart SAM CLI if you update your AWS SAM template
2020-06-05 16:28:41 * Running on http://127.0.0.1:3000/ (Press CTRL+C to quit)
...(省略)
クラウドにデプロイした時と同じくLambdaバックエンドのAPIをローカルのコンテナ上でホストしてくれる模様。
ブラウザでhttp://localhost:3000/hello
を叩くと、こちらも無事Hello Worldしてくれた。
結論
- できること
- CloudFormation互換の書式でサーバーレスのテンプレート(SAMテンプレート)を書ける。
- SAMテンプレートを元に、sam cliで2コマンドでビルドしてデプロイできる。
- ビルドはコードのみならず依存関係のあるランタイムまで取り纏めて、アーティファクト一式としてbuildフォルダに準備してくれる。
- デプロイはアーティファクト(buildフォルダ)をクラウド上にデプロイしてくれる。APIやLambda関数のガラなど、必要なAWSリソースはCloudFormationスタックとして作成してくれる。
- ビルドとデプロイは別々のコマンドなので、パイプラインに応じて、分けて実行できそう。
- Dockerが入ってればローカルでテスト実行もできる。
以上、今さらながら使ってみたAWS SAMでした。