AWS Step Functions で再実行ができるようになったので、前回のシンプル編に引き続き、ジョブネットのエラー対応をどれだけ実現できるか試してみます。
想定するジョブネット
今回はジョブが選択と分岐の形状と想定をして実験してみます。今回はジョブ2-2とジョブ4-2がそれぞれ異常終了したときの挙動を確認します。また、異常終了したジョブと並行して実行されるジョブ(ジョブ2-1や4-1)の完了タイミングが、異常終了の前になるか後になるかで多少の挙動の違いがあるためそこも実験していきます。
実装の概要
前回と同じくaws-samples の amazon-stepfunctions-ssm-waitfortasktoken を利用した SfnRunCommandByInstanceIds を用いて、Steps Functions に以下のようなステートマシンを定義しました。並行稼働部は Parallel を使用しています。
{
"Comment": "This is a test state machine by yki",
"StartAt": "StartAutomationWaitForCallBack (Job 1)",
"States": {
"StartAutomationWaitForCallBack (Job 1)": {
"Type": "Task",
"Resource": "arn:aws:states:::aws-sdk:ssm:startAutomationExecution.waitForTaskToken",
"Parameters": {
"DocumentName": "SfnRunCommandByInstanceIds",
"Parameters": {
"InstanceIds": [
"i-xxxxxxxxxxxxxxxxx"
],
"taskToken.$": "States.Array($$.Task.Token)",
"workingDirectory": [
"/home/ec2-user/sample-batch/"
],
"Commands": [
"./do-some1.sh"
]
}
},
"Next": "Parallel"
},
"Parallel": {
"Type": "Parallel",
"Next": "StartAutomationWaitForCallBack (Job 3)",
"Branches": [
{
"StartAt": "StartAutomationWaitForCallBack (Job 2-1)",
"States": {
"StartAutomationWaitForCallBack (Job 2-1)": {
"Type": "Task",
"Resource": "arn:aws:states:::aws-sdk:ssm:startAutomationExecution.waitForTaskToken",
"Parameters": {
"DocumentName": "SfnRunCommandByInstanceIds",
"Parameters": {
"InstanceIds": [
"i-xxxxxxxxxxxxxxxxx"
],
"taskToken.$": "States.Array($$.Task.Token)",
"workingDirectory": [
"/home/ec2-user/sample-batch/"
],
"Commands": [
"./do-some2-1.sh"
]
}
},
"End": true
}
}
},
{
"StartAt": "StartAutomationWaitForCallBack (Job 2-2)",
"States": {
"StartAutomationWaitForCallBack (Job 2-2)": {
"Type": "Task",
"Resource": "arn:aws:states:::aws-sdk:ssm:startAutomationExecution.waitForTaskToken",
"Parameters": {
"DocumentName": "SfnRunCommandByInstanceIds",
"Parameters": {
"InstanceIds": [
"i-xxxxxxxxxxxxxxxxx"
],
"taskToken.$": "States.Array($$.Task.Token)",
"workingDirectory": [
"/home/ec2-user/sample-batch/"
],
"Commands": [
"./do-some2-2.sh"
]
}
},
"End": true
}
}
}
]
},
"StartAutomationWaitForCallBack (Job 3)": {
"Type": "Task",
"Resource": "arn:aws:states:::aws-sdk:ssm:startAutomationExecution.waitForTaskToken",
"Parameters": {
"DocumentName": "SfnRunCommandByInstanceIds",
"Parameters": {
"InstanceIds": [
"i-xxxxxxxxxxxxxxxxx"
],
"taskToken.$": "States.Array($$.Task.Token)",
"workingDirectory": [
"/home/ec2-user/sample-batch/"
],
"Commands": [
"./do-some3.sh"
]
}
},
"Next": "Parallel (1)"
},
"Parallel (1)": {
"Type": "Parallel",
"End": true,
"Branches": [
{
"StartAt": "StartAutomationWaitForCallBack (Job 4-1)",
"States": {
"StartAutomationWaitForCallBack (Job 4-1)": {
"Type": "Task",
"Resource": "arn:aws:states:::aws-sdk:ssm:startAutomationExecution.waitForTaskToken",
"Parameters": {
"DocumentName": "SfnRunCommandByInstanceIds",
"Parameters": {
"InstanceIds": [
"i-xxxxxxxxxxxxxxxxx"
],
"taskToken.$": "States.Array($$.Task.Token)",
"workingDirectory": [
"/home/ec2-user/sample-batch/"
],
"Commands": [
"./do-some4-1.sh"
]
}
},
"End": true
}
}
},
{
"StartAt": "StartAutomationWaitForCallBack (Job 4-2)",
"States": {
"StartAutomationWaitForCallBack (Job 4-2)": {
"Type": "Task",
"Resource": "arn:aws:states:::aws-sdk:ssm:startAutomationExecution.waitForTaskToken",
"Parameters": {
"DocumentName": "SfnRunCommandByInstanceIds",
"Parameters": {
"InstanceIds": [
"i-xxxxxxxxxxxxxxxxx"
],
"taskToken.$": "States.Array($$.Task.Token)",
"workingDirectory": [
"/home/ec2-user/sample-batch/"
],
"Commands": [
"./do-some4-2.sh"
]
}
},
"End": true
}
}
}
]
}
}
}
ジョブ2-2の異常終了と再実行
異常終了
異常終了が発生するようにtouch /home/ec2-user/sample-batch/filetest2-2
とtouch /home/ec2-user/sample-batch/filetest4-2
を行ってからステートマシンの実行を行います。
ここでリカバリ対応としてrm /home/ec2-user/sample-batch/filetest2-2
をしてからリドライブを行います。
異常終了したジョブ2-2とその後続のジョブが実行されてました。その上で、予定通りジョブ4-2が異常終了しています。
さらにジョブ4-2の異常終了と再実行
リカバリ対応としてrm /home/ec2-user/sample-batch/filetest4-2
をしてからリドライブを行います。
異常終了する前に並行稼働ジョブが完了していない場合
上記の例では、例えばジョブ2-2が異常終了する前にジョブ2-1は正常終了していましたが、そうではない場合のケースも確認します。
ジョブ2-1の実行時間を延長し、ジョブ2-2より先に終わらないようにした上で、先ほどと同じステートマシンを実行します。ジョブ2-2は異常終了するように仕込んであります。すると結果として、ジョブ2-2は予定通り失敗となりましたが、ジョブ2-1はキャンセル済みという状態となりました。
この状態でリカバリ対応を行った後にステートマシンのリドライブをしてみます。
すると先ほどの実験とは異なり、ジョブ2-1とジョブ2-2の両方が再実行されました。
ジョブ2-1の構造によっては、再実行されたりされなかったりというのは困るため、以下のように工夫をする必要がありそうです。これはちょっと不便ですね。
補足:キャンセル済みとはどんな状態か
以下の記事で検証されているように、キャンセルとは単純に呼び出し元の Step Functions 上のお話のようです。