[AWS] Step Functionsで遊んでみる(SAM + Lambda) Part.1(基礎編)


Step Functionsとは

AWS Step Functionsとは、マイクロサービスコンポーネントをワークフロー化するためのサービスです。

状態

Step Functionsでは、状態によって様々な動作を制御できます。
状態には、以下のようなものがあります。

状態 制御
Task ステートマシンで何らかの作業をする
Choice 実行の選択肢間で選択する
Fail or Succeed 失敗または成功で実行を停止する
Pass 入力を単純に出力に渡す、または一部の固定データを出力する
Wait 一定時間または指定された時刻/日付まで遅延を提供する
Parallel 実行の並列ブランチを開始する
Map ステップを動的に反復する

Taskで利用可能なサービス

Step FunctionsのTaskには、以下のサービスを指定できます。

  • Lambda
  • Batch
  • DynamoDB
  • ECS
  • Fargate
  • SNS
  • SQS
  • Glue
  • SageMaker
  • EMR
  • CodeBuild
  • Step FUnctions

今回のターゲット

Step Functionsは、範囲が非常に広く、Step Functions + Lambdaだけでみてもかなり広範囲に及びます。
投稿内容も膨大になりかねないので、この投稿に関しては、以下の内容までをターゲットにします。
パラメータを渡してみたり、条件によりタスクを換えたり、別のサービスを実行したり、といった箇所は次回にとりあげたいと思います。

  • Lambda関数を作成する(SAM)
  • Lambda関数をデプロイする(SAM)
  • ステートマシンを構成する
    • Lambda関数を呼び出す(だけ)
  • ステートマシンをデプロイする(SAM)
  • ステートマシンを実行する(マネジメントコンソール)

前提

  • SAM
  • Lambda
    • Python3.8

SAM

SAMについては、以下を参照ください。

Lambda関数を用意する

まずは、RuntimeをPython(3.8)で、Hello Worldのプロジェクトを作成します。

$ sam init --runtime=python3.8
Which template source would you like to use?
    1 - AWS Quick Start Templates
    2 - Custom Template Location
Choice: 1

Project name [sam-app]:

Cloning app templates from https://github.com/awslabs/aws-sam-cli-app-templates.git

AWS quick start application templates:
    1 - Hello World Example
    2 - EventBridge Hello World
    3 - EventBridge App from scratch (100+ Event Schemas)
    4 - Step Functions Sample App (Stock Trader)
    5 - Elastic File System Sample App
Template selection: 1

-----------------------
Generating application:
-----------------------
Name: sam-app
Runtime: python3.8
Dependency Manager: pip
Application Template: hello-world
Output Directory: .

Next steps can be found in the README file at ./sam-app/README.md

今回は、API Gatewayはいらないので、template.ymlを以下のように編集します。
AWS::Serverless::FunctionEventsの定義が不要です。
あと、Outputsそのものも不要です。

template.yml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
  sam-app

  Sample SAM Template for sam-app

# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst
Globals:
  Function:
    Timeout: 3

Resources:
  HelloWorldFunction:
    Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
    Properties:
      CodeUri: hello_world/
      Handler: app.lambda_handler
      Runtime: python3.8

保存したら、sam buildし、sam deploy --guidedを実行してデプロイしましょう。

Step Functionsでステートマシンを構成する

準備

まず、ステートマシンを構成するうえで、必要な準備をしていきましょう。
それは、Lambda関数の設定として、Step Functionから呼び出せるようロールの定義を追加します。
Hello Worldで作成したテンプレートは、デフォルトのロールをLambda関数に割り当てているので、これを明示的に作成し、割り当てる必要があります。
では、template.ymlをいじってみましょう。

template.yml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
  sam-app

  Sample SAM Template for sam-app

# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst
Globals:
  Function:
    Timeout: 3

Resources:
  HelloWorldFunction:
    Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
    Properties:
      CodeUri: hello_world/
      Handler: app.lambda_handler
      Runtime: python3.8
      Role: !GetAtt HelloWorldFunctionRole.Arn
  HelloWorldFunctionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
            Action:
              - sts:AssumeRole
      Path: /
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
        - arn:aws:iam::aws:policy/AWSStepFunctionsReadOnlyAccess

ステートマシン定義の追加

続いて、ステートマシンの定義をJson形式で作成します。
まず、ファイルの置き場所となるディレクトリを作成し、そこにファイルを新規に作成します。

$ mkdir step_functions
$ touch step_functions/state_machine.json

続いて、ステートマシンの定義を行います。
下記定義は、hello_worldのLambda関数を呼び出して、終了するだけのもので、条件やパラメータなどは一切ない、非常にシンプルな定義となっています。

step_functions/state_machine.json
{
  "StartAt": "hello world",
  "States": {
    "hello world": {
      "Type": "Task",
      "Resource": "${HelloWorldFunction}",
      "End": true
    }
  }
}

SAMのテンプレートにステートマシン定義を追加する

最後に、template.ymlに、ステートマシンの定義を追加しましょう。

template.yml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
  sam-app

  Sample SAM Template for sam-app

# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst
Globals:
  Function:
    Timeout: 3

Resources:
  HelloWorldFunction:
    Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
    Properties:
      CodeUri: hello_world/
      Handler: app.lambda_handler
      Runtime: python3.8
      Role: !GetAtt HelloWorldFunctionRole.Arn
  HelloWorldFunctionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
            Action:
              - sts:AssumeRole
      Path: /
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
        - arn:aws:iam::aws:policy/AWSStepFunctionsReadOnlyAccess
  StateMachine:
    Type: AWS::Serverless::StateMachine
    Properties:
      DefinitionUri: step_functions/state_machine.json
      DefinitionSubstitutions:
        HelloWorldFunction: !GetAtt HelloWorldFunction.Arn
      Role: !GetAtt StateMachineRole.Arn
  StateMachineRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - states.amazonaws.com
            Action:
              - sts:AssumeRole
      Path: /
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AWSLambdaRole

そして、sam buildsam deploy --guidedまで実行してみましょう。

確認してみる

まず、現在の状態を確認してみましょう。
マネジメントコンソールで、Step Functionsを選択してみましょう。
ステートマシンがデプロイされていることが確認できます。

ここにあるステートマシンの中身をみてみましょう。
「定義」の中身をみると、下記のような感じになっているかと思います。

hello_worldが呼び出されることが確認できますね。
「定義」のJsonの中身も、Resourceの部分が、Lambda関数のARNに置き換えられていることがわかります。

実行してみる

では、ステートマシンを実行してみましょう。
「実行」タブの「実行の開始」ボタンを押すと、ステートマシンが実行されます。

今回は、パラメータなどをLambda側で受け取るようにしていないため、入力もそのままで実行して大丈夫です。

すぐに実行が完了し、イベント履歴が確認できます。

リンクになっているCloud Watchを確認すると、確かにLambda関数が呼び出されていることが確認できるかと思います。

まとめ 

今回は、基本中の基本の動作ということで、まずはここまでをしっかりと抑えておくのが重要かと思います。
パラメータの設定や、Lambda以外をTaskから呼び出す方法、条件分岐については、次回とりあげてみたいと思います。

サンプルコードリポジトリ