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を開発してみようと思います。