serverless-v1.0.0-rc.1を試してみた(2) – 実際にデプロイしてみる

モバイルアプリサービス部の五十嵐です。

前回は基本的なコマンドを試してみました。今回は実際に作成したLambdaをデプロイするまでを書いていきます。serverlessプロジェクトでの成果物は こちら にあります。

環境

  • serverless 1.0.0-rc.1
  • node.js 4.3.2
  • npm 2.14.12

npmのインストール

serverless v1.0.0-rcにはLambdaが参照できる環境変数を設定する機能がまだ無いので、configというnpmを使いました。configは、設定ファイルのJSONを外出しして簡単に読み込めるライブラリです。

npm init コマンドで package.json を作った後に、 npm install <パッケージ名> --save コマンドを実行します。package.json の dependencies に書き込みたいので --save オプションを付けますnpmはデプロイパッケージに含めるので必ずローカルにインストールします。

# npm init --yes
# npm install config --save
npm WARN package.json sample@1.0.0 No description
npm WARN package.json sample@1.0.0 No repository field.
npm WARN package.json sample@1.0.0 No README data
config@1.21.0 node_modules/config
└── json5@0.4.0

以下はconfigの設定ファイルの設定例です。本物の設定ファイルにはKMSのトークンなどが書かれているため、GitHubに登録されないよう.gitignoreに追加しておきます。また合わせてnode_modulesディレクトリも.gitignoreに追加しておきます。

# ll config
total 16
-rw-r--r--  1 bisque33  staff   333B  9 10 07:15 default.json # <-こっちが本物
-rw-r--r--  1 bisque33  staff   139B  9 10 07:17 default_sample.json

# config/default_sample.json                                                                                                                     {
    "kmsEncryptedToken": "<kmsEncryptedToken>",
    "invokeFunctionARN": "arn:aws:lambda:<region>:<accountId>:function:<functionName>"
}

# echo config/default.json >> .gitignore
# echo node_modules >> .gitignore

IAMの設定

IAMの設定を行います。このLambdaが必要とするAWSの権限は以下の2つです。

  • 他のLambdaをInvokeする。
  • KMSに暗号化してあるSlackのアクセストークンを取得する。

serverlessの設定ファイルに以下のように記述することで、必要な権限を持ったIAMが作成されます。書き方はIAMのJSONをほぼそのままYAMLにしたような形式です。

provider:
...
# you can add statements to the Lambda function's IAM Role here
  iamRoleStatements:
    - Effect: "Allow"
      Action:
        - "lambda:InvokeFunction"
      Resource: "arn:aws:lambda:ap-northeast-1:*:function:*"
    - Effect: "Allow"
      Action:
        - "kms:Decrypt"
      Resource: "*"

Lambdaの設定

Lambda自体の設定は、serverlessの設定ファイルのfunctions以下に記述します。今回作成するLambdaは1つですが、複数のLambdaの設定を書くことも可能です。slashCommandsがLambdaの名前、handlerエントリーポイントの関数名です。トリガーを設定しないのであればここまでで良いです。

eventsはトリガーの設定です。今回はAPI Gatewayから呼び出されるようにしたいので、http以下の属性を書いていきます。書き方は serverless/01-apigateway.md を参照します。

functions:
  slashCommands:
    handler: handler.slashCommands
    events:
      - http:
          path: slack/slash-commands
          method: post
          request:
            template:
              application/x-www-form-urlencoded: '{ "body": $input.json("$") }'
            passThrough: NEVER

API Gatewayのリソースを設定する方法も一応載っているのですが、深みに嵌りそうなので今回は手動で作成しました。

serverless-1.0.0-rc-review-2-1

Lambdaの実装

serverlessでプロジェクトを作成すると handler.js というファイルが作成されます。その中にエントリーポイントとなる関数が用意されていますので、その中に実際の処理を書いていきます。実装コードの module.exports.XXX と先ほどの設定に書いたLambdaの設定の functions:<functionの名前>:handler:<ファイル名>.XXX のXXXの部分を一致させます。

// You can add more handlers here, and reference them in serverless.yml
module.exports.slashCommands = (event, context, callback) => {
    // ここに処理を書く
};

デプロイパッケージの作成

デプロイパッケージの設定をpackageに記述します。includeが明示的に追加したい項目、excludeがその逆です。基本的にはプロジェクト配下の全てがパッケージ化されますのでincludeは書かなくても問題ないかと思います。

# you can add packaging information here
package:
  # include:
  exclude:
   - config/default_sample.json
   - event.json
#  artifact: my-service-code.zip

デプロイ

AWS上にリソースを作成します。 deploy コマンドに -v オプションを付けることで、CloudFormationのログをコンソールに出力することができます。ログを見ていると何が行われているか一目瞭然です。

# sls deploy -v
Serverless: Creating Stack...
Serverless: Checking Stack create progress...
CloudFormation - CREATE_IN_PROGRESS - AWS::CloudFormation::Stack - slack-prd
CloudFormation - CREATE_IN_PROGRESS - AWS::S3::Bucket - ServerlessDeploymentBucket
CloudFormation - CREATE_IN_PROGRESS - AWS::S3::Bucket - ServerlessDeploymentBucket
CloudFormation - CREATE_COMPLETE - AWS::S3::Bucket - ServerlessDeploymentBucket
CloudFormation - CREATE_COMPLETE - AWS::CloudFormation::Stack - slack-prd
Serverless: Stack create finished...
Serverless: Packaging service...
Serverless: Uploading CloudFormation file to S3...
Serverless: Uploading service .zip file to S3...
Serverless: Updating Stack...
Serverless: Checking Stack update progress...
CloudFormation - UPDATE_IN_PROGRESS - AWS::CloudFormation::Stack - slack-prd
CloudFormation - CREATE_IN_PROGRESS - AWS::IAM::Role - IamRoleLambdaExecution
CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::RestApi - ApiGatewayRestApi
CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::RestApi - ApiGatewayRestApi
CloudFormation - CREATE_COMPLETE - AWS::ApiGateway::RestApi - ApiGatewayRestApi
CloudFormation - CREATE_IN_PROGRESS - AWS::IAM::Role - IamRoleLambdaExecution
CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::Resource - ApiGatewayResourceSlack
CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::Resource - ApiGatewayResourceSlack
CloudFormation - CREATE_COMPLETE - AWS::ApiGateway::Resource - ApiGatewayResourceSlack
CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::Resource - ApiGatewayResourceSlackSlashcommands
CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::Resource - ApiGatewayResourceSlackSlashcommands
CloudFormation - CREATE_COMPLETE - AWS::ApiGateway::Resource - ApiGatewayResourceSlackSlashcommands
CloudFormation - CREATE_COMPLETE - AWS::IAM::Role - IamRoleLambdaExecution
CloudFormation - CREATE_IN_PROGRESS - AWS::IAM::Policy - IamPolicyLambdaExecution
CloudFormation - CREATE_IN_PROGRESS - AWS::Lambda::Function - SlashCommandsLambdaFunction
CloudFormation - CREATE_IN_PROGRESS - AWS::IAM::Policy - IamPolicyLambdaExecution
CloudFormation - CREATE_IN_PROGRESS - AWS::Lambda::Function - SlashCommandsLambdaFunction
CloudFormation - CREATE_COMPLETE - AWS::IAM::Policy - IamPolicyLambdaExecution
CloudFormation - CREATE_COMPLETE - AWS::Lambda::Function - SlashCommandsLambdaFunction
CloudFormation - CREATE_IN_PROGRESS - AWS::Lambda::Permission - SlashCommandsLambdaPermissionApiGateway
CloudFormation - CREATE_IN_PROGRESS - AWS::Lambda::Permission - SlashCommandsLambdaPermissionApiGateway
CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::Method - ApiGatewayMethodSlackSlashcommandsPost
CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::Method - ApiGatewayMethodSlackSlashcommandsPost
CloudFormation - CREATE_COMPLETE - AWS::ApiGateway::Method - ApiGatewayMethodSlackSlashcommandsPost
CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::Deployment - ApiGatewayDeployment1473542643677
CloudFormation - CREATE_COMPLETE - AWS::Lambda::Permission - SlashCommandsLambdaPermissionApiGateway
CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::Deployment - ApiGatewayDeployment1473542643677
CloudFormation - CREATE_COMPLETE - AWS::ApiGateway::Deployment - ApiGatewayDeployment1473542643677
CloudFormation - UPDATE_COMPLETE_CLEANUP_IN_PROGRESS - AWS::CloudFormation::Stack - slack-prd
CloudFormation - UPDATE_COMPLETE - AWS::CloudFormation::Stack - slack-prd
Serverless: Stack update finished...

Service Information
service: slack
stage: prd
region: ap-northeast-1
endpoints:
  POST - https://xxx.execute-api.ap-northeast-1.amazonaws.com/prd/slack/slash-commands
functions:
  slack-prd-slashCommands: arn:aws:lambda:ap-northeast-1:XXX:function:slack-prd-slashCommands

気になった点としては、デプロイ後動作は問題ないのですが、Lambdaのトリガーに設定が表示されませんでした。この機能はまだ使わないほうがいいかもしれません。

serverless-1.0.0-rc-review-2-2

まとめ

Lambdaの開発に必要な一連の操作がほぼすべてserverlessでできました。 API Gatewayまわりの機能は怪しいのでv1.0.0がリリースされたらもう一度試してみたいと思います。フォーラムの動きがとても活発なのできっとすぐに修正されると期待しています。