CloudFormation 一撃でBatchでジョブが失敗したときに通知する仕組みを構築する

CloudFormation一撃シリーズに入門。Batchでジョブが失敗した時の通知する仕組みを一撃で構築します。
2021.03.30

こんにちは。AWS事業本部のKyoです。

AWS Batchを利用していて、「このジョブいつ終わるんや・・・あ、失敗してた・・・。」みたいな切ない状況になったことはありませんか?

Event Bridge + SNSでジョブが失敗したら通知を飛ばすというシンプルな設定をCloudFormationでテンプレート化したのでご利用ください。

また、少し手を加えることで、ジョブの成功、失敗を問わず通知を飛ばすことも可能です。

テンプレート

AWSTemplateFormatVersion: 2010-09-09

Parameters:
  MailAddress:
    Description: Enter email address to send notification.
    Type: String
  AlertName:
    Description: Enter alert name.
    Type: String
    Default: JobFailedAlert

Resources:
  SnsTopic:
    Type: AWS::SNS::Topic
    Properties:
      TopicName: !Sub ${AlertName}-topic

  SnsSubscription:
    Type: AWS::SNS::Subscription
    Properties:
      Endpoint: !Ref MailAddress
      Protocol: email
      TopicArn: !Ref SnsTopic

  SnsTopicPolicy:
    Type: AWS::SNS::TopicPolicy
    Properties:
      PolicyDocument:
        Version: 2012-10-17
        Statement:
        - Sid: __default_statement_ID
          Effect: Allow
          Principal:
            AWS: "*"
          Action:
            - SNS:GetTopicAttributes
            - SNS:SetTopicAttributes
            - SNS:AddPermission
            - SNS:RemovePermission
            - SNS:DeleteTopic
            - SNS:Subscribe
            - SNS:ListSubscriptionsByTopic
            - SNS:Publish
            - SNS:Receive
          Resource: !Ref SnsTopic
          Condition:
            StringEquals:
              AWS:SourceOwner: ${AWS::AccountId}
        - Sid: AWSEvents_Alert
          Effect: Allow
          Principal:
            Service:
            - events.amazonaws.com
          Action: sns:Publish
          Resource: !Ref SnsTopic
      Topics:
      - !Ref SnsTopic

  CwEventRule:
    Type: AWS::Events::Rule
    Properties:
      Name: !Sub ${AlertName}-rule
      Description: !Ref AlertName
      EventPattern: |
        {
          "detail-type": [
            "Batch Job State Change"
          ],
          "source": [
            "aws.batch"
          ],
          "detail": {
            "status": [
              "FAILED"
            ]
          }
        }
      Targets:
        - Arn: !Ref SnsTopic
          Id: SnsAlertMail

宛先のメールアドレスを入力してCloudFormationを実行し、Subscription Confirmationメールのリンクをクリックすれば準備は完了です。

なお、今回のテンプレートは以下のブログで紹介されているものとほぼ同じ構成であることに気づいた方もいるかもしれません。SNSのメール通知をうっかりunsubscribeしないようにする設定も同じ方法が使えます。

結果が成功でも失敗でも通知したい場合

今回のテンプレートではEventBrigdeでBatchジョブのステータス変化を見ているので、成功でも失敗でも、ジョブが完了したことを通知したい場合はCwEventRule中のstatusSUCCEEDEDorFAILEDの両方を設定してください。

##### 前略 ##### 
  CwEventRule:
    Type: AWS::Events::Rule
    Properties:
      Name: !Sub ${AlertName}-rule
      Description: !Ref AlertName
      EventPattern: |
        {
          "detail-type": [
            "Batch Job State Change"
          ],
          "source": [
            "aws.batch"
          ],
          "detail": {
            "status": [
              "SUCCEEDED",
              "FAILED"
            ]
          }
        }
      Targets:
        - Arn: !Ref SnsTopic
          Id: SnsAlertMail

やってみる

Batchの環境は構築できているものとし、設定が機能することを確認します。

新規ジョブで以下のコマンドを実行する設定にします。

/bin/sh, -c, 'exit 1'

試した限り、ほとんどタイムラグなくメールが届きました。

JSON中のstatusSUCCEEDEDorFAILEDの情報が含まれているので、成功でも失敗でも通知するようにしている場合は、それをもとにジョブの状態を判断することもできます(矢印)。

終わりに

本ブログではAWS Batchのジョブが失敗した時にEvent Bridgeで通知するCloudFormationテンプレートを紹介しました。

単純ではあるものの、長時間待たされた挙句、いつの間にかジョブも失敗しているみたいなモヤモヤする状態を回避できるので、コスパのいい設定だと思います。

なお、メールで届く巨大JSONはお世辞にも見やすいとはいえないので、必要に応じてAWS::Events::Ruleの中でInputTransformerを設定してみてもよいかもしれません。

AWS::Events::Rule InputTransformer

また今回はメール通知でしたが、SNSのエンドポイントをLambdaにするなどしてステータスの変更ごとにSlack通知しても便利かもしれません(より簡単に済ませたい場合はメールをSlack通知する、という方法もアリだと思います)。

以上、何かのお役に立てれば幸いです。

参考