AWS Step FunctionsのIaC化
こんにちは!サーバーサイドエンジニアの真米です。
AWS Step Functions(以下Step Functions)は、分散アプリケーションやマイクロサービスのワークフローを構築および管理するのに役立ちます。
この記事では、Step Functionsの簡単な概要と、Step Functionsのインフラストラクチャをコードとして管理(IaC化)するための方法を紹介します。
今回Serverless Framework、AWS CloudFormation、Pulumiを使用した例を紹介します。
Step Functionsとは
Step Functionsは、分散アプリケーションやマイクロサービスのコンポーネントをシーケンシャルに、または並列に実行するためのワークフローサービスです。
Amazon Simple Workflow Serviceがプログラミングベースであるのに対して、Step Functionsは状態遷移図を用いてワークフローを視覚的に設計できます。各状態でAWS Lambda関数、Amazon S3バケット操作、Amazon SNS通知などを組み合わせることが可能です。さらに、エラーハンドリング、リトライ、条件分岐といったロジックも簡単に追加できるため、柔軟な実装が可能です。
Step FunctionsのIaC化の方法
インフラストラクチャをコードとして管理(IaC化)することで、環境間での移行を容易にでき、変更の追跡と管理を容易にすることができます。
今回はシンプルにLambda関数を2つ繋げ、1つ目のLambda関数でエラーハンドリングを行い, こちらが問題なければ2つ目のLambda関数を実行するStep FunctionsのIaC化を行ってみます。
Step FunctionsをIaC化するためのツールには、Serverless Framework、Terraform、Pulumi、AWS CloudFormation、AWS CDKなどが挙げられます。
今回は、Serverless Framework、AWS CloudFormation、PulumiのそれぞれのIaC化を実際に試してみます。
(Lambda関数の中身の定義は本題と反れるので省略しています。)
Serverless Framework
Serverless Frameworkは、サーバーレスアプリケーションの開発とデプロイを簡素化するためのオープンソースフレームワークです。以下のようにYAMLファイルに設定を記述します。(プラグインを追加する必要があります。)
service: step-functions-example
frameworkVersion: '3'
provider:
name: aws
runtime: nodejs18.x
region: ap-northeast-1
stepFunctions:
stateMachines:
testStateMachine:
name: TestStateMachine
definition:
Comment: "Step Functions test"
StartAt: TestLambda1
States:
TestLambda1:
Type: Task
Resource: arn:aws:lambda:ap-northeast-1:{account-id}:function:TestLambda1
Next: CheckTestLambda1Result
Catch:
- ErrorEquals: ["States.ALL"]
Next: FailState
CheckTestLambda1Result:
Type: Choice
Choices:
- Variable: "$.statusCode"
NumericEquals: 200
Next: TestLambda2
Default: FailState
TestLambda2:
Type: Task
Resource: arn:aws:states:::lambda:invoke
Parameters:
FunctionName: "arn:aws:lambda:ap-northeast-1:{account-id}:function:TestLambda2"
End: true
FailState:
Type: Fail
Cause: "Job failed"
plugins:
- serverless-step-functions
AWS CloudFormation
AWSが提供する主要な管理ツールの一つです。以下はCloudFormationテンプレートの例です。
AWSTemplateFormatVersion: '2010-09-09'
Resources:
MyStateMachine:
Type: AWS::StepFunctions::StateMachine
Properties:
DefinitionString: !Sub |
{
"Comment": "Step Functions test",
"StartAt": "TestLambda1",
"States": {
"TestLambda1": {
"Type": "Task",
"Resource": "arn:aws:lambda:ap-northeast-1:{account-id}:function:TestLambda1",
"Next": "Check TestLambda1 Result",
"Catch": [
{
"ErrorEquals": [
"States.ALL"
],
"Next": "FailState"
}
]
},
"Check TestLambda1 Result": {
"Type": "Choice",
"Choices": [
{
"Variable": "$.statusCode",
"NumericEquals": 200,
"Next": "TestLambda2"
}
],
"Default": "FailState"
},
"TestLambda2": {
"Type": "Task",
"Resource": "arn:aws:states:::lambda:invoke",
"Parameters": {
"FunctionName": "arn:aws:lambda:ap-northeast-1:{account-id}:function:TestLambda2",
},
"End": true
},
"FailState": {
"Type": "Fail",
"Cause": "Job failed"
}
}
}
RoleArn: arn:aws:iam::{YOUR_ACCOUNT_ID}:role/{YOUR_ROLE_NAME}
StateMachineName: TestStateMachine
Pulumi
Pulumiは、プログラミング言語を使用してインフラストラクチャを管理できるツールです。以下はTypeScriptで実装した例です。
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
// Lambda関数のARN(既存のLambda関数を指定)
const testLambda1Arn = "arn:aws:lambda:ap-northeast-1:{account-id}:function:TestLambda1";
const testLambda2Arn = "arn:aws:lambda:ap-northeast-1:{account-id}:function:TestLambda2";
// IAMロールの作成
const role = new aws.iam.Role("stepFunctionsRole", {
assumeRolePolicy: aws.iam.assumeRolePolicyForPrincipal({ Service: "states.amazonaws.com" }),
});
// ポリシーの作成
const policyAttachment = new aws.iam.RolePolicyAttachment("stepFunctionsRoleAttachment", {
role: role.name,
policyArn: aws.iam.ManagedPolicies.AWSLambdaExecute,
});
// ステートマシンの定義
const stepFunctionDefinition = {
Comment: "Step Functions test",
StartAt: "TestLambda1",
States: {
TestLambda1: {
Type: "Task",
Resource: testLambda1Arn,
Next: "CheckTestLambda1Result",
Catch: [
{
ErrorEquals: ["States.ALL"],
Next: "FailState"
}
]
},
CheckTestLambda1Result: {
Type: "Choice",
Choices: [
{
Variable: "$.statusCode",
NumericEquals: 200,
Next: "TestLambda2"
}
],
Default: "FailState"
},
TestLambda2: {
Type: "Task",
Resource: "arn:aws:states:::lambda:invoke",
Parameters: {
FunctionName: testLambda2Arn,
},
End: true
},
FailState: {
Type: "Fail",
Cause: "Job failed"
}
}
};
// ステートマシンの作成
const stepFunction = new aws.sfn.StateMachine("testStateMachine", {
roleArn: role.arn,
definition: JSON.stringify(stepFunctionDefinition),
name: "TestStateMachine",
});
export const stateMachineArn = stepFunction.arn;
まとめ
AWS Step Functionsは、分散アプリケーションやマイクロサービスのワークフローを構築および管理するためのサービスです。
この記事では、Step Functionsの概要と、Serverless Framework、AWS CloudFormation、Pulumiを使用してStep FunctionsをIaC化する方法を紹介しました。
インフラ構成管理ツールはプロジェクトの要件やチームのスキルセットに応じて選択が変わると思いますが、今回触ったStep Functions自体のコード管理は、どのツールでも複雑にならずに管理できそうでした。