giftee Tech Blog

ギフティの開発を支えるメンバーの技術やデザイン、プロダクトマネジメントの情報を発信しています。

Aurora MySQL のイベント通知を設定しよう!(してなかった)

thumnail

おはようございます。エンジニアの chota60 です。

この記事は、ギフティ Advent Calendar 2025 の 8 日目裏番組(シリーズ2)です。

ここでは、Aurora MySQL の Engine Version 自動マイナーバージョンアップグレードが暴発してしまった件に端を発して、イベント通知を有効にしたという話をしていきます。

イベント通知の機能と Chatbot 周りの仕組みの噛み合わせは明確に理解できていないこともあり、「自分がどうにかやってみたところこんな感じだった」という体験談として読んでもらえたら幸いです!

この記事のメインの内容は下記の三点です。

  • AWS Health だけでは、自動マイナーバージョンアップグレードの通知を拾えなかったこと
  • Aurora MySQL / RDS のイベント通知の基本と、どのイベントを拾うかという設計方針
  • Terraform を使う場合の具体的な設定例

前日譚

  • Aurora MySQL の Engine Version EOL に伴い、自動マイナーバージョンアップグレードが発生してしまった
    • ユーザー影響は発生しなかった模様
  • そもそも設定としては無効にしておけばよかったものの、こんな重要な変更をなぜ検知できなかったのか?という課題が生じた

自動マイナーバージョンアップグレードは、AWS Health の通知では送信されない

Engine Version の EOL については、AWS Health で通知されていました。

rds_lifecycle_event_on_health

一方で、RDS インスタンス単位の自動マイナーバージョンアップグレードは、AWS Health では通知されていませんでした。

疑問に思い、ドキュメントを調べていくと、特定のインスタンスにおける自動マイナーバージョンアップグレードの予告通知を受け取るには、Aurora MySQL のイベント通知機能を利用する必要があることがわかりました。

RDS / Aurora のイベント通知機能

管理者が操作したり、AWS 側でメンテナンスしたり、稼働中の RDS には様々なイベントが発生します。 それらのイベントの通知を行うため、イベントサブスクリプション、ないしイベント通知サブスクリプションと呼ばれるリソースが存在します。

これは、ざっくり言うと「どの種類のイベントを、どの DB を対象に、どの SNS Topic に飛ばすか」をまとめたモノです。

docs.aws.amazon.com

イベントたちはそれぞれ、発生起因のリソースごとに定義されています。

例えば、Aurora MySQL の場合、クラスターの単位で起きるイベントがあるほか、インスタンスやパラメータグループなどの単位でイベントが発生します。

docs.aws.amazon.com

RDS の場合でも同様に、さまざまなイベントが発生し、それに対応した記録が行われます。微妙に設定できる種類が違うので注意した方が良さそうです

docs.aws.amazon.com

先立って生じたマイナーバージョン間の自動アップグレードについても、クラスターイベントで通知されることがわかりました。

docs.aws.amazon.com

マイナーバージョンの自動アップグレードは、カテゴリが maintenance で ID が RDS-EVENT-0156 の Amazon RDS DB クラスターイベントを通じて事前に通知されます。詳細については、「Aurora の Amazon RDS イベントカテゴリとイベントメッセージ」を参照してください。

メッセージ上は「できる」なのですが、どうやら「できる」ようになった後、最初のメンテナンスウィンドウで適用されてしまうようですね。

さて、概要は理解したので今後の憂いを断つため、イベント通知の設定をしておきましょう!

イベント通知の方針

まずはイベント通知設定のあるべき姿を考えていきます。 今回検知すべきだったイベントだけを対象に考えればいいのかと言えば、それは No です(=今回の件だけを見て最小限に済ませる話ではない)。

これまではこの機能を知らなかったから設定してなかったのであって、その通知だけを意図的に無効化していたわけではないため、そもそものあるべき設定から考慮し直していきます。

先に方針をざっくりまとめると、「通知対象を可用性に直結する cluster / instance に絞りつつ、カテゴリは広めに拾っておき、実際の通知頻度を見ながらノイズを削っていく」としました。

イベント通知対象のソースタイプ

結構種類があります。

以下のタイプが存在します。

  • DB cluster events
  • DB cluster snapshot events
  • DB instance events
  • DB parameter group events
  • DB security group events
  • DB shard group events
  • RDS Proxy events
  • Blue/green deployment events

どのタイプを通知対象にするか

これらの二つに関するイベントは、可用性に大きく関わるため、積極的に拾う設定とします。

  • DB cluster events
  • DB instance events

その他のタイプについてはまだ一旦は対象外でいいんじゃないかな・・・と思います。

どのカテゴリーを通知対象にするか

通知対象のタイプごとに、通知可能なカテゴリーが定義されています。 まずは広く拾えることを大方針とし、確実に不要だと思われるもの以外を設定します。

設定方法

次に、具体的な設定方法を考えます。といっても、今回対象とするもののインフラ環境は Terraform で IaC されているため、Terraform でどう記述すれば良いのかを考えれば OK です。

aws_db_event_subscription リソースを使う

こちらのドキュメントに全てが書いてあります。

registry.terraform.io

source_type

前述の通り、二つの種類のイベントに関する設定を行います。

  • DB cluster events
  • DB instance events

これらの source_type はそれぞれで対応する event_categories が異なります。

docs.aws.amazon.com

従って、Terraform 上も source_type ごとに resource を定義したほうが、今後起きるかもしれない設定変更に備えることができ、良さそうです。

event_categories

前項の通り、source_type ごとにカテゴリーが異なります、 参考ドキュメントをもとに設定します。

docs.aws.amazon.com

再掲ですが、通知量しだいではあるものの見逃すことを避けたいので、確実に不要と思われるもの以外を通知できるようにそれぞれ設定します。

具体的には下記の設定とします。

db-cluster

  • configuration change
  • creation
  • deletion
  • failover
  • failure
  • maintenance
  • notification

除外するもの

  • global failover
    • マルチ region な構築をしていないので不要です

db-instance

  • availability
  • backtrack
  • configuration change
  • creation
  • deletion
  • failure
  • low storage
  • maintenance
  • notification
  • read replica
  • recovery
  • restoration
  • security patching

除外するもの

  • serverless
    • 今回対象の環境はサーバレスではありません
  • global database
    • マルチ region な構築をしていないので不要です

通知先の設定

イベントサブスクリプションは、あくまで RDS それぞれのイベントを購読する役割を持ちます。 イベントの通知処理は、SNS Topic を介して行われます。

従って、設定上も通知先の SNS Topic の作成、および指定が必要になります。

Chatbot を送信先とする SNS Topic は直接連携できなさそう

今回のイベントの通知設定をする以前に、CloudWatch と繋ぎ込んだ SNS Topic + Chatbot の仕組みがありました。しかし、どうやら RDS イベントサブスクリプションは Chatbot との連携対象外だったので諦めました。

いろいろ試してみたのですが、どうやら以下のように Chatbot 側の制約があり、RDS のイベントサブスクリプションの通知は送信できないようでした(無念ですが・・・)。

採用:通知先を Slack チャンネルの email address とする

  • SNS Topic は、送信先に email を指定できる
  • Slack のチャンネルは、特定の email アドレス宛にきたメールをそのチャンネルに送信することができる

これらの機能を組み合わせることで、購読した RDS 上のイベントを email 経由で Slack チャンネル上に送信することが可能になります。

今回は特に細やかなイベントの判定処理が不要であり、シンプルな設定であるほど嬉しかったので、こちらの方法を採用しました。

不採用:EventBridge に切り替える方法

代替案として、EventBridge を通して通知する方法がありそうです。

docs.aws.amazon.com

ですがこちらの手段を選ぶ場合、当然 Lambda のリソースおよび関数を保守する必要が生じます。

逆に言えば Lambda を実装するだけなので、非常に細やかな制御が可能です。

従って、「とても細かくイベントの種類を制御したい」もしくは「どうしても複雑な仕掛けを導入してみたい」みたいなヘンテコな要望がない限りは、この選択肢を選ぶ必要はないのではないかと思います。

作成した Terraform のイメージ

ここまでに設計してきた内容で、Terraform を作成します。

あくまでイメージですが、このような module を作って対応しました。

Aurora 本体の設定を補完・強化するリソース群になるため、Aurora 本体の設定から独立した module として実装しています。

###
# SNS: Aurora イベント通知を集約するトピック
###
resource "aws_sns_topic" "aurora_event" {
  # 例: myservice-prd-aurora-event-sns-topic
  name = "my-aurora-event-sns-topic"
}

# Slack チャンネルのメールアドレスを購読者として登録する
# (Slack 側で Email Integration を有効化しておく前提)
resource "aws_sns_topic_subscription" "slack_channel_subscription" {
  topic_arn = aws_sns_topic.aurora_event.arn
  protocol  = "email"
  endpoint  = "my-slack-email-address"
}

###
# Aurora イベント通知の購読設定
#
# ここで作成した subscription に対して、
# Aurora クラスター / インスタンスで発生したイベントが SNS に流れてきます。
#
# 通知可能なイベントカテゴリの全体像:
# https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/USER_Events.Messages.html
###

# Aurora クラスター単位のイベント
resource "aws_db_event_subscription" "aurora_cluster_events" {
  name      = "my-aurora-event-subscription"
  sns_topic = aws_sns_topic.aurora_event.arn

  # クラスター単位のイベントだけを対象にする
  source_type = "db-cluster"
  source_ids  = ["my_aurora_cluster_id"]

  # 監視対象のイベントカテゴリ
  # - 障害やフェイルオーバーなど、可用性に直結するもの
  # - バージョン変更やメンテナンスなど、事前に気づきたいもの
  # を中心に選定しつつ、明らかに不要なものは外しています。
  event_categories = [
    "configuration change",
    "creation",
    "deletion",
    "failover",
    "failure",
    "maintenance",
    "notification",
  ]

  tags = {
    Name = "my-aurora-cluster-event-subscription"
  }
}

# Aurora インスタンス単位のイベント
# 必要な環境でだけ有効化したいので、フラグで切り替えられるようにしています。
resource "aws_db_event_subscription" "aurora_instance_events" {
  count     = var.enable_instance_events ? 1 : 0
  name      = "my-aurora-instance-event-subscription"
  sns_topic = aws_sns_topic.aurora_event.arn

  source_type = "db-instance"
  source_ids  = ["my_aurora_instance_id"]

  # インスタンス単位で拾いたいイベントカテゴリ
  # (low storage など、「発生頻度は低いが、起きたら気づきたい」系も含めています)
  event_categories = [
    "availability",
    "backtrack",
    "configuration change",
    "creation",
    "deletion",
    "failure",
    "low storage", # 一度にかなりの量を書き込まれないと発生しないが、検知できるようにしておく
    "maintenance",
    "notification",
    "read replica",
    "recovery",
    "restoration",
    "security patching",
  ]

  tags = {
    Name = "my-aurora-instance-event-subscription"
  }
}

結び

今回作成した設定によって、無事に Aurora MySQL 上のさまざまなイベント通知が Slack に送られてくるようになりました!

自動マイナーバージョンアップグレードの暴発というややしょっぱい事案を契機に、適切な改善・堅牢化に繋げることができたと思います。

実際に問題が起きるようなことがなければあまり意識しないものですが、転ばぬさきのなんとやらということで、皆さんの見直しに貢献できたら嬉しいです。

それでは!ノシ〜