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化を行ってみます。

今回IaC化を行うStep Functions

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自体のコード管理は、どのツールでも複雑にならずに管理できそうでした。

参考記事

この記事が気に入ったらサポートをしてみませんか?