Goで体験するAWS SAMとStep Functions:簡単なステップから学ぶ
はじめに
Step Functionsを実際に操作して理解を深めるために、この記事を執筆しました!
AWS SAMを活用することで、容易に実行環境をセットアップでき、手軽に試すことが可能です。この環境で、Step Functionsの構築手順について詳細に解説していきます。sam init
コマンドのテンプレートオプションには、Step Functionsも含まれているので、このテンプレートを選択します。
そのため、Step Functionsの知識がない方でも、ゼロから実践する必要がないため、安心して取り組むことができます!
もしStep Functionsに関する理解が不十分な場合は、以下の記事が参考になると思います。
準備(sam init)
sam init
コマンドを使用して、サーバーレスアプリケーションを初期化します。
今回はアプリケーション名を「sam-step-functions」としました。
「Choose an AWS Quick Start application template」という質問が表示され、実装済みのStep Functionsが含まれているテンプレートを選択します。具体的には「4 - Multi-step workflow」を選択します。
$ sam init
You can preselect a particular runtime or package type when using the `sam init` experience.
Call `sam init --help` to learn more.
Which template source would you like to use?
1 - AWS Quick Start Templates
2 - Custom Template Location
Choice: 1
Choose an AWS Quick Start application template
1 - Hello World Example
2 - Data processing
3 - Hello World Example with Powertools for AWS Lambda
4 - Multi-step workflow
5 - Scheduled task
6 - Standalone function
7 - Serverless API
8 - Infrastructure event management
9 - Lambda Response Streaming
10 - Serverless Connector Hello World Example
11 - Multi-step workflow with Connectors
12 - Full Stack
13 - Lambda EFS example
14 - Hello World Example With Powertools
15 - DynamoDB Example
16 - Machine Learning
Template: 4
Which runtime would you like to use?
1 - dotnet6
2 - go1.x
3 - go (provided.al2)
4 - java17
5 - java11
6 - java8.al2
7 - java8
8 - nodejs18.x
9 - nodejs16.x
10 - nodejs14.x
11 - nodejs12.x
12 - python3.9
13 - python3.8
14 - python3.7
15 - python3.11
16 - python3.10
17 - ruby3.2
18 - ruby2.7
Runtime: 3
Based on your selections, the only Package type available is Zip.
We will proceed to selecting the Package type as Zip.
Based on your selections, the only dependency manager available is mod.
We will proceed copying the template using mod.
Would you like to enable X-Ray tracing on the function(s) in your application? [y/N]: N
Would you like to enable monitoring using CloudWatch Application Insights?
For more info, please view https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/cloudwatch-application-insights.html [y/N]: y
AppInsights monitoring may incur additional cost. View https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/appinsights-what-is.html#appinsights-pricing for more details
Project name [sam-app]: sam-step-functions
-----------------------
Generating application:
-----------------------
Name: sam-step-functions
Runtime: go (provided.al2)
Architectures: x86_64
Dependency Manager: mod
Application Template: step-functions-sample-app
Output Directory: .
Configuration file: sam-step-functions/samconfig.toml
Next steps can be found in the README file at sam-step-functions/README.md
Commands you can use next
=========================
[*] Create pipeline: cd sam-step-functions && sam pipeline init --bootstrap
[*] Validate SAM template: cd sam-step-functions && sam validate
[*] Test Function in the Cloud: cd sam-step-functions && sam sync --stack-name {stack-name} --watch
SAM CLI update available (1.95.0); (1.93.0 installed)
To download: https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html
フォルダ構成
今回作成した「sam-step-functions」フォルダの構成は以下の通りです。
|--Makefile
|--README.md
|--functions
| |--stockBuyer
| | |--go.mod
| | |--go.sum
| | |--main.go
| | |--main_test.go
| |--stockChecker
| | |--go.mod
| | |--go.sum
| | |--main.go
| | |--main_test.go
| |--stockSeller
| | |--go.mod
| | |--go.sum
| | |--main.go
| | |--main_test.go
|--samconfig.toml
|--statemachine
| |--stockTrader.asl.json
|--template.yaml
AWS SAMテンプレート
初期化後に生成されるテンプレートです。
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
sam-step-functions
Sample SAM Template for sam-step-functions
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/stockTrader.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
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
StockCheckerFunction:
Type: AWS::Serverless::Function # More info about Function Resource: https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-function.html
Metadata:
BuildMethod: go1.x
Properties:
CodeUri: functions/stockChecker/
Handler: bootstrap
Runtime: provided.al2
Architectures:
- x86_64
StockSellerFunction:
Type: AWS::Serverless::Function
Metadata:
BuildMethod: go1.x
Properties:
CodeUri: functions/stockSeller/
Handler: bootstrap
Runtime: provided.al2
Architectures:
- x86_64
StockBuyerFunction:
Type: AWS::Serverless::Function
Metadata:
BuildMethod: go1.x
Properties:
CodeUri: functions/stockBuyer/
Handler: bootstrap
Runtime: provided.al2
Architectures:
- x86_64
TransactionTable:
Type: AWS::Serverless::SimpleTable # More info about SimpleTable Resource: https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-simpletable.html
Properties:
PrimaryKey:
Name: Id
Type: String
ProvisionedThroughput:
ReadCapacityUnits: 1
WriteCapacityUnits: 1
ApplicationResourceGroup:
Type: AWS::ResourceGroups::Group
Properties:
Name:
Fn::Sub: ApplicationInsights-SAM-${AWS::StackName}
ResourceQuery:
Type: CLOUDFORMATION_STACK_1_0
ApplicationInsightsMonitoring:
Type: AWS::ApplicationInsights::Application
Properties:
ResourceGroupName:
Ref: ApplicationResourceGroup
AutoConfigurationEnabled: 'true'
Outputs:
# StockTradingStateMachineHourlyTradingSchedule is an implicit Schedule event rule created out of Events key under Serverless::StateMachine
# Find out more about other implicit resources you can reference within SAM
# https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-specification-generated-resources.html
StockTradingStateMachineArn:
Description: Stock Trading State machine ARN
Value: !Ref StockTradingStateMachine
StockTradingStateMachineRoleArn:
Description: IAM Role created for Stock Trading State machine based on the specified
SAM Policy Templates
Value: !GetAtt StockTradingStateMachineRole.Arn
全体図
初期化が完了した後のアプリ構成図です。
【図の参照先】https://docs.aws.amazon.com/ja_jp/step-functions/latest/dg/tutorial-state-machine-using-sam.html
この構成では、事前定義されたスケジュールに基づいてワークフローが実行されますが、スケジュールはデフォルトで無効になっており、これにより手数料の発生を回避することができます。
AWS SAMテンプレートの解説
まず、template.yaml
内でのStep Functionsに関連する部分を解説します。
Step Functions ステートマシンの定義
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/stockTrader.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
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
DefinitionUri
プロパティを使用して、AWS SAMテンプレートの外部にあるステートマシンのワークフロー定義を指定しています。また、DefinitionSubstitutions
プロパティを使用して、ワークフロー内で定義された変数(${LambdaFunction})と、具体的な値との対応関係をマッピングしています。Events
セクションではEvent Bridgeをトリガーとして指定しています。これにより、1時間ごとにスケジュールされるイベントが発生しますが、初期状態では無効となっています。さらに、Policies
セクションでは、各Lambda関数に対する実行権限を与えるポリシーが定義されています。
ワークフローの内容解説
ワークフローははstatemachine/stockTrader.asl.json
に記述されています。
ワークフロー
{
"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": "$.stockPrice",
"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.$": "$.transactionType"
},
"Price": {
"N.$": "$.price"
},
"Quantity": {
"N.$": "$.qty"
},
"Timestamp": {
"S.$": "$.timestamp"
}
}
},
"Retry": [
{
"ErrorEquals": [
"States.TaskFailed"
],
"IntervalSeconds": 20,
"MaxAttempts": 5,
"BackoffRate": 10
}
],
"End": true
}
}
}
ワークフローをプレビューした際のイメージ図は以下の通りです。
VSCode上のStep Functionsのアイコン(Render state machine graph)をクリックするとワークフローを可視化することができます。
ワークフローの主な処理内容について
-
Check Stock Value (株価チェック):
- タイプ:Task
- StockCheckerFunctionArn で指定されたリソースを実行(株価をチェックする関数)
- エラー時には最大5回までリトライする
- 次のステップ:"Buy or Sell?"
-
Buy or Sell? (買うか売るか選択):
- タイプ:Choice
- $stockPrice の値が50以下の場合、「Buy Stock」ステップに進む。それ以外の場合は「Sell Stock」ステップに進む。
-
Buy Stock (株を買う):
- タイプ:Task
- StockBuyerFunctionArn で指定されたリソースを実行(株を購入する関数)
- エラー時には最大3回までリトライする
- 次のステップ:"Record Transaction"
-
Sell Stock (株を売る):
- タイプ:Task
- StockSellerFunctionArn で指定されたリソースを実行(株を売却する関数)
- エラー時には最大3回までリトライする
- 次のステップ:"Record Transaction"
-
Record Transaction (取引を記録):
- タイプ:Task
- DDBPutItem で指定されたリソースを実行(DynamoDBテーブルに取引情報を記録する関数)
- エラー時には最大5回までリトライする
- ワークフローの終了
sam deploy
デプロイにはsam deploy
コマンドを使用します。
初回の場合、デプロイ先がSAMに設定されていないため、"--guided"オプションを使用して、必要なパラメータを対話形式で設定できます。
$ sam deploy --guided
Setting default arguments for 'sam deploy'
=========================================
Stack Name [sam-step-functions]:
AWS Region [ap-northeast-1]:
#Shows you resources changes to be deployed and require a 'Y' to initiate deploy
Confirm changes before deploy [Y/n]: Y
#SAM needs permission to be able to create roles to connect to the resources in your template
Allow SAM CLI IAM role creation [Y/n]: Y
#Preserves the state of previously provisioned resources when an operation fails
Disable rollback [y/N]: y
Save arguments to configuration file [Y/n]: Y
SAM configuration file [samconfig.toml]:
SAM configuration environment [default]:
変更されるリソースの一覧が表示されます。変更セットを承認すれば、デプロイが開始されます。
CloudFormation stack changeset
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Operation LogicalResourceId ResourceType Replacement
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ Add ApplicationInsightsMonitoring AWS::ApplicationInsights::Application N/A
+ Add ApplicationResourceGroup AWS::ResourceGroups::Group N/A
+ Add StockBuyerFunctionRole AWS::IAM::Role N/A
+ Add StockBuyerFunction AWS::Lambda::Function N/A
+ Add StockCheckerFunctionRole AWS::IAM::Role N/A
+ Add StockCheckerFunction AWS::Lambda::Function N/A
+ Add StockSellerFunctionRole AWS::IAM::Role N/A
+ Add StockSellerFunction AWS::Lambda::Function N/A
+ Add StockTradingStateMachineHourlyTradingScheduleR AWS::IAM::Role N/A
ole
+ Add StockTradingStateMachineHourlyTradingSchedule AWS::Events::Rule N/A
+ Add StockTradingStateMachineRole AWS::IAM::Role N/A
+ Add StockTradingStateMachine AWS::StepFunctions::StateMachine N/A
+ Add TransactionTable AWS::DynamoDB::Table N/A
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Changeset created successfully. arn:aws:cloudformation:ap-northeast-1:************:changeSet/samcli-deploy1693122309/df09c882-d104-430d-a226-ca0f9b30e55e
Previewing CloudFormation changeset before deployment
======================================================
Deploy this changeset? [y/N]:
作成されたリソースなどが表示され、しばらくするとデプロイが完了した旨のメッセージが表示されます。
2023-08-27 16:49:17 - Waiting for stack create/update to complete
CloudFormation events from stack operations (refresh every 5.0 seconds)
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ResourceStatus ResourceType LogicalResourceId ResourceStatusReason
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
CREATE_IN_PROGRESS AWS::IAM::Role StockSellerFunctionRole -
CREATE_IN_PROGRESS AWS::IAM::Role StockCheckerFunctionRole -
CREATE_IN_PROGRESS AWS::ResourceGroups::Group ApplicationResourceGroup -
〜(省略)〜
Successfully created/updated stack - sam-step-functions in ap-northeast-1
作成されたリソースの確認
-
Lambda
正常に作成されていることが確認できます。
-
DynamoDB
正常に作成されていることが確認できます。
-
Step functions
正常に作成されていることが確認できます。
のちほどコンソール画面上から動作確認していきます。
Step Functions ステートマシンの動作確認
作成されたステートマシンの詳細画面にアクセスし、"定義"タブを選択すると、ワークフローを確認することができます。
動作確認を行うため、画面右上の「実行を開始」ボタンをクリックします。
ボタンをクリックすると、開始画面が表示され、JSON形式の入力パラメータを求められます。
通常は、ワークフロー内で定義した変数に対して値を指定する必要がありますが、今回はそのまま進めていきます。
(例えば、株の売買の判定変数である"StockPrice"には、0から99までのランダムな数字が設定されるようになっています。)
【株売却】の結果
詳細画面の「グラフビュー」タブを選択すると、各ステップの動作を詳細に確認することができます。
成功したステップは緑色で表示されます。
【株購入】の結果
株の取引が行われた後、取引データがDynamoDBに正しく登録されていることを確認します。
データが登録されていることが確認できました。
Discussion