AWS SAMでアプリをデプロイする。ついでにSAM Localでローカルテストなどもしてみる

基本的にAWS Lambda等のデプロイはServerless Frameworkを使うことが多いのですが、Swaggerが使えるなどのメリットを感じるところが増えてきたので、SAMについても触ってみました。 スタックを […]

広告ここから
広告ここまで

目次

    基本的にAWS Lambda等のデプロイはServerless Frameworkを使うことが多いのですが、Swaggerが使えるなどのメリットを感じるところが増えてきたので、SAMについても触ってみました。

    スタックを作成

    以下のような形でLambdaをデプロイできます。

    AWSTemplateFormatVersion: '2010-09-09'
    Transform: AWS::Serverless-2016-10-31
    Description: 'Example SAM stack'
    Resources:
      HelloSAM:
        Type: AWS::Serverless::Function
        Properties:
          Handler: index.handler
          Runtime: nodejs6.10

    Lambdaのソースコードは、受け取ったイベントをそのまま返す形にしておきます。

    index.js

    const handler = (event, context, callback) => {
      console.log(event) // eslint-disable-line no-console
      return callback(null, {
        event
      })
    }
    
    module.exports.handler = handler

    デプロイ先バケットの作成

    $ aws s3 mb s3://YOUR_ORIGINAL_BUCKET_NAME --region us-east-1
    make_bucket: YOUR_ORIGINAL_BUCKET_NAME
    
    # S3バケット名はグローバルなので、既に誰かが使っている名前は利用できない
    $ aws s3 mb s3://sam-test --region us-east-1
    make_bucket failed: s3://sam-test An error occurred (BucketAlreadyExists) when calling the CreateBucket operation: The requested bucket name is not available. The bucket namespace is shared by all users of the system. Please select a different name and try again.

    パッケージの作成

    $ aws cloudformation package --template-file ./sam.yml --output-template-file sam-output.yml --s3-bucket YOUR_ORIGINAL_BUCKET_NAME
    Uploading to 58d19799e9bd53029cc4a5fecf6e1370  13277 / 13277.0  (100.00%)
    Successfully packaged artifacts and wrote output template to file sam-output.yml.
    Execute the following command to deploy the packaged template
    aws cloudformation deploy --template-file /Users/develop/sam/example/sam-output.yml --stack-name <YOUR STACK NAME>

    “Uploading to 58d19799e9bd53029cc4a5fecf6e1370″と表示されている名前と同じものがS3の該当バケットにアップロードされている。

    AWSへのデプロイ

    $ aws cloudformation deploy --template-file ./sam-output.yml --stack-name hello-sam

    たまにこうなる

    Failed to create the changeset: Waiter ChangeSetCreateComplete failed: Waiter encountered a terminal failure state Status: FAILED. Reason: Requires capabilities : [CAPABILITY_IAM]

    --capabilities CAPABILITY_IAMをつければOK

    デプロイがこける場合

    たまにデプロイがこけることがあります。

    $ aws cloudformation deploy --template-file ./sam-output.yml --stack-name hello-sam --capabilities CAPABILITY_IAM
    Waiting for changeset to be created..
    Waiting for stack create/update to complete
    
    Failed to create/update the stack. Run the following command
    to fetch the list of events leading up to the failure
    aws cloudformation describe-stack-events --stack-name hello-sam

    aws cloudformation describe-stack-eventsで原因調べろ」ということみたいですね。jqを使ってサクッとこけたときのメッセージだけ拾いましょう。

    $ aws cloudformation describe-stack-events --stack-name hello-sam | jq '.StackEvents[] | select(.ResourceStatus == "CREATE_FAILED") | .ResourceStatusReason' -r
    Error occurred while GetObject. S3 Error Code: PermanentRedirect. S3 Error Message: The bucket is in this region: us-east-1. Please use this region to retry the request
    

    S3のバケットとCloudFormationのリージョンが一致していないみたいです。

    ということで、aws cloudformation deploy--region us-east-1を追加してリトライしてみます。

    $ aws cloudformation deploy --template-file ./sam-output.yml --stack-name hello-sam --capabilities CAPABILITY_IAM
    Waiting for changeset to be created..
    Waiting for stack create/update to complete
    Successfully created/updated stack - hello-sam

    成功しました。aws cloudformation describe-stacksでも、情報がとれています。

    $ aws cloudformation describe-stacks --stack-name hello-sam --region us-east-1 | jq .
    {
      "Stacks": [
        {
          "StackId": "arn:aws:cloudformation:us-east-1:99999:stack/hello-sam/xxxx-xxxx-xxxx-xxxx-xxxx",
          "Description": "Example SAM stack",
          "Tags": [],
          "CreationTime": "2018-05-08T00:25:41.478Z",
          "Capabilities": [
            "CAPABILITY_IAM"
          ],
          "StackName": "hello-sam",
          "NotificationARNs": [],
          "StackStatus": "CREATE_COMPLETE",
          "DisableRollback": false,
          "ChangeSetId": "arn:aws:cloudformation:us-east-1:999999:changeSet/awscli-cloudformation-package-deploy-1525739139/xxxx-xxxx-xxxx-xxxx-xxxx",
          "LastUpdatedTime": "2018-05-08T00:25:53.008Z"
        }
      ]
    }
    

    SAMで構築したアプリをローカルで実行する

    デプロイして確認だと少し時間がかかるので、ローカルで検証しましょう。SAM LocalというツールがAWSから提供されています。2018/05/06時点ではまだβ版ですが、ローカルで軽く試す程度ならまぁ大丈夫でしょう。

    $ npm i -g aws-sam-local
    $ sam --version
    sam version 0.2.11

    YAMLファイルはtemplate.yml

    SAM Localを使うには、スタック情報がtemplate.ymlに記述されている必要があります。他のファイル名だと、エラーになる様子でした。

    $ sam local invoke HelloSAM
    2018/05/07 23:21:02 Failed to parse template: open template.yml: no such file or directory

    eventパラメータファイルを用意する

    event.jsonなどでファイルを用意しましょう。

    {
      "hello": "world"
    }

    実行する

    sam local invoke FUNCTION_NAMEで実行できます。Dockerイメージを落としてくるため、初回は時間がかかります。

    $ sam local invoke HelloSAM --event ./event.json 
    2018/05/07 23:26:31 Successfully parsed template.yml
    2018/05/07 23:26:31 Connected to Docker 1.37
    2018/05/07 23:26:31 Fetching lambci/lambda:nodejs6.10 image for nodejs6.10 runtime...
    nodejs6.10: Pulling from lambci/lambda
    Digest: sha256:56205b1ec69e0fa6c32e9658d94ef6f3f5ec08b2d60876deefcbbd72fc8cb12f
    Status: Image is up to date for lambci/lambda:nodejs6.10
    2018/05/07 23:26:36 Invoking index.handler (nodejs6.10)
    2018/05/07 23:26:36 Mounting /Users/develop/sam/example as /var/task:ro inside runtime container
    START RequestId: 3e7cfb67-c2d0-1295-9e38-257f28a25ced Version: $LATEST
    2018-05-07T14:27:04.155Z	3e7cfb67-c2d0-1295-9e38-257f28a25ced	{ hello: 'world' }
    END RequestId: 3e7cfb67-c2d0-1295-9e38-257f28a25ced
    REPORT RequestId: 3e7cfb67-c2d0-1295-9e38-257f28a25ced	Duration: 36.54 ms	Billed Duration: 100 ms	Memory Size: 128 MB	Max Memory Used: 29 MB	
    
    {"event":{"hello":"world"}}

    広告ここから
    広告ここまで
    Home
    Search
    Bookmark