【AWS Batch】CloudFormationでエラーコードやステータス理由によるリトライ設定を行う方法

AWS Batchを使ってジョブを実行していると、ネットワークやコンテナの不安定な挙動によりジョブが失敗することがあります。こうした一時的な問題に対しては、リトライポリシーを設定することで、ジョブの安定性を向上させることができます。

本記事では、CloudFormationテンプレート上で、`EvaluateOnExit` を使って特定のエラーコードやステータス理由に基づいてジョブをリトライする方法について紹介します。

```yaml
EvaluateOnExit:
  - OnExitCode: "140"
    OnStatusReason: "Waiting for the network interface to be provisioned timed out."
    Action: RETRY
  - OnReason: "Essential container in task exited"
    Action: RETRY
  - OnExitCode: "*"
    Action: EXIT
```
#
### 1. 背景：EvaluateOnExitとは？
`EvaluateOnExit` は、AWS Batchのジョブ定義（JobDefinition）内の `RetryStrategy` の一部であり、ジョブが異常終了した場合に、どの条件でリトライを行うか／終了するかを細かく指定できます。

指定可能な条件には、以下のものがあります：
- `OnExitCode`: コンテナが返す終了コード（例: `"140"`はセグメンテーションフォールト）
- `OnReason`: ECSで発生する汎用的な理由（例: `"Essential container in task exited"`）
- `OnStatusReason`: ECSが報告する詳細なステータス理由（例: `"Timeout waiting for network interface provisioning to complete."`）

### 2. 具体的なユースケース
以下のようなジョブ定義のテンプレートがあったとします：

```yaml
MyBatchJobDefinition:
  Type: AWS::Batch::JobDefinition
  Properties:
    Type: container
    ContainerProperties:
      Image: your-image
      Memory: 2048
      Vcpus: 1
    RetryStrategy:
      Attempts: 3
      EvaluateOnExit:
        - OnExitCode: "140"
          OnStatusReason: "Timeout waiting for network interface provisioning to complete."
          Action: RETRY
        - OnReason: "Essential container in task exited"
          Action: RETRY
        - OnExitCode: "*"
          Action: EXIT
```
### ポイント解説：
- `OnExitCode: "140"`:
Unix系で「セグメンテーションフォールト」を意味します。
- `OnStatusReason`:
タスクが ENI（Elastic Network Interface）のプロビジョニングに失敗した際に報告される典型的な理由。
- `OnReason: "Essential container in task exited"`:
コンテナが何らかの理由で異常終了した際の ECS タスクレベルの理由。
- `Action: RETRY`:
条件に合致した場合、リトライを試みる。
- `Action: EXIT`:
条件に合致しなければ、リトライせずに失敗として終了。

### 3. 注意点とTips
- `OnExitCode` は文字列で指定します（数値ではなく `"0"`, `"1"` など）。
- `EvaluateOnExit` は最大5つまで定義可能です。
- より細かく制御したい場合、`OnExitCode`と`OnStatusReason`を組み合わせることで、特定ケースのみリトライ可能です。
- `EvaluateOnExit` は `RetryStrategy` がある場合にのみ指定できます。

### 4. AWS CLIでのジョブ定義登録例
CloudFormationを使わずにAWS CLIでジョブ定義を登録する場合も、同様に retryStrategy と evaluateOnExit を含めることができます。

以下は、aws batch register-job-definition を使ってジョブ定義を作成するコマンドの例です。

```bash
aws batch register-job-definition \
  --job-definition-name my-cli-job-def \
  --type container \
  --container-properties '{
      "image": "your-image",
      "vcpus": 1,
      "memory": 2048
  }' \
  --retry-strategy '{
      "attempts": 3,
      "evaluateOnExit": [
        {
          "onExitCode": "140",
          "onStatusReason": "Timeout waiting for network interface provisioning to complete.",
          "action": "RETRY"
        },
        {
          "onReason": "Essential container in task exited",
          "action": "RETRY"
        },
        {
          "onExitCode": "*",
          "action": "EXIT"
        }
      ]
  }'
```

### 補足：
- CLIでは `--container-properties` や `--retry-strategy` にJSON文字列を直接渡します。
- クォートのネストに注意してください（特にWindowsユーザーはシングル/ダブルクォートの使い分けに注意が必要です）。
- `attempts` で最大リトライ回数（3回）を指定しています。
#
### 5. まとめ
AWS Batchでは、リトライ戦略を適切に設計することで、一時的な障害に強いジョブ処理を実現できます。CloudFormationでこれらのポリシーをコード化しておけば、インフラの安定性を維持しつつ再現性のあるデプロイが可能です。

### 参考リンク
https://docs.aws.amazon.com/batch/latest/userguide/job_definition_parameters-copy.html#retryStrategy

https://docs.aws.amazon.com/AmazonECS/latest/developerguide/scheduling_tasks.html#task-lifecycle