🔖

AWS Batch: 配列ジョブの完了を待ってから通知する

2023/04/24に公開

業務でAWS Batchに触れる機会がありましたので、困ったところを記事にしたいと思います。

経緯

当初、複数のジョブを配列ジョブ等は使用せず、lambda上からsubmitしていましたが、グループ化されていたほうが扱いやすいといったことから配列ジョブを使用した方法を検討しようということになりました。

単にジョブのステータスの変更によって、イベント通知を行う方法は記事が見つかりましたが、ジョブ全体の完了通知を行う方法は見つけることができなかったので、メモ程度に残しておこうと思います。

具体的には画像のような形式となります。
完了通知が発火されると後続のlambdaが実行される形式です。

実装

事前準備

チュートリアルのステップ3のBatchにジョブ定義を行うところまで進めてください。

その他設定
コンピューティング環境

  • EC2 のプロビジョニングモデルを使用
  • 名称は「print-color-computing」
  • インスタンスロールにAdministarAccess

ジョブキュー

  • 名称は「print-color-queue」

lambda, eventBridgeの作成

batchが終了した後に呼び出されるlambdaとeventBridgeの設定を行います。

def lambda_handler(event, context):
    arrayProperties = event["detail"].get("arrayProperties", dict())
    print(arrayProperties.get("index", "root"))
イベントパターン
{
  "source": ["aws.batch"],
  "detail-type": ["Batch Job State Change"],
  "detail": {
    "jobDefinition": ["チュートリアルで作成したjobDefinitionのArn"],
    "status": ["SUCCEEDED"]   // 成功時のみ通知
  }
}

一旦、submit

チュートリアルと同様、jobをsubmitしてみます。

print-color-job.json
{
  "jobName": "print-color",
  "jobQueue": "print-color-queue",
  "arrayProperties": {
    "size": 7
  },
  "jobDefinition": "print-color"
}
aws batch submit-job --cli-input-json file://print-color-job.json

成功すると写真のように、lambda側で配列のindex情報がログに表示されると思います。
実行回数としては8回(親ジョブと子ジョブの合計)です。

親ジョブだけを通知するように修正する

親ジョブと子ジョブでイベント情報の違いを確認してみます。
*全て載せるとかなり長いので、不要なところは削除しています。

子ジョブ
{
  "version": "0",
  "detail-type": "Batch Job State Change",
  "source": "aws.batch",
  "detail": {
    "attempts": [
      {
        "container": {
          "containerInstanceArn": "",
          "taskArn": "",
          "exitCode": 0,
          "logStreamName": "",
          "networkInterfaces": []
        },
        "startedAt": 0,
        "stoppedAt": 0,
        "statusReason": "Essential container in task exited"
      }
    ],
    "statusReason": "Essential container in task exited",
    "container": {
      "image": "",
      "command": [],
      "volumes": [],
      "environment": [],
      "mountPoints": [],
      "ulimits": [],
      "exitCode": 0,
      "containerInstanceArn": "",
      "taskArn": "",
      "logStreamName": "",
      "networkInterfaces": [],
      "resourceRequirements": [
        {
          "value": "250",
          "type": "MEMORY"
        },
        {
          "value": "1",
          "type": "VCPU"
        }
      ],
      "secrets": []
    },
    "arrayProperties": {
      "statusSummary": {},
      "index": 1
    }
  }
}
親ジョブ
{
  "version": "0",
  "detail-type": "Batch Job State Change",
  "source": "aws.batch",
  "detail": {
    "attempts": [],
    "container": {
      "image": "",
      "command": [],
      "volumes": [],
      "environment": [],
      "mountPoints": [],
      "ulimits": [],
      "networkInterfaces": [],
      "resourceRequirements": [
        {
          "value": "250",
          "type": "MEMORY"
        },
        {
          "value": "1",
          "type": "VCPU"
        }
      ],
      "secrets": []
    },
    "arrayProperties": {
      "statusSummary": {
        "STARTING": 0,
        "FAILED": 0,
        "RUNNING": 0,
        "SUCCEEDED": 2,
        "RUNNABLE": 0,
        "SUBMITTED": 0,
        "PENDING": 0
      },
      "size": 2
    }
  }
}

見比べてみるといくつか違いがわかります。
"arrayProperties"の要素が"size"と"index"で異なっていたり、子ジョブの方の"container"の中には実行したコンテナ情報やログの情報などが入っていますね。

これらの違いを利用して親ジョブの完了時のみ、lambdaを実行するように修正します。
*今回はイベントスキーマに記載のある項目の中から選択していますが、親ジョブと子ジョブで異なる要素であれば、なんでも構いません。

イベントパターン(修正後)
{
  "source": ["aws.batch"],
  "detail-type": ["Batch Job State Change"],
  "detail": {
    "jobDefinition": ["チュートリアルで作成したjobDefinitionのArn"],
    "status": ["SUCCEEDED"],  // 成功時のみ通知
    "container": {
      "containerInstanceArn": [{
        "exists": false
      }]
    }
  }
}

動作確認

再度、ジョブを送信してみます。
lambdaから実行回数を確認してみると8回 → 1回に減ったことが確認できると思います。

まとめ

今回は配列ジョブの親ジョブの終了に伴って通知を行う方法をご紹介しました。
AWSは今回のようにレスポンスの要素が違っていて、なかなか気づけないことも多いですが、今後もこのような形で記事にできればと思います。

以上です。

Discussion