この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
AWS Serverless Application Model(以下、AWS SAM)は、サーバーレスアプリケーションのデプロイに特化した、CloudFormation(以下、CFn)の拡張機能です。
AWS SAMもテンプレートにリソースを定義し、デプロイの際はCFnが使用されます。AWS SAMはCFnに比べ、テンプレートを簡潔に定義できるのが特徴だったりします。
そんな、AWS SAMで、先日Step Functionsがサポートされました。
これにより、Lambda Functionとあわせ、呼び出し元(Step Functions)が定義できるようになりました。また、Step FunctionsのワークフローをAWS SAMテンプレート外に定義することで、Amazon States Language(以下、ASL)で記述できるので、AWS SAMを利用した構築に際し、新たな書式を覚える必要がありません。
AWS SAMでStep Functionsを構築したところ、積極的に利用していきたいと思いましたので、使用感などお伝えしたいと思います。
前提
AWS SAMでStep Functionsを扱うためには、AWS SAM CLI バージョン0.52.0以上が必要になります。AWS SAM CLIのインストールについては、以下を参照ください。
本エントリではAWS SAMについての詳細は割愛していますので、AWS SAMを詳しく求むという方は以下を参照してください。
やってみた
今回はLambda Functionを呼び出す、シンプルなステートマシンを構築してみたいと思います。
以下のような構成で、Lambda Functionのコードはfunctions
ディレクトリ配下のapp.py
で定義しました。ステートマシンのワークフローは、AWS SAMテンプレート内で定義するのではなくstatemachine
ディレクトリ配下のsfn.asl.json
で定義しました。
.
├── functions
│ └── hello_world
│ ├── app.py
│ └── requirements.txt
├── statemachine
│ └── sfn.asl.json
└── template.yaml
それぞれ定義をみていきたいと思います。
ステートマシンから呼び出しされる、Lambda Functionのコードです。
functions/hello_world/app.py
def lambda_handler(event, context):
print("Hello world")
ステートマシンのワークフローは、AWS SAMテンプレートから外出ししているので、マネジメントコンソールで定義する際と同様、ASL (Amazon States Language) で定義します。呼び出しを行うLambda Funtionの指定は、変数定義にすることで、AWS SAMテンプレート内で動的に指定することができます。
sfn.asl.json
{
"StartAt": "hello world",
"States": {
"hello world": {
"Type": "Task",
"Resource": "${LambdaFunction}",
"End": true
}
}
}
AWS SAMテンプレートになります。ハイライトしている箇所がStep Functionsの定義です。
template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Parameters:
StateMachineName:
Description: Please type the Step Functions StateMachine Name.
Type: String
Default: 'sfn-sam-app-statemachine'
LambdaFunctionName:
Description: Please type the Lambda Function Name.
Type: String
Default: 'sfn-sam-app-function'
Resources:
LambdaFunction:
Type: AWS::Serverless::Function
Properties:
FunctionName: !Sub ${LambdaFunctionName}
CodeUri: functions/hello_world/
Handler: app.lambda_handler
Runtime: python3.8
Timeout: 60
Role: !GetAtt LambdaFunctionRole.Arn
LambdaFunctionRole:
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:
Name: !Sub ${StateMachineName}
DefinitionUri: statemachine/sfn.asl.json
DefinitionSubstitutions:
LambdaFunction: !GetAtt LambdaFunction.Arn
Role: !GetAtt StateMachineRole.Arn
Logging:
Level: ALL
IncludeExecutionData: True
Destinations:
- CloudWatchLogsLogGroup:
LogGroupArn: !GetAtt StateMachineLogGroup.Arn
StateMachineLogGroup:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName : !Join [ "", [ '/aws/states/', !Sub '${StateMachineName}', '-Logs' ] ]
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
- arn:aws:iam::aws:policy/CloudWatchLogsFullAccess
簡単に補足します。
DefinitionUriプロパティでAWS SAMテンプレート外に記述したステートマシンのワークフロー定義を指定しています。DefinitionSubstitutionsプロパティで、ワークフロー内に定義した変数(${LambdaFunction}
)と、定義する値をマッピングしています。
これで構築の準備が完了です。
sam deployでデプロイを行います。オプション--guided
を指定することで、CFnスタック名など、必要なパラメータを対話形式で指定することが可能です。
$ sam deploy --guided
Configuring SAM deploy
======================
Looking for samconfig.toml : Not found
Setting default arguments for 'sam deploy'
=========================================
Stack Name [sam-app]:
AWS Region [us-east-1]: ap-northeast-1
Parameter StateMachineName [sfn-sam-app-statemachine]:
Parameter LambdaFunctionName [sfn-sam-app-function]:
#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]:
Save arguments to samconfig.toml [Y/n]:
プロンプトに従い必要な情報を入力していくと、変更されるリソース等が表示されます。変更セットを許可すればデプロイが開始されます。
Waiting for changeset to be created..
CloudFormation stack changeset
---------------------------------------------------------------------------------------------------------------------------
Operation LogicalResourceId ResourceType
---------------------------------------------------------------------------------------------------------------------------
+ Add LambdaFunctionRole AWS::IAM::Role
+ Add LambdaFunction AWS::Lambda::Function
+ Add StateMachineLogGroup AWS::Logs::LogGroup
+ Add StateMachineRole AWS::IAM::Role
+ Add StateMachine AWS::StepFunctions::StateMachine
---------------------------------------------------------------------------------------------------------------------------
Changeset created successfully. arn:aws:cloudformation:ap-northeast-1:XXXXXXXXXXXX:changeSet/samcli-deploy1592909667/0face98a-4e59-4dd9-be36-f9662d24d0c9
Previewing CloudFormation changeset before deployment
======================================================
Deploy this changeset? [y/N]: y
作成されたリソース等が表示され、しばらくするとデプロイが完了します。
2020-06-23 19:59:05 - Waiting for stack create/update to complete
CloudFormation events from changeset
-------------------------------------------------------------------------------------------------------------------------
ResourceStatus ResourceType LogicalResourceId ResourceStatusReason
-------------------------------------------------------------------------------------------------------------------------
CREATE_IN_PROGRESS AWS::Logs::LogGroup StateMachineLogGroup -
CREATE_IN_PROGRESS AWS::IAM::Role StateMachineRole -
CREATE_IN_PROGRESS AWS::IAM::Role LambdaFunctionRole -
CREATE_IN_PROGRESS AWS::Logs::LogGroup StateMachineLogGroup Resource creation Initiated
CREATE_IN_PROGRESS AWS::IAM::Role StateMachineRole Resource creation Initiated
CREATE_IN_PROGRESS AWS::IAM::Role LambdaFunctionRole Resource creation Initiated
CREATE_COMPLETE AWS::Logs::LogGroup StateMachineLogGroup -
CREATE_COMPLETE AWS::IAM::Role StateMachineRole -
CREATE_COMPLETE AWS::IAM::Role LambdaFunctionRole -
CREATE_IN_PROGRESS AWS::Lambda::Function LambdaFunction -
CREATE_IN_PROGRESS AWS::Lambda::Function LambdaFunction Resource creation Initiated
CREATE_COMPLETE AWS::Lambda::Function LambdaFunction -
CREATE_IN_PROGRESS AWS::StepFunctions::StateMac StateMachine -
hine
CREATE_COMPLETE AWS::StepFunctions::StateMac StateMachine -
hine
CREATE_IN_PROGRESS AWS::StepFunctions::StateMac StateMachine Resource creation Initiated
hine
CREATE_COMPLETE AWS::CloudFormation::Stack sam-app -
-------------------------------------------------------------------------------------------------------------------------
Successfully created/updated stack - sam-app in ap-northeast-1
デプロイが完了していますので、マネジメントコンソールからもステートマシンの作成を確認することができます。
今回の構成でワークフローを変更する際は、sfn.asl.json
を更新します。
sfn.asl.json
{
"StartAt": "hello world",
"States": {
"hello world": {
"Type": "Task",
"Resource": "${LambdaFunction}",
"Next": "succeed",
"Catch": [
{
"ErrorEquals": [
"States.ALL"
],
"Next": "fail"
}
]
},
"succeed": {
"Type": "Succeed"
},
"fail": {
"Type": "Fail",
"Error": "ErrorCode 100",
"Cause": "There is Error."
}
}
}
再度、デプロイを行えば環境に反映されます。
$ sam deploy
(省略)
CloudFormation stack changeset
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Operation LogicalResourceId ResourceType
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
* Modify StateMachine AWS::StepFunctions::StateMachine
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
(省略)
CloudFormation events from changeset
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ResourceStatus ResourceType LogicalResourceId ResourceStatusReason
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
UPDATE_IN_PROGRESS AWS::StepFunctions::StateMachine StateMachine -
UPDATE_COMPLETE AWS::StepFunctions::StateMachine StateMachine -
UPDATE_COMPLETE_CLEANUP_IN_PROGRESS AWS::CloudFormation::Stack sam-app -
UPDATE_COMPLETE AWS::CloudFormation::Stack sam-app -
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Successfully created/updated stack - sam-app in ap-northeast-1
変更が反映されたことが確認できました。
おまけ
テンプレート内のLambda Functionから、StepFunctionsを操作したいといった時には、 該当するステートマシンのARNをLambda Functionの環境変数に設定したり...なんてことがあると思いますが、今回のような構成でそれをやってしまうと、circular dependencies(循環参照)のエラーとなります。
StepFunctionsでは実行中に使用できるContext オブジェクトがあり、ステートマシンのARNも取得することができます。 循環参照が発生した時でもいいので、Context オブジェクトで値がとれるということを、頭の片隅にでも入れておいていただければ幸いです。
最後に
Step Functionsがサポートされたことにより、Lambda Functionとあわせ、呼び出し元(Step Functions)も定義できますので、 AWS SAMのベストプラクティスにあるような管理が行え、 開発、運用が行いやすくなるのではないでしょうか。
CFnに馴染みのある方であれが、AWS SAM自体はスムーズに利用できると思いますので、Step Functionsを構築する際はAWS SAMの利用も検討してみてはいかがでしょうか。