AWS Step Functions で再実行ができるようになったので、ジョブネットのエラー対応をどれだけ実現できるか試してみます。まずはシンプルなステートマシンを使用して確認します。
想定するジョブネット
説明をわかりやすくするために、用語は以下の通りとします。
実行する処理をジョブと呼びます。ジョブはシェルスクリプトで実装されていて、EC2上で稼働する前提とします。そして、複数のジョブをつなげて実行する塊をジョブネットと呼びます。
本記事で想定するジョブネットは以下とします。
ジョブネット再実行のパターン
本記事では以下の基本的な3パターンの実装を試みてみます。結論としてパターン1とパターン3は Step Functions の再実行機能を用いて簡単に手動再実行できますが、パターン2はあらかじめステートマシンの定義を工夫して自動処理としておくなどの対応が必要です。
- 異常終了したジョブから再実行
- 異常終了したジョブの次から再実行
- 異常終了したジョブが含まれるジョブネット全体を再実行
実装の概要
aws-samples の amazon-stepfunctions-ssm-waitfortasktoken を利用した SfnRunCommandByInstanceIds を用いて Steps Functions に以下のようなステートマシンを定義しました。
{
"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-xxxxxxxxxxxxxxxxxx"
],
"taskToken.$": "States.Array($$.Task.Token)",
"workingDirectory": [
"/home/ec2-user/sample-batch/"
],
"Commands": [
"./do-some1.sh"
]
}
},
"Next": "StartAutomationWaitForCallBack (Job 2)"
},
"StartAutomationWaitForCallBack (Job 2)": {
"Type": "Task",
"Resource": "arn:aws:states:::aws-sdk:ssm:startAutomationExecution.waitForTaskToken",
"Parameters": {
"DocumentName": "SfnRunCommandByInstanceIds",
"Parameters": {
"InstanceIds": [
"i-xxxxxxxxxxxxxxxxxx"
],
"taskToken.$": "States.Array($$.Task.Token)",
"workingDirectory": [
"/home/ec2-user/sample-batch/"
],
"Commands": [
"./do-some2.sh"
]
}
},
"Next": "StartAutomationWaitForCallBack (Job 3)"
},
"StartAutomationWaitForCallBack (Job 3)": {
"Type": "Task",
"Resource": "arn:aws:states:::aws-sdk:ssm:startAutomationExecution.waitForTaskToken",
"Parameters": {
"DocumentName": "SfnRunCommandByInstanceIds",
"Parameters": {
"InstanceIds": [
"i-xxxxxxxxxxxxxxxxxx"
],
"taskToken.$": "States.Array($$.Task.Token)",
"workingDirectory": [
"/home/ec2-user/sample-batch/"
],
"Commands": [
"./do-some3.sh"
]
}
},
"End": true
}
}
}
なお、使用しているシェルは以下のように filetest2というファイルがあるとエラーを返すように実装しています。
#!/bin/bash
if [ $# -ne 0 ]; then
echo "引数は$#個です" 1>&2
echo "引数を指定してはいけません" 1>&2
exit 1
fi
for i in {1..3} ; do
echo "Doing Something #2" ${i}
sleep 1
done
if [ -f ./filetest2 ]; then
exit 1
fi
exit 0
パターン1:異常終了したジョブから再実行
これが今回できるようになったパターンですね。ジョブ2をエラーとするために touch /home/ec2-user/sample-batch/filetest2
でファイルを作ってから上記のステートマシンを実行します。
ここでリカバリ対応としてrm /home/ec2-user/sample-batch/filetest2
をしてから、ステートマシンに対してリドライブを指示します。リドライブはマネジメントコンソールの以下の画面から行います。
以下のような確認ダイアログが表示されます。確かにジョブ2から再実行と表示されています。
ちなみに、同じくマネジメントコンソールの以下の部分からもリドライブが可能です。
パターン2:異常終了したジョブの次から再実行
前述の通り、リドライブをするとジョブ2も再実行されてしまうので事後対応はできません。 事前に Step functions のステートマシン定義にエラーをキャッチして次のアクションに進むように定義をしておく必要があります。
具体的にはジョブ2のアクションの「エラーをキャッチ」の設定で "Statues.TaskFailed" をキャッチして次のアクションであるジョブ3に進むよう定義しておきます。
この定義を行っておくと、ジョブ2がエラーとなる状態でステートマシンを実行しても、ステートマシン全体としては成功となりますが、ジョブ2のアクションは「キャッチされたエラー」として表示されます。
ただ、この設定をステートマシンにしてしまうとリドライブができません。現時点では実行したい処理のエラー対応要件によって使い分けるしかないかと思います。
パターン3:異常終了したジョブが含まれるジョブネット全体を再実行
これは以前から実現できていました。単純に新たにステートマシンを実行することとなります。先ほどと同じくジョブ2がエラー停止した状態とした上で、マネジメントコンソールの "Recovery"の "Start New Execution" から再度ステートマシン全体を実行可能です。
新たに実行を開始する画面が表示されるため「実行を開始」をクリックします。
なお、この方法だと「失敗」ステータスとなった実行は失敗のまま残ることとなります。
本記事では AWS Step Functions の再実行パターンをシンプルなステートマシンを用いて確認してみました。リドライブができることでこれまで以上に Step Functions の用途が広がることになると思います。