【自分用】【備忘録】AWS Step Functions+ECSタスクのワークフロー
【備忘録】
Step functionsステートマシンでのECS(Fargate)タスク実行について
並列・直列実行ワークフロー定義を作成した。
※学習内容を備忘録として残す
■Step Functions ステートマシーン定義
直列実行定義(ECSタスク×2) 警告判定
{
"StartAt": "ECS_TaskA",
"States": {
"ECS_TaskA": {
"Type": "Task",
"Resource": "arn:aws:states:::ecs:runTask.sync",
"Parameters": {
"LaunchType": "FARGATE",
"Cluster": "",
"TaskDefinition": "",
"NetworkConfiguration": {
"AwsvpcConfiguration": {
"Subnets": [
"subnet-020bfb42a62070fd0",
"subnet-0f76b85fd4ec253be"
],
"SecurityGroups": [
"sg-0a952161376b08a81"
],
"AssignPublicIp": "ENABLED"
}
}
},
"Catch": [
{
"ErrorEquals": [
"States.ALL"
],
"ResultPath": "$.error",
"Next": "警告判定(A)"
}
],
"Next": "ECS_TaskB"
},
"警告判定(A)": {
"Type": "Choice",
"Choices": [
{
"Variable": "$.error.Cause",
"StringMatches": "*\"ExitCode\":9*",
"Next": "ECS_TaskB"
}
],
"Default": "異常終了"
},
"ECS_TaskB": {
"Type": "Task",
"Resource": "arn:aws:states:::ecs:runTask.sync",
"Parameters": {
"LaunchType": "FARGATE",
"Cluster": "",
"TaskDefinition": "",
"NetworkConfiguration": {
"AwsvpcConfiguration": {
"Subnets": [
"subnet-020bfb42a62070fd0",
"subnet-0f76b85fd4ec253be"
],
"SecurityGroups": [
"sg-0a952161376b08a81"
],
"AssignPublicIp": "ENABLED"
}
}
},
"Catch": [
{
"ErrorEquals": [
"States.ALL"
],
"Next": "警告判定(B)",
"ResultPath": "$.error"
}
],
"End": true
},
"警告判定(B)": {
"Type": "Choice",
"Choices": [
{
"Variable": "$.error.Cause",
"StringMatches": "*\"ExitCode\":9*",
"Next": "警告判定(ExitCode:9)"
}
],
"Default": "異常終了"
},
"警告判定(ExitCode:9)": {
"Type": "Succeed"
},
"異常終了": {
"Type": "Fail",
"Error": "UnexpectedFailure",
"Cause": "ExitCode が 0, 9 以外の異常終了"
}
}
}
直列実行定義(ECSタスク×2) 警告判定 CFn
AWSTemplateFormatVersion: '2010-09-09'
Resources:
StateMachinec7bf56b8:
Type: AWS::StepFunctions::StateMachine
Properties:
Definition:
StartAt: ECS_TaskA
States:
ECS_TaskA:
Type: Task
Resource: arn:aws:states:::ecs:runTask.sync
Parameters:
LaunchType: FARGATE
Cluster: [クラスターARN]
TaskDefinition: [タスク定義ARN]
NetworkConfiguration:
AwsvpcConfiguration:
Subnets:
- subnet-020bfb42a62070fd0
- subnet-0f76b85fd4ec253be
SecurityGroups:
- sg-0a952161376b08a81
AssignPublicIp: ENABLED
Catch:
- ErrorEquals:
- States.ALL
ResultPath: $.error
Next: 警告判定(A)
Next: ECS_TaskB
警告判定(A):
Type: Choice
Choices:
- Variable: $.error.Cause
StringMatches: '*"ExitCode":9*'
Next: ECS_TaskB
Default: 異常終了
ECS_TaskB:
Type: Task
Resource: arn:aws:states:::ecs:runTask.sync
Parameters:
LaunchType: FARGATE
Cluster: [クラスターARN]
TaskDefinition: [タスク定義ARN]
NetworkConfiguration:
AwsvpcConfiguration:
Subnets:
- subnet-020bfb42a62070fd0
- subnet-0f76b85fd4ec253be
SecurityGroups:
- sg-0a952161376b08a81
AssignPublicIp: ENABLED
Catch:
- ErrorEquals:
- States.ALL
ResultPath: $.error
Next: 警告判定(B)
End: true
警告判定(B):
Type: Choice
Choices:
- Variable: $.error.Cause
StringMatches: '*"ExitCode":9*'
Next: 警告判定(ExitCode:9)
Default: 異常終了
警告判定(ExitCode:9):
Type: Succeed
異常終了:
Type: Fail
Error: UnexpectedFailure
Cause: ExitCode が 0, 9 以外の異常終了
RoleArn: [IAMのARN]
StateMachineName: StateMachinec7bf56b8
StateMachineType: STANDARD
EncryptionConfiguration:
Type: AWS_OWNED_KEY
直列実行警告(ECSタスク×2) CFn定義詳細
プロパティ名 | 項目説明 | 設定根拠・意味 |
---|---|---|
StateMachineName |
ステートマシンの名前 | コンソールやCLI上で識別する名前として使用されます。 |
StateMachineType |
ステートマシンの種別(STANDARD or EXPRESS) |
STANDARD は長時間実行・高信頼、EXPRESS は高頻度/短時間向け。今回は標準型。 |
RoleArn |
ステートマシンが AWS サービスを操作するための IAM ロール | ECS タスクの実行、ログ出力などを許可するために必要です。 |
EncryptionConfiguration.Type |
実行履歴の暗号化方式 |
AWS_OWNED_KEY は AWS が自動管理するキーで暗号化します(デフォルト)。 |
♦︎定義内の各ステート(状態)
プロパティ名 | 項目説明 | 設定根拠・意味 |
---|---|---|
StartAt |
ステートマシンの最初のステート名 | 実行が ECS_TaskA から始まることを指定します。 |
ECS_TaskA.Type / ECS_TaskB.Type
|
タスク実行の型 |
Task 型で ECS タスクを同期実行(runTask.sync )します。 |
Resource |
実行リソースのARN |
arn:aws:states:::ecs:runTask.sync は Step Functions から ECS タスクを同期実行するリソース指定です。 |
Parameters.LaunchType |
実行タイプ |
FARGATE を指定することで、Fargateでの実行になります。 |
Parameters.Cluster |
実行する ECS クラスターの ARN | ECS タスクがどのクラスターで動くかを指定します。 |
Parameters.TaskDefinition |
実行する ECS タスク定義 | 実行されるアプリケーション(Dockerコンテナ構成)を定義したリソースです。 |
NetworkConfiguration.AwsvpcConfiguration |
ネットワーク設定(VPC) | 実行環境のサブネットやセキュリティグループを指定します。 |
Catch |
エラー発生時の処理先ステート |
States.ALL によりすべての例外をキャッチし、次の判断(Choice)に進めます。 |
警告判定(A/B).Type |
条件分岐ステート | エラー内容に "ExitCode":9 が含まれているかを判定します。 |
警告判定(ExitCode:9).Type |
警告とみなして正常終了扱いにするステート |
Succeed を返して全体の処理を成功として終了させます。 |
異常終了.Type |
異常終了を明示するステート |
Fail 型は明示的に失敗とするため、モニタリングや通知に活用できます。 |
<注記>
・StringMatches: '"ExitCode":9' の書き方は文字列として "ExitCode":9 が含まれているかを見るパターンマッチです。
・ResultPath: $.error によりエラー情報が $.error に格納され、Choice ステートで参照されます。
直列実行定義
{
"Comment": "ECSタスク実行結果に基づいて異常終了原因を明示する構成 (ExitCode をエラー判断に活用)",
"StartAt": "【先行】ECS RunTask ①",
"States": {
"【先行】ECS RunTask ①": {
"Type": "Task",
"Comment": "最初のECSタスク(正常系)を同期実行する",
"Resource": "arn:aws:states:::ecs:runTask.sync",
"Parameters": {
"LaunchType": "FARGATE",
"Cluster": "arn:aws:ecs:ap-northeast-1:{アカウントID}:cluster/2413882_test",
"TaskDefinition": "arn:aws:ecs:ap-northeast-1:{アカウントID}:task-definition/2413882_Helloworld:7",
"NetworkConfiguration": {
"AwsvpcConfiguration": {
"Subnets": [
"subnet-020bfb42a62070fd0",
"subnet-0f76b85fd4ec253be"
],
"SecurityGroups": [
"sg-0a952161376b08a81"
],
"AssignPublicIp": "ENABLED"
}
}
},
"Retry": [
{
"ErrorEquals": [
"States.ALL"
],
"IntervalSeconds": 2,
"MaxAttempts": 1,
"BackoffRate": 1
}
],
"Catch": [
{
"ErrorEquals": [
"States.ALL"
],
"ResultPath": "$.error",
"Next": "異常終了"
}
],
"Next": "【先行】ECS RunTask ②"
},
"【先行】ECS RunTask ②": {
"Type": "Task",
"Comment": "2つ目のECSタスク(正常/異常含む)を同期実行する",
"Resource": "arn:aws:states:::ecs:runTask.sync",
"Parameters": {
"LaunchType": "FARGATE",
"Cluster": "arn:aws:ecs:ap-northeast-1:{アカウントID}:cluster/2413882_test",
"TaskDefinition": "arn:aws:ecs:ap-northeast-1:{アカウントID}:task-definition/2413882_Helloworld:6",
"NetworkConfiguration": {
"AwsvpcConfiguration": {
"Subnets": [
"subnet-020bfb42a62070fd0",
"subnet-0f76b85fd4ec253be"
],
"SecurityGroups": [
"sg-0a952161376b08a81"
],
"AssignPublicIp": "ENABLED"
}
}
},
"Retry": [
{
"ErrorEquals": [
"States.ALL"
],
"IntervalSeconds": 2,
"MaxAttempts": 1,
"BackoffRate": 1
}
],
"Catch": [
{
"ErrorEquals": [
"States.ALL"
],
"ResultPath": "$.error",
"Next": "異常終了"
}
],
"Next": "成功"
},
"成功": {
"Type": "Succeed",
"Comment": "すべての処理が正常に終了した"
},
"異常終了": {
"Type": "Fail",
"Comment": "いずれかのECSタスクが異常終了した",
"Cause": "ECSタスクが異常終了しました",
"Error": "ECS.Fargate.ExitCode"
}
}
}
Overridesを用いてECSタスクにデータを渡す
{
"StartAt": "【先行】ECS RunTask ①",
"States": {
"【後行】ECS RunTask ①": {
"Type": "Task",
"Resource": "arn:aws:states:::ecs:runTask.sync",
"Parameters": {
"LaunchType": "FARGATE",
"Cluster": "[クラスターARN]",
"TaskDefinition": "[タスク定義ARN]",
"NetworkConfiguration": {
"AwsvpcConfiguration": {
"Subnets": [
"subnet-020bfb42a62070fd0",
"subnet-0f76b85fd4ec253be"
],
"SecurityGroups": [
"sg-0a952161376b08a81"
],
"AssignPublicIp": "ENABLED"
}
},
"Overrides": {
"ContainerOverrides": [
{
"Name": "[コンテナ名]",
"Command": [
"sh",
"-c",
"echo Hello-world; exit 100"
]
}
]
}
},
"End": true
}
}
}
並列実行定義=Prallelが失敗したら、失敗とみなす
{
"Comment": "並列ECSジョブ + 条件分岐",
"StartAt": "並列ジョブ開始",
"States": {
"並列ジョブ開始": {
"Type": "Parallel",
"Branches": [
{
"StartAt": "ECS RunTask (Helloworld)",
"States": {
"ECS RunTask (Helloworld)": {
"Type": "Task",
"Resource": "arn:aws:states:::ecs:runTask.sync",
"Parameters": {
"LaunchType": "FARGATE",
"Cluster": "arn:aws:ecs:ap-northeast-1:{アカウントID}:cluster/2413882_test",
"TaskDefinition": "arn:aws:ecs:ap-northeast-1:{アカウントID}:task-definition/2413882_Helloworld:7",
"NetworkConfiguration": {
"AwsvpcConfiguration": {
"Subnets": [
"subnet-020bfb42a62070fd0",
"subnet-0f76b85fd4ec253be"
],
"SecurityGroups": [
"sg-0a952161376b08a81"
],
"AssignPublicIp": "ENABLED"
}
}
},
"End": true
}
}
},
{
"StartAt": "Run Task (Helloworld:202)",
"States": {
"Run Task (Helloworld:202)": {
"Type": "Task",
"Resource": "arn:aws:states:::ecs:runTask.sync",
"Parameters": {
"LaunchType": "FARGATE",
"Cluster": "arn:aws:ecs:ap-northeast-1:{アカウントID}:cluster/2413882_test",
"TaskDefinition": "arn:aws:ecs:ap-northeast-1:{アカウントID}:task-definition/2413882_Helloworld:8",
"NetworkConfiguration": {
"AwsvpcConfiguration": {
"Subnets": [
"subnet-020bfb42a62070fd0",
"subnet-0f76b85fd4ec253be"
],
"SecurityGroups": [
"sg-0a952161376b08a81"
],
"AssignPublicIp": "ENABLED"
}
}
},
"Retry": [
{
"ErrorEquals": [
"States.ALL"
],
"IntervalSeconds": 2,
"MaxAttempts": 1,
"BackoffRate": 1
}
],
"End": true
}
}
}
],
"Next": "Check If Success"
},
"Check If Success": {
"Type": "Choice",
"Choices": [
{
"Variable": "$[1].Containers[0].ExitCode",
"NumericEquals": 0,
"Next": "Final ECS RunTask"
}
],
"Default": "異常終了"
},
"Final ECS RunTask": {
"Type": "Task",
"Resource": "arn:aws:states:::ecs:runTask.sync",
"Parameters": {
"LaunchType": "FARGATE",
"Cluster": "arn:aws:ecs:ap-northeast-1:{アカウントID}:cluster/2413882_test",
"TaskDefinition": "arn:aws:ecs:ap-northeast-1:{アカウントID}:task-definition/2413882_Helloworld:7",
"NetworkConfiguration": {
"AwsvpcConfiguration": {
"Subnets": [
"subnet-020bfb42a62070fd0",
"subnet-0f76b85fd4ec253be"
],
"SecurityGroups": [
"sg-0a952161376b08a81"
],
"AssignPublicIp": "ENABLED"
}
}
},
"Next": "成功"
},
"成功": {
"Type": "Succeed"
},
"異常終了": {
"Type": "Fail",
"Error": "TaskFailed",
"Cause": "One or more parallel jobs failed"
}
}
}
並列実行定義=条件分岐(片方失敗しても、Prallel突破) ※後行ジョブは実行しない
{
"Comment": "並列ECSジョブ + 条件分岐",
"StartAt": "並列ジョブ開始",
"States": {
"並列ジョブ開始": {
"Type": "Parallel",
"Branches": [
{
"StartAt": "ECS RunTask (Helloworld①)",
"States": {
"ECS RunTask (Helloworld①)": {
"Type": "Task",
"Resource": "arn:aws:states:::ecs:runTask.sync",
"Parameters": {
"LaunchType": "FARGATE",
"Cluster": "arn:aws:ecs:ap-northeast-1:{アカウントID}:cluster/2413882_test",
"TaskDefinition": "arn:aws:ecs:ap-northeast-1:{アカウントID}:task-definition/2413882_Helloworld:7",
"NetworkConfiguration": {
"AwsvpcConfiguration": {
"Subnets": [
"subnet-020bfb42a62070fd0",
"subnet-0f76b85fd4ec253be"
],
"SecurityGroups": [
"sg-0a952161376b08a81"
],
"AssignPublicIp": "ENABLED"
}
}
},
"Catch": [
{
"ErrorEquals": [
"States.ALL"
],
"ResultPath": "$.error",
"Next": "SetExitCode①"
}
],
"End": true
},
"SetExitCode①": {
"Type": "Pass",
"Result": {
"ExitCode": "エラー"
},
"ResultPath": "$.Containers[0]",
"End": true
}
}
},
{
"StartAt": "Run Task (Helloworld②)",
"States": {
"Run Task (Helloworld②)": {
"Type": "Task",
"Resource": "arn:aws:states:::ecs:runTask.sync",
"Parameters": {
"LaunchType": "FARGATE",
"Cluster": "arn:aws:ecs:ap-northeast-1:{アカウントID}:cluster/2413882_test",
"TaskDefinition": "arn:aws:ecs:ap-northeast-1:{アカウントID}:task-definition/2413882_Helloworld:9",
"NetworkConfiguration": {
"AwsvpcConfiguration": {
"Subnets": [
"subnet-020bfb42a62070fd0",
"subnet-0f76b85fd4ec253be"
],
"SecurityGroups": [
"sg-0a952161376b08a81"
],
"AssignPublicIp": "ENABLED"
}
}
},
"Catch": [
{
"ErrorEquals": [
"States.ALL"
],
"ResultPath": "$.error",
"Next": "SetExitCode②"
}
],
"End": true
},
"SetExitCode②": {
"Type": "Pass",
"Result": {
"ExitCode": "エラー"
},
"ResultPath": "$.Containers[0]",
"End": true
}
}
}
],
"Next": "Check If Success"
},
"Check If Success": {
"Type": "Choice",
"Choices": [
{
"Variable": "$[0].Containers[0].ExitCode",
"NumericEquals": 0,
"Next": "Check Branch 2"
}
],
"Default": "異常終了"
},
"Check Branch 2": {
"Type": "Choice",
"Choices": [
{
"Variable": "$[1].Containers[0].ExitCode",
"NumericEquals": 0,
"Next": "Final ECS RunTask"
}
],
"Default": "異常終了"
},
"Final ECS RunTask": {
"Type": "Task",
"Resource": "arn:aws:states:::ecs:runTask.sync",
"Parameters": {
"LaunchType": "FARGATE",
"Cluster": "arn:aws:ecs:ap-northeast-1:{アカウントID}:cluster/2413882_test",
"TaskDefinition": "arn:aws:ecs:ap-northeast-1:{アカウントID}:task-definition/2413882_Helloworld:7",
"NetworkConfiguration": {
"AwsvpcConfiguration": {
"Subnets": [
"subnet-020bfb42a62070fd0",
"subnet-0f76b85fd4ec253be"
],
"SecurityGroups": [
"sg-0a952161376b08a81"
],
"AssignPublicIp": "ENABLED"
}
}
},
"Next": "成功"
},
"成功": {
"Type": "Succeed"
},
"異常終了": {
"Type": "Fail",
"Error": "TaskFailed",
"Cause": "One or more parallel jobs failed"
}
}
}
並列実行定義=条件分岐(片方失敗しても、Prallel突破、※後行ジョブも実行
{
"Comment": "並列ECSジョブ + 条件分岐(OR 条件)",
"StartAt": "並列ジョブ開始",
"States": {
"並列ジョブ開始": {
"Type": "Parallel",
"Branches": [
{
"StartAt": "【先行】ECS RunTask ①",
"States": {
"【先行】ECS RunTask ①": {
"Type": "Task",
"Resource": "arn:aws:states:::ecs:runTask.sync",
"Parameters": {
"LaunchType": "FARGATE",
"Cluster": "arn:aws:ecs:ap-northeast-1:{アカウントID}:cluster/2413882_test",
"TaskDefinition": "arn:aws:ecs:ap-northeast-1:{アカウントID}:task-definition/2413882_Helloworld:8",
"NetworkConfiguration": {
"AwsvpcConfiguration": {
"Subnets": [
"subnet-020bfb42a62070fd0",
"subnet-0f76b85fd4ec253be"
],
"SecurityGroups": [
"sg-0a952161376b08a81"
],
"AssignPublicIp": "ENABLED"
}
}
},
"Catch": [
{
"ErrorEquals": [
"States.ALL"
],
"ResultPath": "$.error",
"Next": "①エラーコードをChoiceへ渡す"
}
],
"End": true
},
"①エラーコードをChoiceへ渡す": {
"Type": "Pass",
"Result": {
"ExitCode": 999
},
"ResultPath": "$.Containers[0]",
"End": true
}
}
},
{
"StartAt": "【先行】ECS RunTask ②",
"States": {
"【先行】ECS RunTask ②": {
"Type": "Task",
"Resource": "arn:aws:states:::ecs:runTask.sync",
"Parameters": {
"LaunchType": "FARGATE",
"Cluster": "arn:aws:ecs:ap-northeast-1:{アカウントID}:cluster/2413882_test",
"TaskDefinition": "arn:aws:ecs:ap-northeast-1:{アカウントID}task-definition/2413882_Helloworld:7",
"NetworkConfiguration": {
"AwsvpcConfiguration": {
"Subnets": [
"subnet-020bfb42a62070fd0",
"subnet-0f76b85fd4ec253be"
],
"SecurityGroups": [
"sg-0a952161376b08a81"
],
"AssignPublicIp": "ENABLED"
}
}
},
"Catch": [
{
"ErrorEquals": [
"States.ALL"
],
"ResultPath": "$.error",
"Next": "②エラーコードをChoiceへ渡す"
}
],
"End": true
},
"②エラーコードをChoiceへ渡す": {
"Type": "Pass",
"Result": {
"ExitCode": 999
},
"ResultPath": "$.Containers[0]",
"End": true
}
}
}
],
"Next": "判定"
},
"判定": {
"Type": "Choice",
"Choices": [
{
"Or": [
{
"Variable": "$[0].Containers[0].ExitCode",
"NumericEquals": 0
},
{
"Variable": "$[1].Containers[0].ExitCode",
"NumericEquals": 0
}
],
"Next": "【後行】ECS RunTask③"
}
],
"Default": "異常終了"
},
"【後行】ECS RunTask③": {
"Type": "Task",
"Resource": "arn:aws:states:::ecs:runTask.sync",
"Parameters": {
"LaunchType": "FARGATE",
"Cluster": "arn:aws:ecs:ap-northeast-1:{アカウントID}:cluster/2413882_test",
"TaskDefinition": "arn:aws:ecs:ap-northeast-1:{アカウントID}:task-definition/2413882_Helloworld:8",
"NetworkConfiguration": {
"AwsvpcConfiguration": {
"Subnets": [
"subnet-020bfb42a62070fd0",
"subnet-0f76b85fd4ec253be"
],
"SecurityGroups": [
"sg-0a952161376b08a81"
],
"AssignPublicIp": "ENABLED"
}
}
},
"Next": "成功",
"Catch": [
{
"ErrorEquals": [
"States.ALL"
],
"Comment": "エラーキャッチ",
"Next": "異常終了"
}
]
},
"成功": {
"Type": "Succeed"
},
"異常終了": {
"Type": "Fail",
"Cause": "ECSタスクが異常終了しました"
}
}
}
並列実行定義=条件分岐(片方失敗しても、Prallel突破、※後行ジョブも実行するが、各ジョブどれかエラーの場合は、ステートマシーンは失敗
{
"Comment": "並列ジョブ → 最終ジョブは常に実行 → 成否で分岐",
"StartAt": "並列ジョブ開始",
"States": {
"並列ジョブ開始": {
"Type": "Parallel",
"Branches": [
{
"StartAt": "ECS RunTask (Helloworld1)",
"States": {
"ECS RunTask (Helloworld1)": {
"Type": "Task",
"Resource": "arn:aws:states:::ecs:runTask.sync",
"Parameters": {
"LaunchType": "FARGATE",
"Cluster": "arn:aws:ecs:ap-northeast-1:{アカウントID}:cluster/2413882_test",
"TaskDefinition": "arn:aws:ecs:ap-northeast-1:{アカウントID}:task-definition/2413882_Helloworld:7",
"NetworkConfiguration": {
"AwsvpcConfiguration": {
"Subnets": [
"subnet-020bfb42a62070fd0",
"subnet-0f76b85fd4ec253be"
],
"SecurityGroups": [
"sg-0a952161376b08a81"
],
"AssignPublicIp": "ENABLED"
}
}
},
"Catch": [
{
"ErrorEquals": [
"States.ALL"
],
"ResultPath": "$.Containers[0]",
"Next": "SetError1"
}
],
"End": true
},
"SetError1": {
"Type": "Pass",
"Result": {
"ExitCode": 999
},
"ResultPath": "$.Containers[0]",
"End": true
}
}
},
{
"StartAt": "ECS RunTask (Helloworld2)",
"States": {
"ECS RunTask (Helloworld2)": {
"Type": "Task",
"Resource": "arn:aws:states:::ecs:runTask.sync",
"Parameters": {
"LaunchType": "FARGATE",
"Cluster": "arn:aws:ecs:ap-northeast-1:{アカウントID}:cluster/2413882_test",
"TaskDefinition": "arn:aws:ecs:ap-northeast-1:{アカウントID}4:task-definition/2413882_Helloworld:9",
"NetworkConfiguration": {
"AwsvpcConfiguration": {
"Subnets": [
"subnet-020bfb42a62070fd0",
"subnet-0f76b85fd4ec253be"
],
"SecurityGroups": [
"sg-0a952161376b08a81"
],
"AssignPublicIp": "ENABLED"
}
}
},
"Catch": [
{
"ErrorEquals": [
"States.ALL"
],
"ResultPath": "$.Containers[0]",
"Next": "SetError2"
}
],
"End": true
},
"SetError2": {
"Type": "Pass",
"Result": {
"ExitCode": 999
},
"ResultPath": "$.Containers[0]",
"End": true
}
}
}
],
"Next": "後行ジョブ"
},
"後行ジョブ": {
"Type": "Task",
"Resource": "arn:aws:states:::ecs:runTask.sync",
"Parameters": {
"LaunchType": "FARGATE",
"Cluster": "arn:aws:ecs:ap-northeast-1:{アカウントID}:cluster/2413882_test",
"TaskDefinition": "arn:aws:ecs:ap-northeast-1:{アカウントID}:task-definition/2413882_Helloworld:7",
"NetworkConfiguration": {
"AwsvpcConfiguration": {
"Subnets": [
"subnet-020bfb42a62070fd0",
"subnet-0f76b85fd4ec253be"
],
"SecurityGroups": [
"sg-0a952161376b08a81"
],
"AssignPublicIp": "ENABLED"
}
}
},
"Next": "判定"
},
"判定": {
"Type": "Choice",
"Choices": [
{
"Or": [
{
"Variable": "$[0].Containers[0].ExitCode",
"NumericEquals": 999
},
{
"Variable": "$[1].Containers[0].ExitCode",
"NumericEquals": 999
}
],
"Next": "異常終了"
}
],
"Default": "成功"
},
"成功": {
"Type": "Succeed"
},
"異常終了": {
"Type": "Fail",
"Cause": "1つ以上の並列ジョブが異常終了しました",
"Error": "ParallelJobFailed"
}
}
}
■直列・並列定義詳細を表で整理
直列実行定義詳細
項目 | 定義 | 詳細 | 設定根拠 |
---|---|---|---|
処理構成 | StartAt |
"StartAt": "[対象ECSタスク]" 最初に実行されるステートを定義 |
ステートマシンの開始地点を明示的に指定する必要があるため |
ECSタスクの同期実行 | Resource |
"Resource": "arn:aws:states:::ecs:runTask.sync" ECSタスクの同期型起動 |
タスクの完了を待ち、終了コードに基づく次の処理を制御するため |
Fargate実行設定 | Parameters |
LaunchType , Cluster , TaskDefinition , NetworkConfiguration 等を定義 |
ECSタスクの実行環境(クラスタ、定義、NW設定)を指定するため |
AwsvpcConfiguration |
Subnets , SecurityGroups , AssignPublicIp を指定 |
タスクのENI生成に必要であるため | |
再試行 | Retry |
ErrorEquals: States.ALL IntervalSeconds: 2 MaxAttempts: 1 BackoffRate: 1
|
一時的な失敗に対して自動再試行することで、ワークフローの耐久性を高めるため |
エラーハンドリング | Catch |
ErrorEquals: States.ALL ResultPath: "$.error"
|
タスクが失敗した際、異常終了に制御を移すため |
正常終了定義 | 成功状態 | "Type": "Succeed" |
成功時のステートマシン終了状態を明示するため |
異常終了定義 | 異常終了状態 |
"Type": "Fail" "Cause": "ECSタスクが異常終了しました" "Error": "ECS.Exit"
|
失敗時のステートマシン終了状態を明示するため |
並列実行定義詳細
大項目 | 中項目 | 詳細 | 設定根拠 |
---|---|---|---|
処理構成 | StartAt |
"StartAt": "[対象ECSタスク]" 最初に実行されるステートを定義 |
ステートマシンの開始地点を明示的に指定する必要があるため |
ECSタスクの同期実行 | Resource |
"Resource": "arn:aws:states:::ecs:runTask.sync" ECSタスクの同期型起動 |
タスクの完了を待ち、終了コードに基づく次の処理を制御するため |
Fargate実行設定 | Parameters |
LaunchType , Cluster , TaskDefinition , NetworkConfiguration 等を定義 |
ECSタスクの実行環境(クラスタ、定義、NW設定)を指定するため |
AwsvpcConfiguration |
Subnets , SecurityGroups , AssignPublicIp を指定 |
タスクのENI(Elastic Network Interface)生成に必要であるため | |
再試行 | Retry |
ErrorEquals: States.ALL IntervalSeconds: 2 MaxAttempts: 1 BackoffRate: 1
|
一時的な失敗に対して自動再試行することで、ワークフローの耐久性を高めるため |
エラーハンドリング | Catch |
ErrorEquals: States.ALL ResultPath: "$.error" |
タスクが失敗した際、”Pass”へ遷移させるため |
エラーコードを"Choice"へ渡す | Pass |
"Pass" で"ExitCode: 999" を Containers[0] に格納し、Choiceに使用できるようにする Result で固定値 "ExitCode: 999" を生成 ResultPath で出力データ構造を他と統一する |
並列ジョブいずれか一方が失敗しても、後行ジョブを実行させるため |
判定(正常 or 異常) | Choice |
"Choice" 下記条件を設定することで、後行ジョブが実行する ※並列ジョブ両方失敗は、後行ジョブ実行しない "Variable": "$[0].Containers[0].ExitCode" 並列ジョブ両方成功"Variable":"$[1].Containers[0].ExitCode" 並列ジョブいずれか一方が失敗 |
後行ジョブ実行後、ステートマシーン全体が正常 or 異常と判定させるため |
正常終了定義 | 成功状態 | "Type": "Succeed" |
成功時のステートマシン終了状態を明示するため |
異常終了定義 | 異常終了状態 |
"Type": "Fail" "Cause": "失敗したジョブがあります" "Error": "ParallelJobFailed"
|
終了時のステートマシン終了状態を明示するため |
■親,子ステートマシン CloudFormation(yml)で作成
親,子ステートマシンCFn
AWSTemplateFormatVersion: '2010-09-09'
Resources:
Child1StateMachine:
Type: AWS::StepFunctions::StateMachine
Properties:
Definition:
StartAt: 子1ECSタスク
States:
子1ECSタスク:
Type: Task
Resource: arn:aws:states:::ecs:runTask.sync
Parameters:
LaunchType: FARGATE
Cluster: !ImportValue MyECSClusterArn
TaskDefinition: !ImportValue MyTaskDefinitionArn
NetworkConfiguration:
AwsvpcConfiguration:
Subnets:
- !ImportValue MySubnet1Id
- !ImportValue MySubnet2Id
SecurityGroups:
- !ImportValue MySecurityGroupId
AssignPublicIp: ENABLED
Overrides:
ContainerOverrides:
- Name: my-container-name
Command:
- sh
- '-c'
- echo Hello-world; exit 0
End: true
RoleArn: !ImportValue MyStepFunctionsRoleArn
StateMachineName: Child1
StateMachineType: STANDARD
EncryptionConfiguration:
Type: AWS_OWNED_KEY
LoggingConfiguration:
Level: 'OFF'
IncludeExecutionData: false
Child2StateMachine:
Type: AWS::StepFunctions::StateMachine
Properties:
Definition:
StartAt: 子2ECSタスク
States:
子2ECSタスク:
Type: Task
Resource: arn:aws:states:::ecs:runTask.sync
Parameters:
LaunchType: FARGATE
Cluster: !ImportValue MyECSClusterArn
TaskDefinition: !ImportValue MyTaskDefinitionArn
NetworkConfiguration:
AwsvpcConfiguration:
Subnets:
- !ImportValue MySubnet1Id
- !ImportValue MySubnet2Id
SecurityGroups:
- !ImportValue MySecurityGroupId
AssignPublicIp: ENABLED
Overrides:
ContainerOverrides:
- Name: my-container-name
Command:
- sh
- '-c'
- echo Hello-world; exit 0
End: true
RoleArn: !ImportValue MyStepFunctionsRoleArn
StateMachineName: Child2
StateMachineType: STANDARD
EncryptionConfiguration:
Type: AWS_OWNED_KEY
LoggingConfiguration:
Level: 'OFF'
IncludeExecutionData: false
PareStateMachine:
Type: AWS::StepFunctions::StateMachine
Properties:
Definition:
Comment: Parent state machine
StartAt: '[先行]StartExecution'
States:
'[先行]StartExecution':
Type: Task
Resource: arn:aws:states:::states:startExecution.sync:2
Parameters:
StateMachineArn: !Ref Child1StateMachine
Next: '[後行]StartExecution'
'[後行]StartExecution':
Type: Task
Resource: arn:aws:states:::states:startExecution.sync:2
Parameters:
StateMachineArn: !Ref Child2StateMachine
Next: '[先行]ECS RunTask'
'[先行]ECS RunTask':
Type: Task
Resource: arn:aws:states:::ecs:runTask.sync
Parameters:
LaunchType: FARGATE
Cluster: !ImportValue MyECSClusterArn
TaskDefinition: !ImportValue MyTaskDefinitionArn
NetworkConfiguration:
AwsvpcConfiguration:
Subnets:
- !ImportValue MySubnet1Id
- !ImportValue MySubnet2Id
SecurityGroups:
- !ImportValue MySecurityGroupId
AssignPublicIp: ENABLED
Overrides:
ContainerOverrides:
- Name: my-container-name
Command:
- sh
- '-c'
- echo Hello-world; exit 0
Next: '[後行]ECS RunTask'
'[後行]ECS RunTask':
Type: Task
Resource: arn:aws:states:::ecs:runTask.sync
Parameters:
LaunchType: FARGATE
Cluster: !ImportValue MyECSClusterArn
TaskDefinition: !ImportValue MyTaskDefinitionArn
NetworkConfiguration:
AwsvpcConfiguration:
Subnets:
- !ImportValue MySubnet1Id
- !ImportValue MySubnet2Id
SecurityGroups:
- !ImportValue MySecurityGroupId
AssignPublicIp: ENABLED
Overrides:
ContainerOverrides:
- Name: my-container-name
Command:
- sh
- '-c'
- echo Hello-world; exit 0
End: true
QueryLanguage: JSONPath
RoleArn: !ImportValue MyStepFunctionsRoleArn
StateMachineName: Pare
StateMachineType: STANDARD
EncryptionConfiguration:
Type: AWS_OWNED_KEY
LoggingConfiguration:
Level: 'OFF'
IncludeExecutionData: false
Outputs:
Pare:
Description: ARN of the parent Step Functions state machine
Value: !Ref PareStateMachine
Export:
Name: Pare
Child1:
Description: ARN of the first child Step Functions state machine
Value: !Ref Child1StateMachine
Export:
Name: Child1
Child2:
Description: ARN of the second child Step Functions state machine
Value: !Ref Child2StateMachine
Export:
Name: Child2
EventBridgeスケジュール,スケジュールグループ
AWSTemplateFormatVersion: '2010-09-09'
Resources:
# EventBridgeスケジュールグループ作成
MyScheduleGroup:
Type: AWS::Scheduler::ScheduleGroup
Properties:
Name: my-schedule-group
Tags:
- Key: Name
Value: 計画操作
# EventBridgeスケジュール作成
MySchedule:
Type: AWS::Scheduler::Schedule
Properties:
Name: my-schedule-job
GroupName: !Ref MyScheduleGroup
Description: stepfunctions-test
ScheduleExpression: 'cron(0 10 * * ? *)'
ScheduleExpressionTimezone: Asia/Tokyo
FlexibleTimeWindow:
Mode: "OFF"
Target:
Arn: !ImportValue Pare # ← 親ステートマシンの出力名 'Pare' を参照
RoleArn: [IAM]
Input: '{}'
RetryPolicy:
MaximumRetryAttempts: 0
MaximumEventAgeInSeconds: 60
Outputs:
ScheduleGroupArn:
Description: ARN of the EventBridge schedule group
Value: !Sub arn:aws:scheduler:${AWS::Region}:${AWS::AccountId}:schedule-group/my-schedule-group
Export:
Name: ScheduleGroupArn
ScheduleArn:
Description: ARN of the EventBridge schedule
Value: !Sub arn:aws:scheduler:${AWS::Region}:${AWS::AccountId}:schedule/my-schedule-group/my-schedule-job
Export:
Name: ScheduleArn
・DLQを使いたいときだけ DeadLetterConfig を明示
・[MaximumEventAgeInSeconds: 60]について
たとえ GUI 上で「再試行ポリシー」をオフにしても、
AWS EventBridge Scheduler の裏側では イベント自体の「最大生存期間(Event Age)」として 24時間(= 86400秒) がデフォルトとして使われる
機能 | 明記しなかった場合のデフォルト | OFFにしたいときに必要な書き方 |
---|---|---|
再試行ポリシー(RetryPolicy) | ON(再試行される) | RetryPolicy: { MaximumRetryAttempts: 0 } |
デッドレターキュー(DLQ) | OFF(使用されない) |
DeadLetterConfig: { Arn: ... } を記載しなければOFFのまま
|
プロパティ名 | 項目説明 | 設定根拠 |
---|---|---|
Name |
スケジュールの一意な名前 | GUIの「スケジュール名」欄に相当 |
GroupName |
紐づくスケジュールグループの名前(上記の Name を参照) |
GUIで「スケジュールグループを選択」で設定 |
Description |
スケジュールの説明テキスト | GUIの「説明」欄に入力される |
ScheduleExpression |
実行スケジュール(cron形式)cron(0 1 * * ? *) は JSTで毎日10:00 |
GUIの「スケジュール(cron/rate)」に相当。UTCベースのためJST換算で 10:00実行になる |
FlexibleTimeWindow.Mode |
実行時間の柔軟性を許容するか"OFF" = 固定時間に実行 |
GUIの「柔軟な時間ウィンドウ」をオフにした状態 |
Target.Arn |
実行先の Step Functions の ARN | GUIで「ターゲット」→ Step Functions 選択で指定 |
Target.RoleArn |
EventBridge スケジューラがターゲットを実行するための IAM ロール | GUIで指定する「IAM 実行ロール」に相当 |
Target.Input |
ターゲットへ渡す入力 JSON | GUIで「入力パラメータ(JSON形式)」に相当。ここでは空の {} を指定 |
RetryPolicy.MaximumRetryAttempts |
ターゲットが失敗した場合の最大再試行回数(ここでは再試行なし) | GUIで「再試行ポリシー」→ オフにしたときと同様 |
RetryPolicy.MaximumEventAgeInSeconds |
最大でイベントを保持する時間(秒) 60秒=1分以内に実行できなければ中断 |
GUIでは非表示だが、CLI/IaCで明示しないとデフォルト(86400秒=24時間)が適用されるため明示指定が必要 |
・公式ドキュメント
When retry policy is not specified, the scheduler uses a default MaximumEventAgeInSeconds of 86400 seconds (24 hours).
IAMポリシー
events:PutEvents
カスタムイベントを EventBridge に送信するための権限
Step Functions が ECS タスクの終了を検知するために使う EventBridge 機能では、PutEvents は使わない
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowRunAndMonitorECSTask",
"Effect": "Allow",
"Action": [
"ecs:RunTask",
"ecs:StopTask",
"ecs:DescribeTasks"
],
"Resource": "*"
},
{
"Sid": "AllowPassTaskRole",
"Effect": "Allow",
"Action": "iam:PassRole",
"Resource": "arn:aws:iam::{アカウントID}:role/ecsTaskExecutionRole"
},
{
"Sid": "AllowEventBridgeSyncForECS",
"Effect": "Allow",
"Action": [
"events:PutTargets",
"events:PutRule",
"events:DescribeRule"
],
"Resource": "*"
},
{
"Sid": "AllowStartChildStepFunction",
"Effect": "Allow",
"Action": [
"states:StartExecution",
"states:DescribeExecution"
],
"Resource": "*"
},
{
"Sid": "AllowCloudWatchLogsAccess",
"Effect": "Allow",
"Action": [
"logs:CreateLogDelivery",
"logs:GetLogDelivery",
"logs:UpdateLogDelivery",
"logs:DeleteLogDelivery",
"logs:ListLogDeliveries",
"logs:PutResourcePolicy",
"logs:DescribeResourcePolicies",
"logs:DescribeLogGroups"
],
"Resource": "*"
}
]
}
Sid | Action一覧 | Resourceの範囲 | 説明 |
---|---|---|---|
AllowRunAndMonitorECSTask | - ecs:RunTask - ecs:StopTask - ecs:DescribeTasks |
*(全てのECSタスク) | Step Functions から ECS タスクを起動・停止・状態確認するために必要な権限 |
AllowPassTaskRole | - iam:PassRole | arn:aws:iam::{アカウントID}:role/ecsTaskExecutionRole | ECS タスクに割り当てる実行ロール(Task Execution Role)を許可。ARN指定で最小権限を遵守 |
AllowEventBridgeSyncForECS | - events:PutTargets - events:PutRule - events:DescribeRule |
*(イベントルール一式) | runTask.sync の内部処理で必要な EventBridge の同期ルール作成と管理に必要 |
AllowStartChildStepFunction | - states:StartExecution - states:DescribeExecution |
*(すべての Step Functions) | 子ステートマシン(サブステートマシン)を起動・状態確認するための権限 |
AllowCloudWatchLogsAccess | - logs:CreateLogDelivery - logs:GetLogDelivery - logs:UpdateLogDelivery - logs:DeleteLogDelivery - logs:ListLogDeliveries - logs:PutResourcePolicy - logs:DescribeResourcePolicies - logs:DescribeLogGroups |
*(CloudWatch Logs 関連リソース) | ステートマシン実行ログを CloudWatch Logs に出力するために必要な一連の操作 |
iam:PassRole の Resource はセキュリティ観点から 明示された1つのロールに限定
events:* 系のアクションは、Step Functions から ECS を同期実行 (runTask.sync) する場合に AWS が 内部的に EventBridge ルールを作成するため必要
states:* の権限で、Step Functions の中から 子ステートマシンを起動できる
logs:* は、Step Functions の 実行ログやトレースを CloudWatch に出力するために必要
Discussion