この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
これまで、Step Functionsの構築にCFnやCLI等を利用していましたが、Serverless Frameworkを利用したところ、JSONベースのステートメント言語から開放され、サクッと構築できましたので紹介したいと思います。
Serverless FrameworkでStep Functionsを扱うにはプラグインが必要になります。
過去にStep Functionsプラグインを利用したエントリはありますが、プラグイン等もアップデートされていますので改めてやってみた系のエントリになります。
前提
Serverless Framework自体のインストールや、基本的な利用方法については割愛しています。
その辺りから確認されたい方は、以下が参考になると思います。
- 今から始めるServerless Frameworkで簡単Lambda開発環境の構築
- 初めてのサーバーレスアプリケーション開発 ~Serverless Framework を使ってAWSリソースをデプロイする~
本エントリでは以下バージョンを利用しています。
- serverless 1.48.4
- serverless-step-functions 2.1.0
やってみた
サービス作成
Serverless Frameworkではサービスという単位で複数のリソースを管理しますので、まずはサービスを作成します。
ここでは、サービス用のディレクトリTestStepFunctions
を作成して、サービス名StepFunctionsService
でランタイムはpython3
としました。
$ serverless create --template aws-python3 --name StepFunctionsService --path TestStepFunctions
Serverless: Generating boilerplate...
Serverless: Generating boilerplate in "/Users/sakamaki.kazuyoshi/awscli/sakamaki.kazuyoshi/TestStepFunctions"
_______ __
| _ .-----.----.--.--.-----.----| .-----.-----.-----.
| |___| -__| _| | | -__| _| | -__|__ --|__ --|
|____ |_____|__| \___/|_____|__| |__|_____|_____|_____|
| | | The Serverless Application Framework
| | serverless.com, v1.48.4
-------'
Serverless: Successfully generated boilerplate for template: "aws-python3"
上記コマンドを実行すると、カレントディレクトリにTestStepFunctions
ディレクトリが作成され、配下にServerless Frameworkの定義ファイルserverless.yml
と、テンプレートのpythonスクリプトhandler.py
が作成されます。
$ ls -l
total 0
drwxr-xr-x 5 sakamaki.kazuyoshi staff 160 Jul 28 16:15 TestStepFunctions
$ ls -lR TestStepFunctions
total 16
-rw-r--r-- 1 sakamaki.kazuyoshi staff 497 Jul 28 16:15 handler.py
-rw-r--r-- 1 sakamaki.kazuyoshi staff 3162 Jul 28 16:15 serverless.yml
プラグイン インストール
Step Functionsを利用するために以下のプラグイン導入します。
Serverless Frameworkのプラグインはサービスごとに追加され、グローバルには適用されませんので、サービスのルートディレクトリ(ここではTestStepFunctions
)よりインストールを行います。
$ cd TestStepFunctions/
$ npm install --save-dev serverless-step-functions
serverless.yml修正
serverless.yml
はサービス全体の設定を行うためのファイルです。ここでは以下のように定義しました。
service: StepFunctionsService
plugins:
- serverless-step-functions
provider:
name: aws
runtime: python3.7
region: ap-northeast-1
functions:
Function1:
name: TestFunction
handler: handler.hello
stepFunctions:
stateMachines:
StateMachine1:
name: TestStateMachine
definition:
StartAt: HelloWorld
States:
HelloWorld:
Type: Task
Resource:
Fn::GetAtt: [Function1LambdaFunction, Arn]
End: true
Step Functions周りの設定について説明します。plugins
プロパティでStep Functionsのプラグインを指定し、stepFunctions
プロパティにステートマシンを定義していきます。
ここでは、単一のLambda関数を実行するだけのステートマシンを定義しています。
ステートマシンから実行されるLambda関数は定義ファイル内で作成しており、ステートマシンの定義では、実行するLambda関数のARNが必要になるので、CFn組み込み関数(Fn::GetAtt
)を使用してARNを取得しています。
定義の詳細については、以下をご確認ください。
余談ですが、Serverless Frameworkでどのようにリソース論理名が作成されるか、マニュアルから読み取れなかったので、Fn::GetAtt
に指定するリソース論理名はsls package
等で生成されるCFnテンプレートから確認しました。functions
プロパティ配下のLambda関数論理名(ここではFunction1
)+LambdaFunction
となっていました。
デプロイ
サービスをデプロイします。
$ sls deploy -v
Serverless: Packaging service...
Serverless: Excluding development dependencies...
(省略)
デプロイが完了すると、CFnスタックが作成され、serverless.yml
で定義したLambda、ステートマシンが作成されています。
スタック
Lambda
ステートマシン
動作確認(ステートマシン実行)
デプロイしたステートマシンをServerless Frameworkより実行します。
$ sls invoke stepf --name StateMachine1
.
{ executionArn:
'arn:aws:states:ap-northeast-1:XXXXXXXXXXXX:execution:TestStateMachine:e3fde4c1-c416-4be1-83d1-2ac8f7ae0734',
stateMachineArn:
'arn:aws:states:ap-northeast-1:XXXXXXXXXXXX:stateMachine:TestStateMachine',
name: 'e3fde4c1-c416-4be1-83d1-2ac8f7ae0734',
status: 'SUCCEEDED',
startDate: 2019-07-28T07:47:05.951Z,
stopDate: 2019-07-28T07:47:06.458Z,
input: '{}',
output:
'{"statusCode": 200, "body": "{\\"message\\": \\"Go Serverless v1.0! Your function executed successfully!\\", \\"input\\": {}}"}' }
実行結果が出力され、ステートマシンを正常に実行することができました。
ステートマシン更新/動作確認
ステートマシン実行時の入力値に応じて、処理分岐するステートマシンに更新してみたいと思います。serverless.yml
を以下に更新しました。ハイライトしている箇所が更新部分です。
以前はステートマシンの更新がサポートされておらず、一度作成したステートマシンは編集できませんでしたが、現在はサポートされていますので、Serverless Frameworkからでも問題なく更新ができます。
service: StepFunctionsService
plugins:
- serverless-step-functions
provider:
name: aws
runtime: python3.7
region: ap-northeast-1
functions:
Function1:
name: TestFunction
handler: handler.hello
stepFunctions:
stateMachines:
StateMachine1:
name: TestStateMachine
definition:
StartAt: ChoiceState
States:
ChoiceState:
Type: Choice
Choices:
- Variable: "$.input"
StringEquals: "error"
Next: Fail
Default: HelloWorld
HelloWorld:
Type: Task
Resource:
Fn::GetAtt: [Function1LambdaFunction, Arn]
Next: Succeed
Fail:
Type: Fail
Succeed:
Type: Succeed
デプロイします。
$ sls deploy -v
Serverless: Packaging service...
Serverless: Excluding development dependencies...
(省略)
デプロイが完了するとステートマシンが更新されれました。
ステートマシン実行時のインプットを変え、動作を確認してみたいと思います。
成功
$ sls invoke stepf --name StateMachine1 --data '{"input":"sakana"}'
.
{ executionArn:
'arn:aws:states:ap-northeast-1:XXXXXXXXXXXX:execution:TestStateMachine:76401943-7bde-4e90-9acf-ea04d1389ab5',
stateMachineArn:
'arn:aws:states:ap-northeast-1:XXXXXXXXXXXX:stateMachine:TestStateMachine',
name: '76401943-7bde-4e90-9acf-ea04d1389ab5',
status: 'SUCCEEDED',
startDate: 2019-07-28T08:14:09.082Z,
stopDate: 2019-07-28T08:14:09.634Z,
input: '{"input":"sakana"}',
output:
'{"statusCode": 200, "body": "{\\"message\\": \\"Go Serverless v1.0! Your function executed successfully!\\", \\"input\\": {\\"input\\": \\"sakana\\"}}"}' }
HL00257-2:TestStepFunctions sakamaki.kazuyoshi$
失敗
$ sls invoke stepf --name StateMachine1 --data '{"input":"error"}'
{ executionArn:
'arn:aws:states:ap-northeast-1:XXXXXXXXXXXX:execution:TestStateMachine:86dcf2f5-3768-457c-b775-852e08908b65',
stateMachineArn:
'arn:aws:states:ap-northeast-1:XXXXXXXXXXXX:stateMachine:TestStateMachine',
name: '86dcf2f5-3768-457c-b775-852e08908b65',
status: 'FAILED',
startDate: 2019-07-28T08:15:16.756Z,
stopDate: 2019-07-28T08:15:16.896Z,
input: '{"input":"error"}' }
HL00257-2:TestStepFunctions sakamaki.kazuyoshi$
さいごに
ステートマシンの定義にボリュームがでてくると、ステートメント言語(JSONベース)での定義がつらくなってくると思います。また、Step Functionsを利用するほとんどのケースで、Lambdaを利用していると思いますので、一連のデプロイをServerless Frameworkで実施すると簡潔になると思います。CloudWatchイベントの連携等もサクッと定義することができるので、Step Functionsを構築する際はServerless Frameworkの利用を検討してみてはいかがでしょうか。