AWS SAM でサーバレスアプリケーション(WebAPI)を動かす
AWS SAM(Serverless Application Model)は、LambdaやAPI GatewayなどのAWSのサービスを使ったサーバレスアプリケーションを構築可能なフレームワークです。
今回は SAM を使って、サンプルアプリケーションを動かしてみます。
事前準備
AWS CLI, AWS SAM CLI, Node.js のインストールを済ませます。
AWS CLI は aws configure などを実行し初期設定を済ませておきます。
% aws --version aws-cli/2.1.23 Python/3.9.1 Darwin/19.6.0 source/x86_64 prompt/off % sam --version SAM CLI, version 1.17.0 % node --version v14.15.4
アプリケーションの作成
sam init でアプリケーションを作成します。
% sam init
Which template source would you like to use?
1 - AWS Quick Start Templates
2 - Custom Template Location
Choice: 1
What package type would you like to use?
1 - Zip (artifact is a zip uploaded to S3)
2 - Image (artifact is an image uploaded to an ECR image repository)
Package type: 1
Which runtime would you like to use?
1 - nodejs14.x
2 - python3.8
3 - ruby2.7
4 - go1.x
5 - java11
6 - dotnetcore3.1
7 - nodejs12.x
8 - nodejs10.x
9 - python3.7
10 - python3.6
11 - python2.7
12 - ruby2.5
13 - java8.al2
14 - java8
15 - dotnetcore2.1
Runtime: 1
Project name [sam-app]: sam-hello-app
Cloning app templates from https://github.com/aws/aws-sam-cli-app-templates
AWS quick start application templates:
1 - Hello World Example
2 - Step Functions Sample App (Stock Trader)
3 - Quick Start: From Scratch
4 - Quick Start: Scheduled Events
5 - Quick Start: S3
6 - Quick Start: SNS
7 - Quick Start: SQS
8 - Quick Start: Web Backend
Template selection: 1
-----------------------
Generating application:
-----------------------
Name: sam-hello-app
Runtime: nodejs14.x
Dependency Manager: npm
Application Template: hello-world
Output Directory: .
Next steps can be found in the README file at ./sam-hello-app/README.md
次の構造のアプリケーションが作成されます。
sam-hello-app ├── README.md ├── events │ └── event.json ├── hello-world │ ├── app.js │ ├── package.json │ └── tests │ └── unit │ └── test-handler.js └── template.yaml
基本的には template.yaml にアプリケーションの構成を、hello-world/app.js に実際の処理(Lambda関数の実装)をします。
template.yaml は次の内容です(ここではテンプレートのrepositoryを参照しています)。
Resources のセクションに必要なリソース(例えば、Lambda、API Gateway、S3やDynamoDB)を記述していきます。
今回は、Lambda関数としてHelloWorldFunctionが、Lambda関数をAPIとして利用できるようAPI GatewayとしてHelloWorldApiが定義されています。
また、hello-world/app.js は次のとおりです。
ローカル環境での動作確認
まずは手元のPC上で動作確認してみましょう。
npm install
Lambda 関数は、Amazon Linux 上で実行されます。macOSなどの異なる環境上で npm install を行うとパッケージによっては動作しないことがあります。 そこで次のようにプラットフォームを指定して npm install を行います。
% cd hello-world % npm install --arch=x64 --platform=linux
起動(sam local start-api)
sam local start-api で Lambda 関数をホストするローカルの HTTP サーバが起動します。
% cd .. % sam local start-api # template.yaml と同じ階層に移動 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 2021-02-07 22:20:50 * Running on http://127.0.0.1:3000/ (Press CTRL+C to quit)
動作確認
curl を使って先ほど起動したHTTPサーバにアクセスしてみます。
% curl http://127.0.0.1:3000/hello
{"message":"hello world"}
APIとしてLambda関数を実行することができました。
Lambda関数の実装を変更してみましょう
sam local start-api はホットリロードに対応しています。
したがって、Lambda 関数の実装を変更した場合でも、HTTPサーバを再起動せず(sam local start-apiを再実行せずに)、変更が反映されます。
Lambda関数の実装 hello-world/app.js の実装を変更して表示されるメッセージを変更してみましょう。
response = { 'statusCode': 200, 'body': JSON.stringify({ message: 'EZ DO DANCE', // こちらを変更 // location: ret.data.trim() })
では、先ほどと同様に curl でアクセスしてみます。
% curl http://127.0.0.1:3000/hello
{"message":"EZ DO DANCE"}
表示内容が変更されました!
実際の開発の際は、ローカルサーバを起動したままLambda関数の実装を変更し動作確認する流れになりそうです(とても便利ですね)。
AWS環境へデプロイする(sam buildとsam deploy)
ローカル環境での動作確認が済んだので、実際にAWS環境へデプロイしてみましょう。
ビルドとデプロイ
sam build は --use-container を指定すると実際の動作環境に近い Docker コンテナ上でビルドを行うことができます。
sam deploy は --guided を指定するとデプロイに関わる設定を行いながらデプロイが行えます。
# アプリケーションのビルド
% sam build --use-container
Starting Build inside a container
Building codeuri: hello-world/ runtime: nodejs14.x metadata: {} functions: ['HelloWorldFunction']
Fetching amazon/aws-sam-cli-build-image-nodejs14.x Docker container image......
Mounting /Users/yutokubo/projects/sam-hello-app/hello-world as /tmp/samcli/source:ro,delegated inside runtime container
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
Running NodejsNpmBuilder:NpmPack
Running NodejsNpmBuilder:CopyNpmrc
Running NodejsNpmBuilder:CopySource
Running NodejsNpmBuilder:NpmInstall
Running NodejsNpmBuilder:CleanUpNpmrc
# デプロイ
% sam deploy --guided
Configuring SAM deploy
======================
Looking for config file [samconfig.toml] : Not found
Setting default arguments for 'sam deploy'
=========================================
Stack Name [sam-app]: sam-hello-app
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
HelloWorldFunction 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: Not found.
Creating the required resources...
Successfully created!
Managed S3 bucket: aws-sam-cli-managed-default-samclisourcebucket-xxxxxx
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
Uploading to sam-hello-app/6d165a6f8e6b1f14d69a5f59807a9541 121586 / 121586.0 (100.00%)
Deploying with following values
===============================
Stack name : sam-hello-app
Region : ap-northeast-1
Confirm changeset : True
Deployment s3 bucket : aws-sam-cli-managed-default-samclisourcebucket-xxxxxx
Capabilities : ["CAPABILITY_IAM"]
Parameter overrides : {}
Signing Profiles : {}
Initiating deployment
=====================
HelloWorldFunction may not have authorization defined.
Uploading to sam-hello-app/a9c5be03ba9e86b1f09de6c10ede13d7.template 1108 / 1108.0 (100.00%)
Waiting for changeset to be created..
CloudFormation stack changeset
-------------------------------------------------------------------------------------------------
Operation LogicalResourceId ResourceType Replacement
-------------------------------------------------------------------------------------------------
+ Add HelloWorldFunctionHell AWS::Lambda::Permissio N/A
oWorldPermissionProd n
+ Add HelloWorldFunctionRole AWS::IAM::Role N/A
+ Add HelloWorldFunction AWS::Lambda::Function N/A
+ Add ServerlessRestApiDeplo AWS::ApiGateway::Deplo N/A
yment0000000000 yment
+ Add ServerlessRestApiProdS AWS::ApiGateway::Stage N/A
tage
+ Add ServerlessRestApi AWS::ApiGateway::RestA N/A
pi
-------------------------------------------------------------------------------------------------
Changeset created successfully. arn:aws:cloudformation:ap-northeast-1:000000:changeSet/samcli-deploy000000/9db63ba3-ddf4-4c2c-9af0-095e65510000
Previewing CloudFormation changeset before deployment
======================================================
Deploy this changeset? [y/N]: y
2021-02-07 22:51:42 - 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::RestA ServerlessRestApi -
pi
CREATE_IN_PROGRESS AWS::ApiGateway::RestA ServerlessRestApi Resource creation
pi Initiated
CREATE_COMPLETE AWS::ApiGateway::RestA ServerlessRestApi -
pi
CREATE_IN_PROGRESS AWS::ApiGateway::Deplo ServerlessRestApiDeplo -
yment yment47fc2d5f9d
CREATE_IN_PROGRESS AWS::ApiGateway::Deplo ServerlessRestApiDeplo Resource creation
yment yment47fc2d5f9d Initiated
CREATE_IN_PROGRESS AWS::Lambda::Permissio HelloWorldFunctionHell Resource creation
n oWorldPermissionProd Initiated
CREATE_IN_PROGRESS AWS::Lambda::Permissio HelloWorldFunctionHell -
n oWorldPermissionProd
CREATE_COMPLETE AWS::ApiGateway::Deplo ServerlessRestApiDeplo -
yment yment47fc2d5f9d
CREATE_IN_PROGRESS AWS::ApiGateway::Stage ServerlessRestApiProdS -
tage
CREATE_IN_PROGRESS AWS::ApiGateway::Stage ServerlessRestApiProdS Resource creation
tage Initiated
CREATE_COMPLETE AWS::ApiGateway::Stage ServerlessRestApiProdS -
tage
CREATE_COMPLETE AWS::Lambda::Permissio HelloWorldFunctionHell -
n oWorldPermissionProd
CREATE_COMPLETE AWS::CloudFormation::S sam-hello-app -
tack
-------------------------------------------------------------------------------------------------
CloudFormation outputs from deployed stack
-------------------------------------------------------------------------------------------------
Outputs
-------------------------------------------------------------------------------------------------
Key HelloWorldFunctionIamRole
Description Implicit IAM Role created for Hello World function
Value arn:aws:iam::0000000:role/sam-hello-app-HelloWorldFunctionRole-
BVZKC3SFRLYW
Key HelloWorldApi
Description API Gateway endpoint URL for Prod stage for Hello World function
Value https://6xcmvqyqw4.execute-api.ap-northeast-1.amazonaws.com/Prod/hello/
Key HelloWorldFunction
Description Hello World Lambda Function ARN
Value arn:aws:lambda:ap-northeast-1:0000000:function:sam-hello-app-
HelloWorldFunction-00000000
-------------------------------------------------------------------------------------------------
Successfully created/updated stack - sam-hello-app in ap-northeast-1
sam deploy を実行すると、CloudFormationを使ってデプロイや実行に必要な IAM role、リソースとしてLambdaやAPI Gatewayが追加されます。
また、今回指定した設定内容は samconfig.toml に保存されています。
次回以降のデプロイは --guided を指定せず sam deploy で実行可能です。
% sam deploy
動作確認
では動作確認してみましょう。
% curl https://6xcmvqyqw4.execute-api.ap-northeast-1.amazonaws.com/Prod/hello/
{"message":"EZ DO DANCE"}%
AWS環境でも動作できることを確認できました!(とても簡単ですね!)
備考: sam local start-api でホットリロードが有効にならないケース
sam build を行った後に sam local start-api を実行すると、ホットリロードが利用できずLambda関数の変更が反映されないことがことがあります。
これは、sam local start-api では sam build の出力結果である .aws-sam 配下のプログラムが優先されることのようです。
この場合は、.aws-sam を削除してから sam local start-api を実行します。
% rm -rf .aws-sam % sam local start-api
終わりに
今回は、AWS SAM を使って、サーバレスアプリケーションを動作させてみました。
SAM CLI を使うことでローカル環境での動作確認が可能なこと、AWSコンソールをポチポチすることなくデプロイまで実施できることを確認しました。
特に、各種デプロイやリソースがCloudFormationで管理されることで、開発環境や本番環境など複数の環境が存在する場合でも容易に環境構築やリリースが可能になりそうです。
次は、より実践的なWebAPIを開発してみようと思います。