AWS
lambda
APIGateway
serverless
ServerlessFramework

Serverless Frameworkの使い方まとめ


概要

スクリーンショット 2016-10-17 0.53.48.png

Serverless Framework はServerless Applicationを構成管理デプロイするためのツールです。この記事ではその使い方をまとめています。


インストール


Node.jsのインストール

ServerlessはNode.jsで作られたCLIツールです。

なので、あなたのマシンにNode.jsをインストールする必要があります。Node.jsの公式サイトからあなたのPCにNode.jsをインストールしましょう。ServerlessはNode.jsのv4以上が必要となります。


Serverlessのインストール

Serverlessはnpmのパッケージとして公開されています。ターミナルを開いて、npm install -g serverlessでインストールが完了します。

正しくインストールされているかは、serverless --versionにて確認しましょう。以下のようにバージョンが表示されれば正しくインストールされています。

$ serverless --version

1.28.0


プロバイダーアカウントのセットアップ

プロバイダーのアカウントをセットアップします。プロバイダーとは、要はどのクラウドサービスを使用してServerlessを動かすかということです。AWS, GCP, Azure, IBM Cloudなど様々なクラウドプロバイダーに対応しています。

ここではAWSにスポットを当てて解説します。

AWS account Setup

ここにAWSアカウントのセットアップ方法が書いていますが、要は以下を実施すればOKです。


  • Serverless用のIAMユーザを発行

  • IAMユーザにAdministratorAccessの管理ポリシーを与える

基本的にはこのアカウントを使って、ServerlessのデプロイやLambdaファンクションのローカルからの実行を行います。

また、IAMロールを制限したい場合は、serverless-puresec-cliNarrowing the Serverless IAM Deployment Policyを参考に独自でセットアップしましょう。


サービスの作成

Serverlessはサービスという単位で実行環境を作っていきます。

まずはサービスを開設してみましょう。

AWSをプロバイダーとしてNode.jsでサービスを開設する場合は以下の手順になります。

$ serverless create --template aws-nodejs --name my-special-service --path my-special-service

すると、my-special-serviceのディレクトリが作られ、その配下に以下のファイルが出来ているはずです。

これでサービスの作成は完了です。


  • serverless.yml

  • handler.js

  • event.json

また、サービス用のテンプレートですが、以下の言語用のテンプレートが用意されています。


  • aws-nodejs

  • aws-nodejs-typescript

  • aws-nodejs-ecma-script

  • aws-python

  • aws-python3

  • aws-kotlin-jvm-maven

  • aws-kotlin-jvm-gradle

  • aws-kotlin-nodejs-gradle

  • aws-groovy-gradle

  • aws-java-maven

  • aws-java-gradle

  • aws-scala-sbt

  • aws-csharp

  • aws-fsharp

どの言語でLambdaを動かしたいかによってテンプレートを変更してあげましょう


serverless.yml

serverless.ymlは各サービス全体の設定を行うためのファイルです。

AWSでは、以下のような設定が可能です。


  • サービス内のLambdaファンクション群の設定

  • Lambdaに設定されるIAMロールの設定

  • デプロイ時にどのファイル/ディレクトリを含めるか/含めないかの設定

  • 使用するプラグインの定義

  • Lambdaファンクションごとのトリガーとなるイベントの定義

  • Lambdaファンクションが他のAWSリソースを連携する場合は、そのIAMを含めた定義

まずは、serverless.ymlの設定をしてあげましょう。もろもろサービスを実行するために必要な設定はすべてこのファイルで行います。


handler.js

これはファンクションを定義するためのスケルトンとして生成されるファイルです。これを参考に実際のファンクションのプログラムを作っていきます。


event.json

ServerlessのCLIでファンクションを実行する際に入力値となるデータを定義するファイルです。Lambdaファンクション内でevent変数に展開されます。


Githubに上がった既存のサービスをインポートする場合

既にGithubに上がっている既存サービスの開発を行う場合は、そのままローカルにインポートしてServerlessをセットアップしたいと思います。その際はserverless install -u [GITHUB URL OF SERVICE]でインポート可能です。


サービスのデプロイ

次に作ったサービスをプロバイダー上へデプロイしましょう。

serverless deploy -vでデプロイは開始されます。-vオプションを付けるとverboseというモードでデプロイが実施され、途中経過がターミナル上で確認できます。

また、Serverlessのデプロイにはstageという概念が導入されています。いわゆる本番環境とテスト環境といった環境をstageという単位で切り分けています。

Serverlessはデフォルトで、devというステージかつus-east-1リージョンにデプロイされるようになっています。

これを変更したければ serverless.ymlに以下のように設定します。


serverless.yml

service: service-name

provider:
name: aws
stage: beta
region: us-west-2

これでbetaステージのus-west-2リージョンにデプロイされるようになります。


serverless.ymlで定義したものと異なるサービス及びリージョンへのデプロイ

また、deployコマンドはデプロイするstageやregionを引数で指定することも出来ます。

productionステージのap-northeast-1リージョンに上げたければ、serverless deploy --stage production --region ap-northeast-1とすれば、引数通りの指定でデプロイが実施されます。


ファンクション単位のデプロイ

serverless deploy -vはサービス全体のデプロイを行います。ファンクションの一部を修正したなどのケースで、サービス全体がデプロイされるのは大変です。

Serverlessはファンクション単位でのデプロイもserverless deploy function -f <yourfunction>にて可能です。


ファンクションの実行

デプロイしたファンクションを実行してみましょう。


helloファンクションの実行

サービス作成時にhandler.jsとして作成されるhelloファンクションを実行する場合を考えてみましょう。serverless invoke --function hello -p event.jsonで実行できます。


実行時にログを表示させる

ファンクションの実行時にログを見たいを思います。Lambdaの実行時にCloudwatchのログが同時に見れれば便利ですよね? Serverlessはそれにも対応しています。serverless invoke --function Yourfunction -p event.json --logでlogオプションを付与するとこで以下の通りログが確認できます

$ serverless invoke --function function1 -p event.json --log

{
"message": "Go Serverless v1.0! Your function executed successfully!",
"event": {
"key3": "value3",
"key2": "value2",
"key1": "value1"
}
}
--------------------------------------------------------------------
START RequestId: 722d0f98-93b8-11e6-97dc-df560106cc0b Version: $LATEST
END RequestId: 722d0f98-93b8-11e6-97dc-df560106cc0b
REPORT RequestId: 722d0f98-93b8-11e6-97dc-df560106cc0b Duration: 6.53 ms Billed Duration: 100 ms Memory Size: 1024 MB Max Memory Used: 34 MB


各ファンクションのログの履歴を確認する

後からファンクション毎のログを確認する場合はserverless logs --function Yourfunctionというコマンドを実行します。

すると以下の通りログがリストで表示されます。

$ serverless logs --function function1

START RequestId: 722d0f98-93b8-11e6-97dc-df560106cc0b Version: $LATEST
END RequestId: 722d0f98-93b8-11e6-97dc-df560106cc0b
REPORT RequestId: 722d0f98-93b8-11e6-97dc-df560106cc0b Duration: 6.53 ms Billed Duration: 100 ms Memory Size: 1024 MB Max Memory Used: 34 MB

START RequestId: 263c0816-93b9-11e6-bebd-e1e068167f38 Version: $LATEST


他のAWSリソースにIAMでポリシーを設定する

実行時に他のAWSリソースを参照する場合は、serverless.yml内のiamRoleStatementsを使用して必要なポリシーを設定します。

DynamoDBのexampleテーブルに対する全権限を付与する場合は以下のような設定をします。


serverless.yml

iamRoleStatements:

- Effect: "Allow"
Action:
- "dynamodb:*"
Resource:
- "arn:aws:dynamodb:us-east-1:*:table/example"


イベントトリガーの設定

Serverless Frameworkはファンクションにイベントを設定することでイベント駆動のアーキテクチャを実現することをサポートしています。

イベントにはHTTPリクエスト(AWSではAPI Gateway)やS3 bucket、スケジュールイベントなど、設定を行うことが出来ます。

今回は、AWS Gatewayを使用したhttpイベントの設定を例にあげます。


HTTP eventを追加する

greetというパスでhttpリクエストを受けた場合にhelloファンクションを実行させたい場合は以下のようにserverless.ymlを設定します。


serverless.yml

functions:

hello:
handler: handler.hello
events:
- http: GET greet

この設定を行い。serverless deployを実行してデプロイに成功すれば以下のようなEndpointがターミナル上に表示されるはずです。

endpoints:

GET - https://dxaynpuzd4.execute-api.us-east-1.amazonaws.com/dev/greet

これに対して実際にリクエストを送ってみるとLambdaで定義した返り値が返ってくるはずです。

$ curl https://dxaynpuzd4.execute-api.us-east-1.amazonaws.com/dev/greet

https://serverless.com/framework/docs/providers/aws/events/apigateway/

API Gatewayを使ったhttpイベントは様々なパラメータを設定することが可能です。詳しくは公式のドキュメントを確認してみてください。個人的にはlambda-proxyの機能が、手軽にLambdaからステータスコードの設定が出来て便利だと感じています。

また、現段階でAWSをプロバイダーとして以下のイベントが設定可能です。

- API Gatewayを使用したhttpイベント

- S3の操作をトリガーとしたイベント

- Lambdaのスケジュールイベント

- SNSの通知をトリガーとしたイベント

- DynamoDB / Kinesis Streamsイベント

- Allexa Skill / Alexa Smart Homeイベント

- AWS IoTイベント

- CloudWatch Event

- CloudWatch Log

- Cognito User Poolのトリガーファンクション

- SQS

https://serverless.com/framework/docs/providers/aws/events/


Serverlessで使用できる変数

Serverless Frameworkはserverless.yml内で変数を定義することで柔軟なサービス設定が可能となっています。


環境変数を参照する

環境変数を参照する場合は${env:SOME_VAR}というシンタックスをserverless.ymlに記述します。以下がその例です。


serverless.yml

service: new-service

provider: aws
functions:
hello:
name: ${env:FUNC_PREFIX}-hello
handler: handler.hello
world:
name: ${env:FUNC_PREFIX}-world
handler: handler.world

この例ではあなたのPC内のFUNC_PREFIXという環境変数を参照するようになりました。


CLIオプションを参照する

serverlessコマンド実行時のオプションを参照させたい場合は${opt:SOME_VAR}というシンタックスをserverless.ymlに記述します。以下がその例です。


serverless.yml

service: new-service

provider: aws
functions:
hello:
name: ${opt:stage}-hello
handler: handler.hello
world:
name: ${opt:stage}-world
handler: handler.world

serverless deploy --stage devとした場合は、${opt:stage}はdevが返ります。また、serverless deploy --stage productionとした場合は、productionが返ります。


自身で定義した変数を参照する

serverless.yml内で自身で定義した変数を参照させることも出来ます。${self:someProperty}というシンタックスで定義可能です。以下がその例です。


serverless.yml

service: new-service

provider: aws
custom:
globalSchedule: rate(10 minutes)

functions:
hello:
handler: handler.hello
events:
- schedule: ${self:custom.globalSchedule}
world:
handler: handler.world
events:
- schedule: ${self:custom.globalSchedule}



他のファイルで定義した変数を参照する

serverless.ymlとは別で定義したファイルを読み込んで、その変数を参照することも出来ます。${file(../myFile.yml):someProperty}というシンタックスでserverless.ymlに定義してください。以下がその例になります。


myCustomFile.yml

globalSchedule: rate(10 minutes)



serverless.yml

service: new-service

provider: aws
custom: ${file(../myCustomFile.yml)} # You can reference the entire file
functions:
hello:
handler: handler.hello
events:
- schedule: ${file(../myCustomFile.yml):globalSchedule} # Or you can reference a specific property
world:
handler: handler.world
events:
- schedule: ${self:custom.globalSchedule} # This would also work in this case


変数のネスト

以下のように変数をネストさせることも可能です。


serverless.yml

service: new-service

provider: aws
custom:
myFlexibleArn: ${env:${opt:stage}_arn}

functions:
hello:
handler: handler.hello



変数の上書き

以下のような記述を例にあげます。


serverless.yml

service: new-service

provider:
name: aws
stage: dev
custom:
myStage: ${opt:stage, self:provider.stage}

functions:
hello:
handler: handler.hello


この場合にserverless deployを発行したとします。この時、opt:stageは定義されていないため、self:provider.stageに定義されているdevが参照されます。

serverless deploy --stage productionが指定されている場合は、opt:stageが定義されているためopt:stageが優先して参照されます。


サービスの削除

あなたのつくったサービス内で、serverless remove -vを実行してください。これでサービスがプロバイダー上から削除されます。


Tips


アクセスキーなど見せたくない情報をserverless.ymlで扱う

SSM秘匿パラメータの機能を使いましょう

https://serverless.com/framework/docs/providers/aws/guide/variables/#reference-variables-using-the-ssm-parameter-store


日本語フォーラム

https://github.com/serverless-japan/forum

日本語のフォーラムもGitHub上で公開してますので、もし不明点などあればこちらにissueを立ててみてください