タダです.
Serveless Applicaiton Model(SAM) で Lambda の開発とデプロイを行い,Step Functions が Lambda 関数処理のワークフローを管理しています.ただ,Step Functions のコード管理ができていない課題があって どの Step Functions が どの Lambda を管理しているかとか不明瞭だったのですが,調べていたら SAM が Step Functions をサポートしたというアップデートがありました.この波に乗って SAM で Step Functions と Lambda を管理する場合どう対応が必要なのかをサンプルアプリケーションを動かしてさらってきます.
サンプルアプリケーションの作成
sam init
で作っていきます(バージョンは 1.6.2
で確認してます).Lambda は Python で作り,Step Functions Sample App (Stock Trader)
のサンプルアプリケーションを選択しました.
$ sam init Which template source would you like to use? 1 - AWS Quick Start Templates 2 - Custom Template Location Choice: 1 Which runtime would you like to use? 1 - nodejs12.x 2 - python3.8 3 - ruby2.7 4 - go1.x 5 - java11 6 - dotnetcore3.1 7 - nodejs10.x 8 - python3.7 9 - python3.6 10 - python2.7 11 - ruby2.5 12 - java8.al2 13 - java8 14 - dotnetcore2.1 Runtime: 9 Project name [sam-app]: sfn-lambda-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) Template selection: 4 ----------------------- Generating application: ----------------------- Name: sfn-lambda-app Runtime: python3.6 Dependency Manager: pip Application Template: step-functions-sample-app Output Directory: . Next steps can be found in the README file at ./sfn-lambda-app/README.md
出来上がったサンプルアプリケーションのディレクトリ構造とディレクトリの役割は次の通りです.
functions - 株式の値をチェックしたり,購入したり,売却したりするためのアプリケーションの Lambda 関数のコード
statemachines - 株式取引のワークフローをオーケストレーションするステートマシンの定義
tests - Lambda 関数のアプリケーションコードのユニットテスト
ディレクトリ構造
$ tree . ├── README.md ├── functions │ ├── __init__.py │ ├── stock_buyer │ │ ├── __init__.py │ │ ├── app.py │ │ └── requirements.txt │ ├── stock_checker │ │ ├── __init__.py │ │ ├── app.py │ │ └── requirements.txt │ └── stock_seller │ ├── __init__.py │ ├── app.py │ └── requirements.txt ├── statemachine │ └── stock_trader.asl.json ├── template.yaml └── tests └── unit ├── __init__.py ├── test_buyer.py ├── test_checker.py └── test_seller.py 7 directories, 17 files
Step Functions の ASL の中身は次のようになっています.
{ "Comment": "A state machine that does mock stock trading.", "StartAt": "Check Stock Value", "States": { "Check Stock Value": { "Type": "Task", "Resource": "${StockCheckerFunctionArn}", "Retry": [ { "ErrorEquals": [ "States.TaskFailed" ], "IntervalSeconds": 15, "MaxAttempts": 5, "BackoffRate": 1.5 } ], "Next": "Buy or Sell?" }, "Buy or Sell?": { "Type": "Choice", "Choices": [ { "Variable": "$.stock_price", "NumericLessThanEquals": 50, "Next": "Buy Stock" } ], "Default": "Sell Stock" }, "Sell Stock": { "Type": "Task", "Resource": "${StockSellerFunctionArn}", "Retry": [ { "ErrorEquals": [ "States.TaskFailed" ], "IntervalSeconds": 2, "MaxAttempts": 3, "BackoffRate": 1 } ], "Next": "Record Transaction" }, "Buy Stock": { "Type": "Task", "Resource": "${StockBuyerFunctionArn}", "Retry": [ { "ErrorEquals": [ "States.TaskFailed" ], "IntervalSeconds": 2, "MaxAttempts": 3, "BackoffRate": 1 } ], "Next": "Record Transaction" }, "Record Transaction": { "Type": "Task", "Resource": "${DDBPutItem}", "Parameters": { "TableName": "${DDBTable}", "Item": { "Id": { "S.$": "$.id" }, "Type": { "S.$": "$.type" }, "Price": { "N.$": "$.price" }, "Quantity": { "N.$": "$.qty" }, "Timestamp": { "S.$": "$.timestamp" } } }, "Retry": [ { "ErrorEquals": [ "States.TaskFailed" ], "IntervalSeconds": 20, "MaxAttempts": 5, "BackoffRate": 10 } ], "End": true } } }
templates.yaml
の中身で Lambda と Step Functions の管理は次のコードで定義していました.DefinitionUri
が ASL の定義場所,DefinitionSubstitutions
がステートマシンの定義に変数のマッピングする場所,Events' がステートマシンのトリガーになるイベント,
Policies` がステートマシンの IAM ロールを指定する場所です.
~中略~ Resources: StockTradingStateMachine: Type: AWS::Serverless::StateMachine # More info about State Machine Resource: https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-statemachine.html Properties: DefinitionUri: statemachine/stock_trader.asl.json DefinitionSubstitutions: StockCheckerFunctionArn: !GetAtt StockCheckerFunction.Arn StockSellerFunctionArn: !GetAtt StockSellerFunction.Arn StockBuyerFunctionArn: !GetAtt StockBuyerFunction.Arn DDBPutItem: !Sub arn:${AWS::Partition}:states:::dynamodb:putItem DDBTable: !Ref TransactionTable Events: HourlyTradingSchedule: Type: Schedule # More info about Schedule Event Source: https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-property-statemachine-schedule.html Properties: Description: Schedule to run the stock trading state machine every hour Enabled: False # This schedule is disabled by default to avoid incurring charges. Schedule: "rate(1 hour)" Policies: # Find out more about SAM policy templates: https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-policy-templates.html - LambdaInvokePolicy: FunctionName: !Ref StockCheckerFunction - LambdaInvokePolicy: FunctionName: !Ref StockSellerFunction - LambdaInvokePolicy: FunctionName: !Ref StockBuyerFunction - DynamoDBWritePolicy: TableName: !Ref TransactionTable ~中略~
サンプルアプリケーションのビルドとデプロイ
サンプルアプリケーションのビルドとデプロイをしてみます.
$ sam build --use-container ~中略~ Build Succeeded Built Artifacts : .aws-sam/build Built Template : .aws-sam/build/template.yaml Commands you can use next ========================= [*] Invoke Function: sam local invoke [*] Deploy: sam deploy --guided Running PythonPipBuilder:ResolveDependencies Running PythonPipBuilder:CopySource $ sam deploy --guided ~中略~ Successfully created/updated stack - sfn-lambda-app in ap-northeast-1
Step Functions の定義もデプロイできていたので,ステートマシンの手動実行もできました.
SAM のデプロイとステートマシンの実行確認できたので,クリーンアップします.
aws cloudformation delete-stack --stack-name sfn-lambda-app
まとめ
SAM で Lambda と Step Functions を管理するコードのプロジェクト作成とデプロイの確認ができました.SAM の Step Functions の扱いをさらえたので実務でも適用を検討していけたらと思います!