はじめに
AWS EventBridgeルールは、各種サービス間のイベント連携に非常に便利ですが、イベント配信エラーが発生した際にCloudWatchの「FailedInvocations
」メトリクスで検知できても、実際のエラーログをコンソール上で確認するのは難しい場合があります。
本記事では、主にイベント配信エラーの発生時にDLQ(デッドレターキュー)を活用してエラーログを取得する手法に焦点を当て、マネジメントコンソールとCloudFormationの両パターンでDLQ設定およびログ取得方法を解説します。
EventBridgeのエラー原因とログ確認の課題
EventBridgeで発生するエラーにはさまざまな原因がありますが、運用現場でよく見受けられる例として、以下の2つのケースが考えられます。
-
(1)ターゲット側エラー
イベント自体は正常に配信されたものの、たとえばECSタスクやSSMオートメーションなど、ターゲット側で処理中にエラーが発生するケースです。
この場合、CloudTrailのイベントログからエラーの詳細を確認できます。-
ECSタスクの場合: イベント名「
RunTask
」でフィルタリング -
SSMオートメーションの場合: イベント名「
StartAutomationExecution
」でフィルタリング
-
ECSタスクの場合: イベント名「
-
(2)イベント配信失敗エラー
EventBridgeからのイベントがそもそもターゲットに届かず、配信自体が失敗するケースです。
※ このケースは、CloudTrailにログが記録されない場合があり、こうした場合はDLQ(デッドレターキュー)を利用してエラーログを取得する方法が有効です。
【参考】
AWS公式ドキュメント:EventBridge で配信されていないイベントを処理するためのデッドレターキューの使用
DLQ設定方法
EventBridgeのイベント配信エラーログの配信先としてDLQを設定する方法を以下の2パターンでご紹介します。
- マネジメントコンソールから設定する場合
- CloudFormationで設定する場合(サンプルコードあり)
前提条件
- EventBridgeルールおよびターゲットを作成済み
- EventBridge用のIAMロールも作成済み
マネジメントコンソールからDLQを設定する場合
1. DLQ用のSQSキューを新規作成する
マネジメントコンソールにログインし、「SQS」のサービス画面を開き、「キューの作成」ボタンをクリックします。
「名前」欄に任意の名前を入力し、その他の設定はデフォルトのまま一番下の「キューを作成」ボタンをクリックしてSQSキューを作成します。
2. EventBridgeルールでDLQを設定する
DLQを設定したいEventBridgeルールの詳細画面を開き、「ターゲット」セクションの「編集」ボタンをクリックします。
すると、ターゲット情報の編集画面が開かれるので、一番下の方までスクロールしていきます。
下の方に、「追加設定」>「デッドレターキュー」という項目があるので、
ここで「デッドレターキューとして使用する、現在の AWS アカウントの Amazon SQS キューを選択
」にチェックを入れ、先ほど作成したSQSキューを選択し、EventBridgeの設定を更新します。
設定完了後、EventBridgeルールの詳細画面からDLQが正しく設定されていることを確認できます。
※ SQSキューはデフォルト設定で作成されるため、初期のキューポリシーは以下のようになります。
{
"Version": "2012-10-17",
"Id": "__default_policy_ID",
"Statement": [
{
"Sid": "__owner_statement",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::<AWSアカウントID>:root"
},
"Action": "SQS:*",
"Resource": "arn:aws:sqs:<リージョン>:<AWSアカウントID>:<SQS名>"
}
]
}
このSQSをDLQとして設定すると、以下のポリシーが自動的に追加されます。
{
"Effect": "Allow",
"Principal": {
"Service": "events.amazonaws.com"
},
"Action": "sqs:SendMessage",
"Resource": "arn:aws:sqs:<リージョン>:<AWSアカウントID>:<SQS名>",
"Condition": {
"ArnEquals": {
"aws:SourceArn": "arn:aws:events:<リージョン>:<AWSアカウントID>:rule/<EventBridgeルール名>"
}
}
}
自動追加されたポリシーは、AWS公式ドキュメントに記載のあるものと同じパターンですね。
CloudFormationでDLQを設定する場合
以下は、EventBridge ルールに DLQ用のSQSキューを指定するサンプル(抜粋)です。
イベント配信が失敗した場合、指定したDLQにエラーログが蓄積され、後から詳細を確認できます。
AWSTemplateFormatVersion: '2010-09-09'
Resources:
# EventBridgeで配信失敗したイベントを処理するDLQ
EventDlq:
Type: AWS::SQS::Queue
DeletionPolicy: Delete
UpdateReplacePolicy: Delete
Properties:
QueueName: "Event-DLQ"
MessageRetentionPeriod: 345600 # 4日
# EventBridgeのイベント配信失敗時に、DLQへエラーメッセージ送信できるようにするポリシー
EventDlqPolicy:
Type: AWS::SQS::QueuePolicy
Properties:
Queues:
- !Ref EventDlq
PolicyDocument:
Version: "2012-10-17"
Statement:
# @see https://docs.aws.amazon.com/ja_jp/eventbridge/latest/userguide/eb-rule-dlq.html#eb-dlq-perms
- Sid: "Allow EventBridge Send Message To DLQ"
Effect: Allow
Principal:
Service: "events.amazonaws.com"
Action: "sqs:SendMessage"
Resource: !GetAtt EventDlq.Arn
Condition:
ArnEquals:
"aws:SourceArn": !GetAtt EventBridgeRule.Arn
# デモ用のEventBridgeルール
EventBridgeRule:
Type: AWS::Events::Rule
Properties:
EventPattern:
source:
- "aws.ec2"
detail-type:
- "EC2 Instance State-change Notification"
detail:
state:
- "stopped"
Targets:
- Id: StartEc2Automation
Arn: !Sub "arn:${AWS::Partition}:ssm:${AWS::Region}::automation-definition/AWS-StartEC2Instance:$LATEST"
RoleArn: !GetAtt EventBridgeRole.Arn
DeadLetterConfig:
Arn: !GetAtt EventDlq.Arn # <--- ここでDLQを指定する
InputTransformer:
InputPathsMap:
instanceId: "$.detail.instance-id"
InputTemplate: !Sub |
{
"InstanceId": ["<instanceId>"],
"AutomationAssumeRole": ["${SsmAutomationRole.Arn}"]
}
デモ: 配信失敗エラーログをDLQから確認してみる
本セクションでは、意図的に EventBridge ルールのイベント配信を失敗させ、DLQに蓄積されたエラーログを実際に確認する手順を紹介します。
シナリオ
イベントのトリガー:
EC2インスタンスの停止イベント
ターゲット:
SSMオートメーション(EC2を起動する処理)
本来のフロー
- EC2インスタンスを手動で停止する
- EventBridgeルールが、EC2インスタンスの停止イベントを検知する
- EventBridgeが、SSMオートメーションに対してイベントを配信する
- SSMオートメーションが起動され、EC2インスタンスが自動的に起動される
今回のデモの流れ(意図的な設定ミスによる配信失敗)
- EC2インスタンスを手動で停止する
- EventBridgeルールが、EC2インスタンスの停止イベントを検知する
- 設定に不備があるため、EventBridgeからのイベント配信が失敗する
- 配信失敗エラーがDLQに蓄積されるので、DLQ内のエラーログを確認する
このデモを通じて、設定ミスやその他の理由でイベント配信が失敗した場合に、DLQを活用してエラーログを取得する方法を確認いただけます。
デモ
1. 意図的にEventBridgeルールの設定を間違える
EventBridgeRule:
Type: AWS::Events::Rule
Properties:
EventPattern:
source:
- "aws.ec2"
detail-type:
- "EC2 Instance State-change Notification"
detail:
state:
- "stopped"
Targets:
- Id: StartEc2Automation
Arn: !Sub "arn:${AWS::Partition}:ssm:${AWS::Region}::automation-definition/AWS-StartEC2Instance:$LATEST"
RoleArn: !GetAtt EventBridgeRole.Arn
DeadLetterConfig:
Arn: !GetAtt EventDlq.Arn
InputTransformer:
InputPathsMap:
instanceId: "$.detail.instance-id"
InputTemplate: !Sub |
{
"InstanceId": ["<instanceId>"],
### ↓ ここの設定値を誤ったものに変更する ###
"AutomationAssumeRole": "${SsmAutomationRole.Arn}"
}
上記は先ほどご紹介したCloudFormationのサンプルコードのEventBridge抜粋部分ですが、
一番最後の値を
"AutomationAssumeRole": ["${SsmAutomationRole.Arn}"]
↓
"AutomationAssumeRole": "${SsmAutomationRole.Arn}"
に変更しました。(本来は配列であるべきですが、ただの文字列にしました)
- 【参考】
- StartAutomationExecution APIのリファレンス
-
Parameters
は配列(array)で渡す必要があります
2. EC2インスタンスを停止する
マネジメントコンソールなどから、任意のEC2インスタンスを1つ停止させます。
3. イベント配信が失敗する
EventBridgeルールの詳細画面の「モニタリング」タブを確認すると、
FailedInvocations
メトリクスのカウントが1になっていますね。
(反映されるのに5分ほどかかるかもしれません)
4. DLQからエラーメッセージを確認する
DLQ用に作成したSQSキューの詳細画面を開き、「メッセージを送受信」ボタンをクリックします
「メッセージをポーリング」ボタンをクリックすると、イベント配信失敗時のエラーメッセージを取得できます。
メッセージの中身を確認してみましょう。
「本文」タブを見てみると、EventBridgeルールに設定したパラメータが表示され、
"AutomationAssumeRole"
の値が配列でなく文字列になっているのが確認できます。
続いて、「属性」タブを見てみると、以下のエラーメッセージが表示されています。
- ERROR_CODE:
INVALID_JSON
- ERROR_MESSAGE:
Invalid input for target.
この結果、InputTransformerに指定した値の形式が不正であったため、イベント配信に失敗したことが確認できます。
参考:CFnサンプルテンプレート全文
以下は、今回のデモで使用したCloudFormationテンプレート全文です。
※ EventBridgeルールの設定値は、意図的に変更した部分以外は正しい設定になっています。
AWSTemplateFormatVersion: '2010-09-09'
Description: |
EventBridgeでEC2停止イベントを受け取り、SSMオートメーションを実行する。
EventBridgeルールとSSMオートメーションを連携した動作確認用の構成。
Parameters:
AmiId:
Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
Default: /aws/service/ami-amazon-linux-latest/al2023-ami-kernel-6.1-x86_64
Resources:
# EventBridgeルール
EventBridgeRule:
Type: AWS::Events::Rule
Properties:
EventPattern:
source:
- "aws.ec2"
detail-type:
- "EC2 Instance State-change Notification"
detail:
state:
- "stopped"
Targets:
- Id: StartEc2Automation
Arn: !Sub "arn:${AWS::Partition}:ssm:${AWS::Region}::automation-definition/AWS-StartEC2Instance:$LATEST"
RoleArn: !GetAtt EventBridgeRole.Arn
DeadLetterConfig:
Arn: !GetAtt EventDlq.Arn
InputTransformer:
InputPathsMap:
instanceId: "$.detail.instance-id"
InputTemplate: !Sub |
{
"InstanceId": ["<instanceId>"],
"AutomationAssumeRole": ["${SsmAutomationRole.Arn}"]
}
# EventBridge用のIAMロール
EventBridgeRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service:
- events.amazonaws.com
- ssm.amazonaws.com
Action: sts:AssumeRole
Policies:
- PolicyName: "AllowSsmAutomation"
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- ssm:StartAutomationExecution
- ssm:GetAutomationExecution
Resource: !Sub "arn:${AWS::Partition}:ssm:${AWS::Region}::automation-definition/AWS-StartEC2Instance:*"
- Effect: Allow
Action: iam:PassRole # SSMオートメーションの引数にロールを渡すために必要
Resource: !GetAtt SsmAutomationRole.Arn
# SSMオートメーション用のIAMロール
SsmAutomationRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service: ssm.amazonaws.com
Action: sts:AssumeRole
Policies:
- PolicyName: InvokeSSMAutomationPolicy
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- ec2:StartInstances
- ec2:DescribeInstances
- ec2:DescribeInstanceStatus
Resource: "*"
# EventBridgeで配信失敗したイベントを処理するDLQ
EventDlq:
Type: AWS::SQS::Queue
DeletionPolicy: Delete
UpdateReplacePolicy: Delete
Properties:
QueueName: "Event-DLQ"
MessageRetentionPeriod: 345600 # 4日
# EventBridgeのイベント配信失敗時に、DLQへエラーメッセージ送信できるようにするポリシー
EventDlqPolicy:
Type: AWS::SQS::QueuePolicy
Properties:
Queues:
- !Ref EventDlq
PolicyDocument:
Version: "2012-10-17"
Statement:
# @see https://docs.aws.amazon.com/ja_jp/eventbridge/latest/userguide/eb-rule-dlq.html#eb-dlq-perms
- Sid: "Allow EventBridge Send Message To DLQ"
Effect: Allow
Principal:
Service: "events.amazonaws.com"
Action: "sqs:SendMessage"
Resource: !GetAtt EventDlq.Arn
Condition:
ArnEquals:
"aws:SourceArn": !GetAtt EventBridgeRule.Arn
Ec2Instance:
Type: AWS::EC2::Instance
Properties:
ImageId: !Ref AmiId
InstanceType: t2.micro
Tags:
- Key: Name
Value: !Ref "AWS::StackName"