三度の飯より飯が好き🍚。どうも私です。
キラメックスでは、機械学習のTrainingや定期的な予測出力にAWS Step Functionsを使用しています。
今回は、Serverless Frameworkを使ってAWS Step Functionsのステートマシーンを作成・実行する方法を紹介します。
前提
- Serverless Frameworkを使って実装していきます。
- 諸々インストール、設定済みとします。
本記事でできること
- Lambda Functionを作ります。
- ステートマシーンに付与するIAMロールを作成します。
- Step Functionsのステートマシーンを作ります。このステートマシーン内では1.で作成したLambda Functionを実行します
- Step Functionsのステートマシーンを実行するためのIAMロールを作ります。
- Amazon EventBridgeのイベントルールを作ります。このイベントでは3.で作成したステートマシーンを4.のロールでcron実行します。
上記をServerless Frameworkで実装してリソースを作成します。
やってみる
プロジェクト作成
sf-example
という名前でプロジェクトを作りました。
$ sls create -t aws-python -p sf-example
sf-example
というフォルダが作成され、その下にhandler.py
とserverless.yml
が作成されます。以降の作業はすべてsf-example
フォルダの下で実施します。
Lambda関数の定義
Lambdaの関数はhandler.py
の自動生成されたコードを使うことにするので今回は特に編集はしません。
serverless.yml
を以下の通りに編集しhelloという関数を定義します。
service: sf-example frameworkVersion: '2' provider: name: aws runtime: python3.8 region: ap-northeast-1 functions: hello: handler: handler.hello
ステートマシーンに付与するIAMロールを定義
serverless.yml
に以下を追記します。
resources: Resources: StepFunctionsExecutionRole: Type: AWS::IAM::Role Properties: Description: StepFunctions Example RoleName: StepFunctionsExample_Execution_Role AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: - states.amazonaws.com Action: - 'sts:AssumeRole' Path: '/service-role/' Policies: - PolicyName: XRayAccess_Example_Policy PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: - xray:PutTraceSegments - xray:PutTelemetryRecords - xray:GetSamplingRules - xray:GetSamplingTargets Resource: '*' - PolicyName: InvokeLambdaFunction_Example_Policy PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: lambda:InvokeFunction Resource: '*'
Step Functionsのステートマシーンを定義
まずは以下のコマンドでStep Functionsのプラグインをインストールします。
$ npm install serverless-step-functions
インストールしたプラグインについてserverless.yml
に以下を追記します。
plugins: - serverless-step-functions package: exclude: - node_modules/**
続いてserverless.yml
にステートマシーンの定義を追記します。
stepFunctions: stateMachines: StateMachineExample: name: StateMachineExample role: Fn::GetAtt: [StepFunctionsExecutionRole, Arn] definition: Comment: Step Functions Example StartAt: Hello Function States: Hello Function: Type: Task Resource: Fn::GetAtt: [hello, Arn] End: True
roleには、前の手順で定義したロールを指定しています。 また、Hello FunctionというTaskの中でLambdaのhello関数を指定しています。
ステートマシーンを実行するためのIAMロール作成
EventBridgeからステートマシーンを実行する際のIAMロールを作成します。
serverless.yml
のResources:
に追記していきます。
resources: Resources: StepFunctionsExecutionRole: 〜 略 〜 InvokeStepFunctionsIamRoleExample: Type: AWS::IAM::Role Properties: Description: StepFunctions Example RoleName: Invoke_StepFunctionsExample_Role AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: - events.amazonaws.com Action: - sts:AssumeRole Path: '/service-role/' Policies: - PolicyName: StartExecution_Policy PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: states:StartExecution Resource: Fn::GetAtt: [StateMachineExample, Arn]
Amazon EventBridgeのルールを定義
最後に、cronでStep Functionsのステートマシーンを実行するイベントルールを定義します。 ここではcronで毎日15:00(JST)に実行するようにしています。
serverless.yml
のResources:
に追記していきます。
resources: Resources: StepFunctionsExecutionRole: 〜 略 〜 InvokeStepFunctionsIamRoleExample: 〜 略 〜 InvokeStepFunctionsEventExample: Type: AWS::Events::Rule Properties: Description: StepFunctions Example Name: Invoke_StepFunctionsExample_Event ScheduleExpression: 'cron(0 6 * * ? *)' # 日本時間の15:00(毎日) State: ENABLED Targets: - Arn: Fn::GetAtt: [StateMachineExample, Arn] Id: StateMachineExample RoleArn: Fn::GetAtt: [InvokeStepFunctionsIamRoleExample, Arn]
デプロイ
以下のコマンドでデプロイします。
$ sls deploy
デプロイが成功すると以下のリソースが新しく作成されるので、マネージメントコンソールにログインして確認してみてください。
- CloudFormationのスタック
- Lambdaの関数
- IAMロール(2種類)
- Step Functionsのステートマシーン
- EventBridgeのルール
cronで指定した時刻になると、StepFunctionsのステートマシーンが実行されます!
実行結果を見るとこのように成功していることが確認できます。
リソースの削除
作成したリソースをすべて削除したい場合は以下のコマンドを実行します。
$ sls remove
終わりに
最後にserverless.yml
の全体を載せておきます。
service: sf-example frameworkVersion: '2' provider: name: aws runtime: python3.8 region: ap-northeast-1 plugins: - serverless-step-functions package: exclude: - node_modules/** functions: hello: handler: handler.hello stepFunctions: stateMachines: StateMachineExample: name: StateMachineExample role: Fn::GetAtt: [StepFunctionsExecutionRole, Arn] definition: Comment: Step Functions Example StartAt: Hello Function States: Hello Function: Type: Task Resource: Fn::GetAtt: [hello, Arn] End: True resources: Resources: StepFunctionsExecutionRole: Type: AWS::IAM::Role Properties: Description: StepFunctions Example RoleName: StepFunctionsExample_Execution_Role AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: - states.amazonaws.com Action: - 'sts:AssumeRole' Path: '/service-role/' Policies: - PolicyName: XRayAccess_Example_Policy PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: - xray:PutTraceSegments - xray:PutTelemetryRecords - xray:GetSamplingRules - xray:GetSamplingTargets Resource: '*' - PolicyName: InvokeLambdaFunction_Example_Policy PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: lambda:InvokeFunction Resource: '*' InvokeStepFunctionsIamRoleExample: Type: AWS::IAM::Role Properties: Description: StepFunctions Example RoleName: Invoke_StepFunctionsExample_Role AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: - events.amazonaws.com Action: - sts:AssumeRole Path: '/service-role/' Policies: - PolicyName: StartExecution_Policy PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: states:StartExecution Resource: Fn::GetAtt: [StateMachineExample, Arn] InvokeStepFunctionsEventExample: Type: AWS::Events::Rule Properties: Description: StepFunctions Example Name: Invoke_StepFunctionsExample_Event ScheduleExpression: 'cron(0 6 * * ? *)' # 日本時間の15:00(毎日) State: ENABLED Targets: - Arn: Fn::GetAtt: [StateMachineExample, Arn] Id: StateMachineExample RoleArn: Fn::GetAtt: [InvokeStepFunctionsIamRoleExample, Arn]