AWS
SAM

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

基本的に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"}}


Random posts

GitHubHomeEnglish