AWS
CloudWatch
lambda
ServerlessFramework

Serverless Frameworkでお手軽サーバーレス(基本編)

Lambdaでお手軽サーバーレス入門の次の記事(とりあえず作ってみる編)(API Gateway設定編)(API Gatewayデプロイ編)(CloudWatch Events編)で、軽くLambda、API Gateway、CloudWatch Eventsについて紹介しました。

問題

  • 関数そのものを作るより設定のほうが手間
  • 設定を手動でするなんてナンセンス

解決策

Serverless Frameworkを使おう!

できること

たくさんありますが、以下のようなことが実現できます。

  • Lambda関数のデプロイ
  • トリガーの設定(API Gateway, CloudWatch Events, SNSなど…)
  • プラグインの使用

前提

Serverless FrameworkはNodeで動くので、以下のツールをインストールしておいてください。

  • Node.js (4.0以上)
  • AWS CLI

インストール・セットアップ

npm install -g serverless

私のところではこのような感じです。
slsserverlessのエイリアスです。)

$ node -v
v8.11.4

$ npm -v
5.6.0

$ sls --version
1.27.3

$ aws --version
aws-cli/1.16.1 Python/3.7.0 Darwin/18.0.0 botocore/1.11.1

インストールが終われば、AWSのアクセスキーを設定します。
(既に設定済みであればパスして問題ありません)

sls config credentials --provider aws --key AWSACCESSKEY --secret AWSSECRETACCESSKEY

定義ファイル

Serverless Frameworkでは、デプロイしたいサービスごとに、定義ファイル serverless.yml を作成する必要があります。

簡単なサンプル

以下のファイルを、Lambdaでお手軽サーバーレス入門(Lambdaのイベント from API Gateway編)で作ったディレクトリに置きます。

image.png

serverless.yml
service: qiita-lambda-apigateway

provider:
  name: aws
  profile: ${opt:profile, 'default'}
  stage: prod
  region: ap-northeast-1
  runtime: python3.6
  role: arn:aws:iam::ACCOUNT_ID:role/service-role/YOUR-ROLE-NAME  # 適切なロール名に置き換えてください!
  timeout: 30
  memorySize: 128
  versionFunctions: false

resources:
  Resources:
    ApiGatewayRestApi:
      Type: AWS::ApiGateway::RestApi
      Properties:
        Name: ${self:service}-${self:provider.stage}

package:
  individually: true

custom:
  prefix: ${self:service}-${self:provider.stage}

functions:
  lambda_function:
    name: ${self:custom.prefix}-lambda_function
    handler: lambda_function.lambda_handler
    events:
      - http:
          integration: lambda-proxy
          path: hello-world
          method: GET
          cors: true
      - http:
          integration: lambda-proxy
          path: hello-world/{id}
          method: GET
          cors: true
      - http:
          integration: lambda-proxy
          path: hello-world
          method: POST
          cors: true

何をするか簡単に解説

  • サービス名は qiita-lambda-apigateway
  • リージョンは東京
  • ランタイムは Python3.6
  • タイムアウトは30秒
  • メモリは128MB確保
  • 関数 lambda_function を定義
    • ハンドラーは lambda_function.lambda_handler
    • イベント定義は3つ
      • HTTP (API Gateway)
        • GET /hello-world
        • GET /hello-world/{id}
        • POST /hello-world
        • CORSをすべて有効にする

早速デプロイする

ターミナルを開き、serverless.ymlのあるディレクトリで、以下のコマンドを実行します。

serverless deploy
# serverless deploy --verbose  # 詳細を見たいとき

このような感じでログが出力されます。

Serverless: Packaging service...
Serverless: Excluding development dependencies...
Serverless: Creating Stack...
Serverless: Checking Stack create progress...
CloudFormation - CREATE_IN_PROGRESS - AWS::CloudFormation::Stack - qiita-lambda-apigateway-prod
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 - qiita-lambda-apigateway-prod
Serverless: Stack create finished...
Serverless: Uploading CloudFormation file to S3...
Serverless: Uploading artifacts...
Serverless: Uploading service .zip file to S3 (6.73 KB)...
Serverless: Validating template...
Serverless: Updating Stack...
Serverless: Checking Stack update progress...
CloudFormation - UPDATE_IN_PROGRESS - AWS::CloudFormation::Stack - qiita-lambda-apigateway-prod
CloudFormation - CREATE_IN_PROGRESS - AWS::Logs::LogGroup - LambdaUnderscorefunctionLogGroup
CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::RestApi - ApiGatewayRestApi
CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::RestApi - ApiGatewayRestApi
CloudFormation - CREATE_IN_PROGRESS - AWS::Logs::LogGroup - LambdaUnderscorefunctionLogGroup
CloudFormation - CREATE_COMPLETE - AWS::ApiGateway::RestApi - ApiGatewayRestApi
CloudFormation - CREATE_COMPLETE - AWS::Logs::LogGroup - LambdaUnderscorefunctionLogGroup
CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::Resource - ApiGatewayResourceHelloDashworld
CloudFormation - CREATE_IN_PROGRESS - AWS::Lambda::Function - LambdaUnderscorefunctionLambdaFunction
CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::Resource - ApiGatewayResourceHelloDashworld
CloudFormation - CREATE_COMPLETE - AWS::ApiGateway::Resource - ApiGatewayResourceHelloDashworld
CloudFormation - CREATE_IN_PROGRESS - AWS::Lambda::Function - LambdaUnderscorefunctionLambdaFunction
CloudFormation - CREATE_COMPLETE - AWS::Lambda::Function - LambdaUnderscorefunctionLambdaFunction
CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::Method - ApiGatewayMethodHelloDashworldOptions
CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::Resource - ApiGatewayResourceHelloDashworldIdVar
CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::Method - ApiGatewayMethodHelloDashworldOptions
CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::Resource - ApiGatewayResourceHelloDashworldIdVar
CloudFormation - CREATE_COMPLETE - AWS::ApiGateway::Resource - ApiGatewayResourceHelloDashworldIdVar
CloudFormation - CREATE_IN_PROGRESS - AWS::Lambda::Permission - LambdaUnderscorefunctionLambdaPermissionApiGateway
CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::Method - ApiGatewayMethodHelloDashworldGet
CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::Method - ApiGatewayMethodHelloDashworldPost
CloudFormation - CREATE_COMPLETE - AWS::ApiGateway::Method - ApiGatewayMethodHelloDashworldOptions
CloudFormation - CREATE_IN_PROGRESS - AWS::Lambda::Permission - LambdaUnderscorefunctionLambdaPermissionApiGateway
CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::Method - ApiGatewayMethodHelloDashworldGet
CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::Method - ApiGatewayMethodHelloDashworldPost
CloudFormation - CREATE_COMPLETE - AWS::ApiGateway::Method - ApiGatewayMethodHelloDashworldGet
CloudFormation - CREATE_COMPLETE - AWS::ApiGateway::Method - ApiGatewayMethodHelloDashworldPost
CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::Method - ApiGatewayMethodHelloDashworldIdVarGet
CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::Method - ApiGatewayMethodHelloDashworldIdVarGet
CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::Method - ApiGatewayMethodHelloDashworldIdVarOptions
CloudFormation - CREATE_COMPLETE - AWS::ApiGateway::Method - ApiGatewayMethodHelloDashworldIdVarGet
CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::Method - ApiGatewayMethodHelloDashworldIdVarOptions
CloudFormation - CREATE_COMPLETE - AWS::ApiGateway::Method - ApiGatewayMethodHelloDashworldIdVarOptions
CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::Deployment - ApiGatewayDeployment1539166300519
CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::Deployment - ApiGatewayDeployment1539166300519
CloudFormation - CREATE_COMPLETE - AWS::ApiGateway::Deployment - ApiGatewayDeployment1539166300519
CloudFormation - CREATE_COMPLETE - AWS::Lambda::Permission - LambdaUnderscorefunctionLambdaPermissionApiGateway
CloudFormation - UPDATE_COMPLETE_CLEANUP_IN_PROGRESS - AWS::CloudFormation::Stack - qiita-lambda-apigateway-prod
CloudFormation - UPDATE_COMPLETE - AWS::CloudFormation::Stack - qiita-lambda-apigateway-prod
Serverless: Stack update finished...
Service Information
service: qiita-lambda-apigateway
stage: prod
region: ap-northeast-1
stack: qiita-lambda-apigateway-prod
api keys:
  None
endpoints:
  GET - https://**********.execute-api.ap-northeast-1.amazonaws.com/prod/hello-world
  GET - https://**********.execute-api.ap-northeast-1.amazonaws.com/prod/hello-world/{id}
  POST - https://**********.execute-api.ap-northeast-1.amazonaws.com/prod/hello-world
functions:
  lambda_function: qiita-lambda-apigateway-prod-lambda_function

Stack Outputs
ServiceEndpoint: https://**********.execute-api.ap-northeast-1.amazonaws.com/prod
ServerlessDeploymentBucketName: qiita-lambda-apigateway-serverlessdeploymentbuck-**********

よく見ると、CloudFormationが動いているようですね。

…はい、Serverless Frameworkは、あの鬼のようにややこしいCloudFormationのテンプレートを作ってくれて、実行してくれるツールです。

確認

それぞれ、コンソールを覗いてみましょう。

Lambda

sls01.png

赤枠で囲ったところに、CloudFormationのスタックに属していることが表示されていますね。

API Gateway

sls02.png

3つ設定したエンドポイントと、CORS用のOPTIONS、計5つが登録されています。
また、このエンドポイントは、↑のLambdaを呼び出すように設定されています。

CloudWatch Logs

sls03.png

ロググループも自動で作られます。
何も実行していないので、ストリームは空です。

まとめ

手動設定とはさよならしましょう!

前職の新人時代、製品のデプロイを任されたときは、手動デプロイしか方法がなかったのですが(今ならもう少し考えます…)、よく設定を忘れたり、ファイルを置き忘れたりして、市場問題と言われて叱責されたことが多々…。

そんなところで神経すり減らすより、使える自動化ツールはどんどん活用しちゃいましょう!