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連携ではカスタマー管理キーを使う。