Closed8
スポットインスタンスの停止をEventBridge+SNSで受け取る
参考になりそう
やりたいこと
スポットインスタンス中断の2分前の通知をEventBridgeで受け取りたい
EventBridgeで受け取れたら後はSNSなりLambdaなりで自由に料理出来る
手動でやる
ひとまずEventBridge + SNSの構成を作る
- SNSトピック設定
- EventBridgeルール作成
- ターゲットはSNSトピック
- イベントパターンの指定はこんな感じ
{
"source": ["aws.ec2"],
"detail-type": ["EC2 Spot Instance Interruption Warning"]
}
これで前回作ったFISを動かす
メール
SNSからメールが届く
こちらがSNSでそのまま送信されているようです
{
"version": "0",
"id": "12345678-1234-1234-1234-123456789012",
"detail-type": "EC2 Spot Instance Interruption Warning",
"source": "aws.ec2",
"account": "123456789012",
"time": "yyyy-mm-ddThh:mm:ssZ",
"region": "us-east-2",
"resources": ["arn:aws:ec2:us-east-2:123456789012:instance/i-1234567890abcdef0"],
"detail": {
"instance-id": "i-1234567890abcdef0",
"instance-action": "action"
}
}
通知方法
上記のようにEventBridgeにイベントが発行される方法と、インスタンスメタデータ内に停止情報が発行される方法の2種類あるらしい
今回は割愛するが、この内容をRunCommandで出力してもトリガーにできそうです
Terraform化
SNS
resource "aws_sns_topic" "topic" {
name = "spot-notice-topic"
fifo_topic = false
}
resource "aws_sns_topic_subscription" "subscription" {
topic_arn = aws_sns_topic.topic.arn
protocol = "email"
endpoint = var.email
}
実行したら指定したメールアドレスに確認のメールが飛ぶため、承認する
SNSトピックアクセスポリシー
デフォルトだとEventBridge→SNSの連携がうまく行かないため、こちらも明示的に設定する必要がある
resource "aws_sns_topic_policy" "policy" {
arn = aws_sns_topic.topic.arn
policy = data.aws_iam_policy_document.sns_topic_policy.json
}
data "aws_iam_policy_document" "sns_topic_policy" {
statement {
effect = "Allow"
actions = ["SNS:Publish"]
principals {
type = "Service"
identifiers = ["events.amazonaws.com"]
}
resources = [aws_sns_topic.topic.arn]
}
}
SNSアクセスポリシーはどうなっていたの?
明示的に指定しないと以下のようになっていました。
{
"Version": "2008-10-17",
"Id": "__default_policy_ID",
"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": "arn:aws:sns:ap-northeast-1:xxxxxxxxxxxx:spot-notice-topic",
"Condition": {
"StringEquals": {
"AWS:SourceOwner": "xxxxxxxxxxxx"
}
}
}
]
}
"SNS:Publish"
は存在しているので、Actionでは問題なさそうです。
おそらくCondition
句でAWSアカウントを指定しているため、それに該当しないEventBridgeのイベントが弾かれた?と考えます
EventBridge
ルールと、ターゲットの2つを設定します
resource "aws_cloudwatch_event_rule" "spot-interruption-rule" {
name = "spot-interruption-rule"
event_bus_name = "default"
tags = {
Name = "spot-interruption-rule"
}
event_pattern = <<EOF
{
"source": ["aws.ec2"],
"detail-type": ["EC2 Spot Instance Interruption Warning"]
}
EOF
}
resource "aws_cloudwatch_event_target" "sns" {
rule = aws_cloudwatch_event_rule.spot-interruption-rule.name
arn = aws_sns_topic.topic.arn
}
公式ドキュメントのサンプルを参考にすればよいでしょう。
リソース名はaws_cloudwatch_event_rule
なんですね、過去の名残?
このスクラップは2023/06/09にクローズされました