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
私のところではこのような感じです。
(sls
はserverless
のエイリアスです。)
$ 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編)で作ったディレクトリに置きます。
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をすべて有効にする
- HTTP (API Gateway)
- ハンドラーは
早速デプロイする
ターミナルを開き、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
赤枠で囲ったところに、CloudFormationのスタックに属していることが表示されていますね。
API Gateway
3つ設定したエンドポイントと、CORS用のOPTIONS、計5つが登録されています。
また、このエンドポイントは、↑のLambdaを呼び出すように設定されています。
CloudWatch Logs
ロググループも自動で作られます。
何も実行していないので、ストリームは空です。
まとめ
手動設定とはさよならしましょう!
前職の新人時代、製品のデプロイを任されたときは、手動デプロイしか方法がなかったのですが(今ならもう少し考えます…)、よく設定を忘れたり、ファイルを置き忘れたりして、市場問題と言われて叱責されたことが多々…。
そんなところで神経すり減らすより、使える自動化ツールはどんどん活用しちゃいましょう!