2026年5月25日

2026年5月25日

AWS SNSで通知システムを構築する方法|トピック作成・メール購読・CloudWatchアラーム・WordPressからの送信

Amazon SNS(Simple Notification Service)で通知の仕組みを作るには、「トピック」を1つ作り、通知を受け取る先(メールアドレスやキューなど)をそのトピックに購読させ、送る側はトピックに向けてメッセージを発行するだけです。送る側は受け取り先を知らなくてよいので、通知先の追加や変更をアプリのコードに触れずに行えます。この記事では、WordPressサイトの運用通知を例に、トピックの作成、メール購読の確認、CloudWatchアラームとの連携、WordPress(PHP)からの送信、権限と暗号化でつまずく点までを順に説明します。

AWSの画面表記やサービス名は変わることがあります。ここでの説明は執筆時点(2026年10月現在)の情報をもとにしているので、細かな項目名は公式ドキュメントでも確認してください。

SNSで何ができて、何に向かないか

SNSは「1つの出来事を、複数の宛先へ同時に配る」ためのサービスです。WordPressの運用で使いやすい場面は次のとおりです。

  • サーバーのCPU使用率やエラー数がしきい値を超えたときに、運用担当者へメールで知らせる
  • プラグインの有効化・無効化など、管理画面での重要な操作を記録として通知する
  • 1つの出来事をSQSのキューやLambdaにも同時に流し、後続の処理を動かす(ファンアウト)

一方で、会員登録の確認メールや注文確認メールのような「サイトの利用者に送るメール」には向きません。SNSのメール通知は文面の自由度が低く、購読の確認手順も必要だからです。利用者向けのメールにはAmazon SESなどのメール送信サービスを使い、SNSは運用者や他のシステムへの通知に使う、と分けて考えると迷いません。

ステップ1:トピックを作る

トピックには「スタンダード」と「FIFO」の2種類があります。運用通知ならスタンダードで十分です。FIFOは順序と重複排除が必要な処理向けで、メールなど一部の購読先は使えません。

AWS CLIでは次のように作成します。リージョンはWordPressのサーバーと同じにそろえておくと、後の設定が分かりやすくなります。

aws sns create-topic --name wp-ops-alerts --region ap-northeast-1

結果に表示される TopicArn(arn:aws:sns:ap-northeast-1:123456789012:wp-ops-alerts のような文字列)は、購読・発行・権限の設定のすべてで使うので控えておきます。アカウントIDは例なので、自分の環境の値に置き換えてください。

トピック名は用途ごとに分けておくと後で楽になります。たとえば「すぐ対応が必要な障害」と「記録として残せばよい操作ログ」を同じトピックに流すと、受け取る側で重要な通知が埋もれます。

ステップ2:メールで購読して確認する

aws sns subscribe \
  --topic-arn arn:aws:sns:ap-northeast-1:123456789012:wp-ops-alerts \
  --protocol email \
  --notification-endpoint ops@example.com

登録した直後の購読は「確認待ち」の状態で、まだ通知は届きません。指定したアドレスにAWSから確認メールが届くので、本文のリンクを開くと購読が有効になります。確認メールが見当たらないときは、迷惑メールフォルダと、メールサーバー側のフィルターを確認してください。確認リンクには有効期限があり、期限が切れたら購読をやり直します。

購読が有効になったら、テスト送信をして届くかを見ます。

aws sns publish \
  --topic-arn arn:aws:sns:ap-northeast-1:123456789012:wp-ops-alerts \
  --subject "SNS test" \
  --message "wp-ops-alerts の送信テストです"

--subject はメールの件名として使われます。メール以外の購読先では使われないので、重要な情報は本文に入れておきます。

メール以外の通知先

  • SQS / Lambda:通知を受けて自動処理をしたいとき。SQSを購読させると、受け手の処理が止まっていてもメッセージがキューに残ります。
  • HTTPS エンドポイント:自前のWebhook受信先に送ります。購読時に確認用のリクエストが届くので、受信側でその確認に応える処理が必要です。
  • SMS:国ごとに送信元の登録などの要件があり、条件は変わりやすい分野です。使う前に、送信先の国の要件を公式ドキュメントで確認してください。
  • Slack などのチャット:AWSのチャット連携サービス(旧称 AWS Chatbot。現在は Amazon Q Developer の一機能として提供)を使うか、Lambdaから各サービスのWebhookへ送る方法があります。名称や設定手順が変わってきた分野なので、最新の手順に従ってください。

ステップ3:CloudWatchアラームから通知する

運用通知でいちばん使うのが、CloudWatchアラームの通知先にトピックを指定する方法です。次の例は、EC2インスタンスのCPU使用率が5分平均で80%を超える状態が2回続いたら通知し、元に戻ったときにも通知するものです。

aws cloudwatch put-metric-alarm \
  --alarm-name wp-web-cpu-high \
  --namespace AWS/EC2 \
  --metric-name CPUUtilization \
  --dimensions Name=InstanceId,Value=i-0123456789abcdef0 \
  --statistic Average \
  --period 300 \
  --evaluation-periods 2 \
  --threshold 80 \
  --comparison-operator GreaterThanThreshold \
  --alarm-actions arn:aws:sns:ap-northeast-1:123456789012:wp-ops-alerts \
  --ok-actions arn:aws:sns:ap-northeast-1:123456789012:wp-ops-alerts

--ok-actions も設定しておくと「いつ復旧したか」が分かり、夜間の通知に対応すべきかの判断がしやすくなります。評価回数を1回にすると一瞬の負荷でも通知が飛び、通知が多すぎて誰も見なくなる原因になります。最初は少し鈍めに設定し、運用しながら調整するのが現実的です。

設定できたら、aws cloudwatch set-alarm-state --alarm-name wp-web-cpu-high --state-value ALARM --state-reason "test" で一時的にアラーム状態にし、通知が届くかを確かめておくと安心です。

ステップ4:WordPressからSNSに通知を送る

WordPressの中で起きた出来事を通知したい場合は、AWS SDK for PHPを使ってトピックに発行します。次の例は、プラグインが有効化・無効化されたときに通知するmu-pluginです。本番に入れる前に、ステージング環境で動作を確かめてください。

<?php
/**
 * Plugin Name: Ops notify via SNS
 * Description: プラグインの有効化・無効化を SNS トピックに通知する
 */

// Composer でインストールした AWS SDK for PHP を読み込む(パスは環境に合わせる)
$wpdr_sdk = WP_CONTENT_DIR . '/mu-plugins/ops-notify/vendor/autoload.php';
if ( ! file_exists( $wpdr_sdk ) || ! defined( 'WPDR_SNS_TOPIC_ARN' ) ) {
	return;
}
require_once $wpdr_sdk;

function wpdr_sns_notify( $subject, $message ) {
	try {
		$sns = new Aws\Sns\SnsClient( array(
			'region'  => 'ap-northeast-1',
			'version' => 'latest',
		) );
		$sns->publish( array(
			'TopicArn' => WPDR_SNS_TOPIC_ARN,
			'Subject'  => $subject,
			'Message'  => $message,
		) );
	} catch ( Exception $e ) {
		// 通知に失敗しても管理画面の操作は止めない
		error_log( 'SNS notify failed: ' . $e->getMessage() );
	}
}

function wpdr_notify_plugin_change( $plugin, $action ) {
	$user = wp_get_current_user();
	$msg  = sprintf(
		"%s: %s\nsite: %s\nuser ID: %d",
		$action,
		$plugin,
		home_url(),
		$user->ID
	);
	wpdr_sns_notify( 'WordPress plugin ' . $action, $msg );
}

add_action( 'activated_plugin', function ( $plugin ) {
	wpdr_notify_plugin_change( $plugin, 'activated' );
} );
add_action( 'deactivated_plugin', function ( $plugin ) {
	wpdr_notify_plugin_change( $plugin, 'deactivated' );
} );

設計上のポイントは次のとおりです。

  • トピックのARNは定数で渡す:wp-config.php に define( 'WPDR_SNS_TOPIC_ARN', '...' ); と書きます。定数が無い環境(ステージングなど)では何もしないので、本番の通知が誤って飛びません。
  • 失敗しても処理を止めない:通知のエラーで管理画面の操作が失敗すると本末転倒です。例外を捕まえてログに残すだけにしています。
  • 通知に個人情報を入れない:例ではユーザー名やメールアドレスではなくユーザーIDだけを送っています。通知メールは転送や共有がされやすいので、必要最小限の情報にとどめます。
  • SDKの重複に注意:ほかのプラグインが別の版のAWS SDKを同梱していると、クラスの読み込みが衝突することがあります。不具合が出たら、SDKを読み込んでいるプラグインを洗い出してください。

認証情報はコードに書かない

EC2でWordPressを動かしているなら、インスタンスにIAMロール(インスタンスプロファイル)を付けます。SDKは認証情報を自動で探すので、アクセスキーをコードや wp-config.php に書く必要がありません。ロールに付けるポリシーは、特定のトピックへの発行だけに絞ります。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "sns:Publish",
      "Resource": "arn:aws:sns:ap-northeast-1:123456789012:wp-ops-alerts"
    }
  ]
}

AWSの外のサーバーからどうしてもアクセスキーを使う場合は、この権限だけを持つ専用のIAMユーザーを作り、キーをWeb公開領域の外やサーバーの環境変数で管理し、Gitには含めないようにします。

つまずきやすい点

暗号化を有効にしたらアラーム通知が届かない

トピックの暗号化(SSE)にAWS管理のKMSキー(alias/aws/sns)を選ぶと、CloudWatchアラームからの発行が失敗することがあります。AWS管理キーのキーポリシーは利用者が変更できず、CloudWatchにキーの利用を許可できないためです。CloudWatchから通知させるトピックを暗号化する場合は、カスタマー管理のKMSキーを作り、キーポリシーでCloudWatchのサービスにキーの利用を許可します。

発行はできているのに届かない

まず購読の状態が「確認済み」かを確認します。次に、購読に「フィルターポリシー」を設定していないかを見ます。フィルターポリシーはメッセージ属性で配信先を絞る機能で、条件に合わないメッセージは黙って配信されません。CloudWatchのSNSのメトリクスで、配信の成功数と失敗数を見ると、どの段階で止まっているかを切り分けられます。

通知が多すぎる

同じ障害で何十通も届くと、本当に大事な通知が見落とされます。アラームの評価期間を見直す、重要度ごとにトピックを分ける、操作ログはメールではなくSQSやログに流す、といった工夫で量を減らします。

まとめ

  • SNSはトピックに発行し、購読先に配る仕組み。送る側は受け取り先を知らなくてよい。
  • メール購読は確認リンクを開くまで有効にならない。登録後はテスト送信で到達を確かめる。
  • CloudWatchアラームには --alarm-actions と --ok-actions でトピックを指定し、発生と復旧の両方を通知する。
  • WordPressから送るときは、IAMロールで認証し、権限は特定トピックへの sns:Publish だけに絞る。通知の失敗で本来の処理を止めない。
  • 暗号化にAWS管理キーを使うとアラーム通知が失敗することがある。CloudWatch連携ではカスタマー管理キーを使う。

お気軽にご相談ください

お見積りへ お問い合わせへ
▲