AWS Step Functionsを定期的に実行するLambda関数をServerless Frameworkでデプロイする #reinvent

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

2017年2月16日追記
API Gateway経由でStep Functionsが呼び出せるようになったようです

2017年4月1日追記
AWSのアップデートによりCloudWatch EventsでStep Functionsを呼び出せるようになりました。

こんにちは、中山です。

AWS re:Invent 2016で発表されたAWS Step Functions。複数のAWSリソースをまとめてビジュアライズなワークフローで管理できる大変便利なサービスです。ただし現時点(2016/12/18)ではこのStep FunctionsをAWS上の何らかのイベント経由で実行することはサポートされていません。自分自身で呼び出す必要があります。いずれこの機能が提供されると思いますが、 現状どこからStep Functionsを実行するか は多くの方が課題だと感じているかと思います。今回はCloudWatch Eventsにより定期実行されたLambda関数からStep Functionsを実行する方法をご紹介します。Lambda関数のデプロイにはServerless Frameworkを利用します。

今回Lambda関数のコードではboto3を利用していますが、Step Functionsとboto3の利用方法については以下のエントリが参考になります。

やってみる

まずは以下のようなStep Functionsから呼び出されるLambda関数とServerless Frameworkの設定ファイルを用意してください。

  • invoked.py
from __future__ import print_function


def handler(event, context):
    print(event)
    return event
  • serverless.yml
service: invoke-step-functions

provider:
  name: aws
  runtime: python2.7
  stage: dev
  region: ap-northeast-1

functions:
  invoked:
    handler: invoked.handler

sls コマンドを利用してデプロイします。

$ sls deploy -v
Serverless: Creating Stack...
Serverless: Checking Stack create progress...
<snip>

今回ステートマシンの作成はマネジメントコンソールで用意されている「Hello World」ブループリントを利用します。ステートマシン用JSONファイルの Resource に先程デプロイしたLambda関数のARNを指定してください。ARNは sls info で確認できます。

image1

続いて作成したStep Functionsを呼び出すLambda関数をデプロイします。以下のコードを用意してください。

  • invoke.py
from __future__ import print_function
import os
import boto3

client = boto3.client('stepfunctions')


def handler(event, context):
    resp = client.start_execution(
            **{
              'input': '{"Comment": "Test"}',
              'stateMachineArn': os.environ['stateMachineArn']
              }
            )
    print(resp)

このLambda関数をデプロイするために先程の serverless.yml を以下のように変更してください。環境変数に渡している stateMachineArnaws stepfunctions list-state-machines などで確認できます。

service: invoke-step-functions

provider:
  name: aws
  runtime: python2.7
  stage: dev
  region: ap-northeast-1

custom:
  stateMachineArn: arn:aws:states:ap-northeast-1:************:stateMachine:test

functions:
  invoke:
    handler: invoke.handler
    role: StepFunctionsExecRole
    environment:
      stateMachineArn: ${self:custom.stateMachineArn}
    events:
       - schedule: rate(1 minute)
  invoked:
    handler: invoked.handler

resources:
  Resources:
    StepFunctionsExecRole:
      Type: AWS::IAM::Role
      Properties:
        AssumeRolePolicyDocument:
          Version: '2012-10-17'
          Statement:
            - Sid: StsAssumeRole
              Effect: Allow
              Principal:
                Service: lambda.amazonaws.com
              Action: sts:AssumeRole
        Path: /
        ManagedPolicyArns:
          - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
        Policies:
          - PolicyName: StartExecution
            PolicyDocument:
              Version: '2012-10-17'
              Statement:
                - Effect: Allow
                  Action:
                    - states:StartExecution
                  Resource: ${self:custom.stateMachineArn}

デプロイします。

$ sls deploy -v
Serverless: Packaging service...
Serverless: Uploading CloudFormation file to S3...
Serverless: Uploading service .zip file to S3 (1005 B)...
Serverless: Updating Stack...
Serverless: Checking Stack update progress...
<snip>

今回は1分毎にStep Functionsを呼び出すLambda関数を実行させているため以下のコマンドでログを出力させ続けてみます。

$ sls logs -f invoke -t
START RequestId: 05e0d449-c51e-11e6-8034-7101556b1caf Version: $LATEST
{u'startDate': datetime.datetime(2016, 12, 18, 12, 35, 21, 16000, tzinfo=tzlocal()), 'ResponseMetadata': {'RetryAttempts': 0, 'HTTPStatusCode': 200, 'RequestId': '708899f9-c51e-11e6-a401-df8361e4a81c', 'HTTPHeaders': {'x-amzn-requestid': '708899f9-c51e-11e6-a401-df8361e4a81c', 'content-length': '142', 'content-type': 'application/x-amz-json-1.0'}}, u'executionArn': u'arn:aws:states:ap-northeast-1:************:execution:test:d997224c-761b-46da-a535-d7d336dd03c1'}
END RequestId: 05e0d449-c51e-11e6-8034-7101556b1caf
REPORT RequestId: 05e0d449-c51e-11e6-8034-7101556b1caf  Duration: 247.52 ms     Billed Duration: 300 ms         Memory Size: 1024 MB    Max Memory Used: 18 MB

START RequestId: 70f58c68-c51e-11e6-97f0-473036194eb9 Version: $LATEST
{u'startDate': datetime.datetime(2016, 12, 18, 12, 35, 21, 834000, tzinfo=tzlocal()), 'ResponseMetadata': {'RetryAttempts': 0, 'HTTPStatusCode': 200, 'RequestId': '7106557e-c51e-11e6-a401-df8361e4a81c', 'HTTPHeaders': {'x-amzn-requestid': '7106557e-c51e-11e6-a401-df8361e4a81c', 'content-length': '142', 'content-type': 'application/x-amz-json-1.0'}}, u'executionArn': u'arn:aws:states:ap-northeast-1:************:execution:test:1daee69e-8ab3-4ba2-9f30-43afbec3fe30'}
END RequestId: 70f58c68-c51e-11e6-97f0-473036194eb9
REPORT RequestId: 70f58c68-c51e-11e6-97f0-473036194eb9  Duration: 232.96 ms     Billed Duration: 300 ms         Memory Size: 1024 MB    Max Memory Used: 18 MB
<snip>

正常に実行されているようです。Step Functionsから呼び出されるLambda関数の様子も見てみます。

$ sls logs -f invoked -t
START RequestId: b9250285-c51e-11e6-923e-87aeefda4cc3 Version: $LATEST
{u'Comment': u'Test'}
END RequestId: b9250285-c51e-11e6-923e-87aeefda4cc3
REPORT RequestId: b9250285-c51e-11e6-923e-87aeefda4cc3  Duration: 0.35 ms       Billed Duration: 100 ms         Memory Size: 1024 MB    Max Memory Used: 16 MB

START RequestId: dcdc6238-c51e-11e6-91cb-0502066f89a6 Version: $LATEST
{u'Comment': u'Test'}
END RequestId: dcdc6238-c51e-11e6-91cb-0502066f89a6
REPORT RequestId: dcdc6238-c51e-11e6-91cb-0502066f89a6  Duration: 0.36 ms       Billed Duration: 100 ms         Memory Size: 1024 MB    Max Memory Used: 16 MB
<snip>

こちらも問題なさそうです。やりましたね。

まとめ

いかがだったでしょうか。

定期的に実行されるLambda関数からStep Functionsを呼び出してみました。AWSが公式にStep Functionsのイベントサポートまでのワークアラウンドですが、もし同じような問題を抱えている際は参考にしていただければと思います。

本エントリがみなさんの参考になったら幸いに思います。