LoginSignup
12
8

More than 3 years have passed since last update.

AWS SAM を使って、Lambda のローカル実行環境を試してみる

Last updated at Posted at 2021-02-20

はじめに

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 バケットが作成されている

image-20210220173809555.png

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 群が作成されている

image-20210220174037338.png

作成完了

Successfully created/updated stack - sam-hello-world-stack in ap-northeast-1

image-20210220174138660.png

Lambda Function や、API Gateway などが作成されている

image-20210220174204731.png

CloudFormation Stack の Output には、API Gateway の Endpoint が出力されています

image-20210220192910787.png

実行すると、Hello World が返ってきます

> curl https://hdz2hgwco1.execute-api.ap-northeast-1.amazonaws.com/Prod/hello/
{"message": "hello world"}

API Gateway のページでも、Endpoint が確認可能

image-20210220211832062.png

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

12
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
8