はじめに
Lambda を開発するときに、どういった環境を使っているでしょうか。AWS マネージドコンソールには、オンラインエディターがあり、ブラウザ上でプログラミングができます。しかし、本格的に開発するときには、多機能で使い慣れた IDE が使いたくなります。手元のノートPC上にインストールしている IDE を使って開発するときに、動作確認のたびに、いちいちプログラミング途中のソースコードをパッケージングして Lambda へアップロードするのは面倒です。出来るだけローカルで完結させて、素早く動作確認と修正を行いたい気持ちになります。
こういう時に便利に使えるのが、SAM (Serverless Application Model) です。SAM は、Lambda を開発するときに便利に使えるオープンソースフレームワークで、次の特徴があります。
- Lambda ライクなローカル環境が使えて、手元で動作確認が出来る
- Lambda Function と、それに付随する API Gateway などの定義して、デプロイ出来る
今回は、SAM の Quick Start をやってみたので、備忘録的にメモを残しておきます。Quick Start は、このドキュメントに書かれているものを参考にしています。
前提条件
- Ubuntu 環境 (WSL2)
- SAM CLI インストール済み
- AWS CLI インストール済み
- Docker インストール済み
- Homebrew on Linux インストール済み
memo : Docker Install
次の URL を参考に適当にインストールします
Docker 起動
sudo service docker start
memo : Homebrew Install
Homebrew を Ubuntu に適当にインストールします
https://docs.brew.sh/Homebrew-on-Linux
fish の場合
vim ~/.config/fish/config.fish
末尾に追記
set -x HOMEBREW_PREFIX /home/linuxbrew/.linuxbrew
set -x HOMEBREW_CELLAR /home/linuxbrew/.linuxbrew/Cellar
set -x HOMEBREW_REPOSITORY /home/linuxbrew/.linuxbrew/Homebrew
set -x PATH /home/linuxbrew/.linuxbrew/bin $PATH
set -x PATH /home/linuxbrew/.linuxbrew/sbin $PATH
set -x MANPATH /home/linuxbrew/.linuxbrew/share/man $MANPATH
set -x INFOPATH /home/linuxbrew/.linuxbrew/share/info $INFOPATH
SAM Init
SAM の Document を参考に、Quick Start を進めていきます。
作業用 dir 作成
mkdir ~/samdir
cd ~/samdir
sam init で初期設定
sam init
1の AWS Quick Start Templates
を選択
> sam init
SAM CLI now collects telemetry to better understand customer needs.
You can OPT OUT and disable telemetry collection by setting the
environment variable SAM_CLI_TELEMETRY=0 in your shell.
Thanks for your help!
Learn More: https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-telemetry.html
Which template source would you like to use?
1 - AWS Quick Start Templates
2 - Custom Template Location
Choice:1
1 の Zip を選択
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
10 の Python を選択
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: 2
Project Name は、hello-world
Project name [sam-app]: hello-world
1の Hello World Example
を選択
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
こんな感じで自動生成されている
> tree hello-world
hello-world
├── README.md
├── __init__.py
├── events
│ └── event.json
├── hello_world
│ ├── __init__.py
│ ├── app.py
│ └── requirements.txt
├── template.yaml
└── tests
├── __init__.py
└── unit
├── __init__.py
└── test_handler.py
4 directories, 10 files
template.yaml の中身はこんな感じ
> cat hello-world/template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
hello-world
Sample SAM Template for hello-world
# 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.6
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
SAM Build
init で生成した環境を Build します
cd hello-world/
sam build
実行例
> sam build
Building codeuri: hello_world/ runtime: python3.6 metadata: {} functions: ['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 Deploy
Build が正常にできたので、SAM をつかって Deploy
sam deploy --guided
CloudFormation の Stack 名入力 : sam-hello-world-stack
Configuring SAM deploy
======================
Looking for config file [samconfig.toml] : Not found
Setting default arguments for 'sam deploy'
=========================================
Stack Name [sam-app]: sam-hello-world-stack
Region このまま Enter
AWS Region [ap-northeast-1]:
変更点を確認するために Yy
#Shows you resources changes to be deployed and require a 'Y' to initiate deploy
Confirm changes before deploy [y/N]:y
必要な IAM Role を自動作成 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
Public に公開する y
HelloWorldFunction may not have authorization defined, Is this okay? [y/N]: y
Config の Save で y
Save arguments to configuration file [Y/n]: y
このまま Enter
SAM configuration file [samconfig.toml]:
Default
SAM configuration environment [default]:
CloudFormation で Stack が作成されている。これは、SAM のメタデータ管理のために、S3 バケットが作成されている
SAM を経由して、CloudFormation の ChangeSet(変更点) が表示されます
Initiating deployment
=====================
HelloWorldFunction may not have authorization defined.
Uploading to sam-hello-world-stack/1b9a60561935a1e52fff89b5860c516a.template 1111 / 1111 (100.00%)
Waiting for changeset to be created..
CloudFormation stack changeset
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Operation LogicalResourceId ResourceType Replacement
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ Add HelloWorldFunctionHelloWorldPermissionProd AWS::Lambda::Permission N/A
+ Add HelloWorldFunctionRole AWS::IAM::Role N/A
+ Add HelloWorldFunction AWS::Lambda::Function N/A
+ Add ServerlessRestApiDeployment47fc2d5f9d AWS::ApiGateway::Deployment N/A
+ Add ServerlessRestApiProdStage AWS::ApiGateway::Stage N/A
+ Add ServerlessRestApi AWS::ApiGateway::RestApi N/A
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Changeset created successfully. arn:aws:cloudformation:ap-northeast-1:539926008561:changeSet/samcli-deploy1613810205/c6116475-2528-40ab-8a50-0555891081b0
これで問題ないことを確認し、y
Deploy this changeset? [y/N]: y
CloudFormation 上で、Resource 群が作成されている
作成完了
Successfully created/updated stack - sam-hello-world-stack in ap-northeast-1
Lambda Function や、API Gateway などが作成されている
CloudFormation Stack の Output には、API Gateway の Endpoint が出力されています
実行すると、Hello World が返ってきます
> curl https://hdz2hgwco1.execute-api.ap-northeast-1.amazonaws.com/Prod/hello/
{"message": "hello world"}
API Gateway のページでも、Endpoint が確認可能
SAM Local Test
SAM CLI には、Docker を使って Lambda のローカル実行環境をシミュレートする機能があります。次の2つのローカル実行方法があります。
- ローカルAPI を生成して実行
- 直接実行
ローカルAPIを生成
ローカルで、API 実行エンドポイントを生成
sam local start-api
実行例。プロンプトは返ってこない
> 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
2021-02-20 21:58:34 * Running on http://127.0.0.1:3000/ (Press CTRL+C to quit)
別の Shell から実行
curl http://127.0.0.1:3000/hello
返ってこないプロンプト上で Build が走る
Invoking app.lambda_handler (python3.6)
Image was not found.
Building image................................................................................................................................................................................................................................................................................................................
Build が完了すると、レスポンスが返ってくる
> curl http://127.0.0.1:3000/hello
{"message": "hello world"}⏎
直接実行
sam local invoke "HelloWorldFunction" -e events/event.json
実行例
> sam local invoke "HelloWorldFunction" -e events/event.json
Invoking app.lambda_handler (python3.6)
Skip pulling image and use local one: amazon/aws-sam-cli-emulation-image-python3.6:rapid-1.18.2.
Mounting /home/sugi/samdir/hello-world/.aws-sam/build/HelloWorldFunction as /var/task:ro,delegated inside runtime container
START RequestId: 45d0fd3b-1f3a-4dbf-8cfc-f15ca9fa6153 Version: $LATEST
END RequestId: 45d0fd3b-1f3a-4dbf-8cfc-f15ca9fa6153
REPORT RequestId: 45d0fd3b-1f3a-4dbf-8cfc-f15ca9fa6153 Init Duration: 0.16 ms Duration: 112.95 ms Billed Duration: 200 ms Memory Size: 128 MB Max Memory Used: 128 MB
{"statusCode": 200, "body": "{\"message\": \"hello world\"}"}⏎
ローカルで新しいプログラムの動作確認
手元のノートPC 上で、プログラミングをしている途中で、すぐに動作確認したいときは、Build をしたあとに、ローカルで実行するコマンドを続けて打てばよいです
Bash 使っているとき
sam build && sam local invoke
Fish 使っているとき
sam build; and sam local invoke
IDE で開発しているときの動作確認
手元のノートPC 上で、プログラミングをしている途中で、すぐに動作確認したいときは、Build をしたあとに、ローカルで実行するコマンドを続けて打てばよいです
Bash 使っているとき
sam build && sam local invoke
Fish 使っているとき
sam build; and sam local invoke
SAM CLI を使って、Lambda Function を更新
ソースコードで、Hello World 2 に変更後、sam deploy を再度行うと、AWS 上で構成された、Lambda Function が更新される
Bash 使っているとき
sam build && sam deploy
Fish 使っているとき
sam build; and sam deploy
実行
> curl https://hdz2hgwco1.execute-api.ap-northeast-1.amazonaws.com/Prod/hello/
{"message": "hello world2"}
参考URL