Serverless FrameworkでStep Functionsを扱ってみる
この記事はServerless Advent Calendar 2017の24日目に遅刻した記事です。 AWS Step Functions AWS Lambda 1つで完了できないようなタスク・ワークフローをいい感じに […]
目次
この記事はServerless Advent Calendar 2017の24日目に遅刻した記事です。
AWS Step Functions
AWS Lambda 1つで完了できないようなタスク・ワークフローをいい感じに処理できるようにするやつ(という適当な認識)なAWS Step Functions。
使ってみたいなと思いつつなかなか使う機会がなかったので、これを機に触ってみました。
GUIで設定はしたくない
チュートリアルなどは基本的にGUIでポチポチやるスタイルですが、terraformやCloudFormation、Serverless Frameworkに慣れてくるとコードで定義したくなります。
ということで堀家さんのプラグイン、Serverless Step FunctionsをServerless Frameworkに入れて立ち上げるようにします。
プロジェクトのセットアップ
とりあえずServerless Frameworkを使ったプロジェクトでやるいつもの手順。
$ serverless create -t aws-nodejs -p step-functions
Serverless: Generating boilerplate...
Serverless: Generating boilerplate in "/Users/dc_hideokamoto/develop/node/sls/step-functions"
_______ __
| _ .-----.----.--.--.-----.----| .-----.-----.-----.
| |___| -__| _| | | -__| _| | -__|__ --|__ --|
|____ |_____|__| \___/|_____|__| |__|_____|_____|_____|
| | | The Serverless Application Framework
| | serverless.com, v1.21.1
-------'
Serverless: Successfully generated boilerplate for template: "aws-nodejs"
$ git init && npm init -y
Initialized empty Git repository in /node/sls/step-functions/.git/
Wrote to /node/sls/step-functions/package.json:
{
"name": "step-functions",
"version": "1.0.0",
"description": "",
"main": "handler.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
Serverless Step Functionsプラグインのインストール
Serverless Frameworkのプラグインとして配布されていますので、インストールとセットアップを進めます。
$ npm install --save-dev serverless-step-functions
serverless.yml
にもプラグインを使用することを明記しましょう。
service: sls-step-functions-example
provider:
name: aws
runtime: nodejs6.10
functions:
hello:
handler: handler.hello
plugins:
- serverless-step-functions
これで準備OKです。
プロジェクトをデプロイする
ドキュメントを見る限り、StateMachineの定義でLambdaのARNが必要になる様子です。
serverless.ymlの中で値を引き回す方法があるのかもですが、ちょっと調べきれてないので今回は一旦Lambdaを先にデプロイして決めうちで書くやり方をとります。
$ sls deploy
Serverless: Packaging service...
Serverless: Excluding development dependencies...
Serverless: Creating Stack...
Serverless: Checking Stack create progress...
.....
Serverless: Stack create finished...
Serverless: Uploading CloudFormation file to S3...
Serverless: Uploading artifacts...
Serverless: Uploading service .zip file to S3 (3.49 KB)...
Serverless: Validating template...
Serverless: Updating Stack...
Serverless: Checking Stack update progress...
..................
Serverless: Stack update finished...
Service Information
service: sls-step-functions-example
stage: dev
region: us-east-1
stack: sls-step-functions-example-dev
api keys:
None
endpoints:
None
functions:
hello: sls-step-functions-example-dev-hello
Serverless StepFunctions OutPuts
endpoints:
ちゃんと動作してくれています。
$ sls invoke -f hello
{
"statusCode": 200,
"body": "{\"message\":\"Go Serverless v1.0! Your function executed successfully!\",\"input\":{}}"
}
LambdaのARNはAWS-CLIからとりました。
$ aws lambda list-functions | grep sls-step-functions-example-dev-hello
"FunctionName": "sls-step-functions-example-dev-hello",
"FunctionArn": "arn:aws:lambda:us-east-1:9999999999:function:sls-step-functions-example-dev-hello",
FunctionArn
の値を控えたら、serverless.yml
に以下の項目を追加します。
stepFunctions:
stateMachines:
hellostepfunc1:
name: myStateMachine
definition:
Comment: "A Hello World example of the Amazon States Language using an AWS Lambda Function"
StartAt: HelloWorld1
States:
HelloWorld1:
Type: Task
Resource: arn:aws:lambda:#{AWS::Region}:#{AWS::AccountId}:function:${self:service}-${opt:stage}-hello
End: true
この状態でデプロイすると、最初のStep Functionsが作成されます。
$ sls deploy
Serverless: Packaging service...
Serverless: Excluding development dependencies...
Serverless: Uploading CloudFormation file to S3...
Serverless: Uploading artifacts...
Serverless: Uploading service .zip file to S3 (3.49 KB)...
Serverless: Validating template...
Serverless: Updating Stack...
Serverless: Checking Stack update progress...
............
Serverless: Stack update finished...
Service Information
service: sls-step-functions-example
stage: dev
region: us-east-1
stack: sls-step-functions-example-dev
api keys:
None
endpoints:
None
functions:
hello: sls-step-functions-example-dev-hello
Serverless StepFunctions OutPuts
endpoints:
State Machineを追加したりする
これだけでは普通のLambdaでええやんって話になるので、Step Functionsっぽいワークフローにしてみます。
2つめのLambdaを追加する
handler.js
にhello()
と違うメッセージを返す関数を追加します。
ワークフローの中で違うLambdaをよんだりするテストをするために使います。
'use strict';
module.exports.hello = (event, context, callback) => {
const response = {
statusCode: 200,
body: JSON.stringify({
message: 'Go Serverless v1.0! Your function executed successfully!',
input: event,
}),
};
callback(null, response);
};
module.exports.final = (event, context, callback) => {
const response = {
statusCode: 200,
body: JSON.stringify({
message: 'Passed final states',
input: event,
}),
};
callback(null, response);
};
serverless.yml
の更新
追加した関数をLambdaにデプロイできるようにします。
functions:
hello:
handler: handler.hello
final:
handler: handler.final
stateMachineはこんな感じにしてみました。
stepFunctions:
stateMachines:
hellostepfunc1:
name: myStateMachine
definition:
Comment: "A Hello World example of the Amazon States Language using an AWS Lambda Function"
StartAt: HelloWorld1
States:
HelloWorld1:
Type: Task
Resource: "arn:aws:lambda:us-east-1:99999:function:sls-step-functions-example-dev-hello"
Next: waitUsingSeconds
Retry:
- ErrorEquals:
- HandledError
IntervalSeconds: 1
MaxAttempts: 2
BackoffRate: 2
waitUsingSeconds:
Type: Wait
Seconds: 10
Next: Parallel
Parallel:
Type: Parallel
Next: FinalState
Branches:
- StartAt: Wait 20s
States:
Wait 20s:
Type: Wait
Seconds: 20
End: true
- StartAt: Pass
States:
Pass:
Type: Pass
Next: Wait 10s
Wait 10s:
Type: Wait
Seconds: 10
End: true
FinalState:
Type: Task
Resource: "arn:aws:lambda:us-east-1:999999:function:sls-step-functions-example-dev-final"
End: true
これでデプロイすると、ちょっと複雑なワークフローに変わりました。
実行すると、ちゃんとfinalのLambdaの戻り値が出力されていることがわかります。
API Gatewayと連携させる
stateMachinesのname
/ definition
と同じ階層にevents
を記述することで、Step Functionsを起動するイベントを指定できます。
stepFunctions:
stateMachines:
hellostepfunc1:
name: myStateMachine
events:
- http:
path: hello
method: GET
definition:
Comment: "A Hello World example of the Amazon States Language using an AWS Lambda Function"
デプロイされたAPIをコールすると、Step Functionsの実行が始まったことがレスポンスで返ってきます。
$ curl https://XXXXXXX.execute-api.us-east-1.amazonaws.com/dev/hello | jq .
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 147 100 147 0 0 175 0 --:--:-- --:--:-- --:--:-- 175
{
"executionArn": "arn:aws:states:us-east-1:999999:execution:myStateMachine:de9e30fd-e989-11e7-b1e4-db09d1e378c9",
"startDate": 1514216401.371
}
cronイベントなども設定可能ですので、ドキュメントをみていろいろトライしてみてください。
そのほか
Readmeにstate machineのサンプルがいろいろ紹介されてますので、そちらもぜひ触ってみてください。
- ワークフローをMarkdownなどで書き出して整理
- serverless.ymlでStateMachineにする
- デプロイして使用する
というワークフローが個人的にしっくりきそうですので、機会があれば導入してみたいなと思います。