
CloudWatchのCPU使用率アラームをMicrosoft Teamsに通知する方法
1. はじめに
EC2インスタンスのCPU使用率が急上昇した際、メールだけでは気づくのが遅れてしまうことがあります。 日常的に使っているMicrosoft Teamsのチャネルに直接アラートを流せれば、チーム全体が即座に異常に気づき、初動対応を早めることができます。
本記事では、CloudWatchアラームを起点として、SNSとLambdaを経由し、Teamsのチャネルへ通知を送る仕組みの構築手順を解説します。
2. 全体構成
TeamsはSlackと異なりAWS Chatbotの標準対応先ではないため(Chatbotの対応先はSlackとChime/Teamsの一部プランに限られ、構成によって挙動が異なります)、もっとも汎用的で確実な方法は「Incoming Webhook + Lambda」を使う構成です。全体の流れは以下の通りです。
EC2(CPU使用率)
→ CloudWatchアラーム(閾値超過を検知)
→ SNSトピック(通知の配信)
→ Lambda関数(メッセージ整形)
→ Teams Incoming Webhook(チャネルへ投稿)
CloudWatchアラームは直接HTTPエンドポイントを呼び出せないため、SNS経由でLambdaをトリガーし、Lambda内でTeams形式のペイロードを作成してWebhookへPOSTする、という構成が定番です。
3. ステップ1:Teams側でIncoming Webhookを準備
1.通知を送りたいTeamsのチャネルを開き、「…」メニューから「コネクタ」を選択
2.「Incoming Webhook」を検索し「構成」をクリック
3.Webhook名(例:「AWS CloudWatchアラート」)を設定し、作成
4.発行されたWebhook URL(https://xxxxx.webhook.office.com/…)を控えておく
このURLに対してJSON形式のペイロードをPOSTするだけでメッセージが投稿されます。URLは機密情報として扱い、Lambdaの環境変数やSecrets Managerで管理してください。
補足 Microsoftは2025年以降、Microsoft 365のOffice 365 Connectorsを段階的に廃止し、 Power Automate/Workflowsベースのウェブフックへ移行する方針を発表しています。
4. ステップ2:SNSトピックの作成
まずCloudWatchアラームの通知先となるSNSトピックを作成します。
aws sns create-topic --name ec2-cpu-alert-topic
作成したトピックのARNを控えておきます(以降の手順で使用します)。
5. ステップ3:CloudWatchアラームの作成
対象EC2インスタンスのCPU使用率が閾値(例:80%)を5分間連続で超えた場合にアラームを発火する設定です。
aws cloudwatch put-metric-alarm \
--alarm-name "EC2-HighCPU-Alarm" \
--alarm-description "CPU使用率が80%を超えた場合に通知" \
--namespace "AWS/EC2" \
--metric-name "CPUUtilization" \
--dimensions Name=InstanceId,Value=i-0123456789abcdef0 \
--statistic Average \
--period 300 \
--evaluation-periods 1 \
--threshold 80 \
--comparison-operator GreaterThanThreshold \
--alarm-actions arn:aws:sns:ap-northeast-1:123456789012:ec2-cpu-alert-topic \
--ok-actions arn:aws:sns:ap-northeast-1:123456789012:ec2-cpu-alert-topic
–ok-actions も指定しておくことで、閾値を下回って正常復帰した際にも通知が届き、「いつ収束したか」をチームで共有できます。
複数インスタンスを一括監視したい場合は、Auto Scalingグループ単位のメトリクス(AWS/EC2 の集約、またはCloudWatchのメトリクス数式)を使う方法もあります。
6. ステップ4:Lambda関数の作成
SNSからのメッセージを受け取り、Teams向けのペイロードに変換してWebhookへPOSTするLambda関数を作成します。ランタイムはPython 3.12を例にします。
import json
import os
import urllib.request
TEAMS_WEBHOOK_URL = os.environ["TEAMS_WEBHOOK_URL"]
def lambda_handler(event, context):
sns_message = json.loads(event["Records"][0]["Sns"]["Message"])
alarm_name = sns_message.get("AlarmName", "Unknown Alarm")
new_state = sns_message.get("NewStateValue", "UNKNOWN")
reason = sns_message.get("NewStateReason", "")
region = sns_message.get("Region", "")
timestamp = sns_message.get("StateChangeTime", "")
# アラーム状態に応じて色を切り替える(ALARM=赤、OK=緑)
theme_color = "FF0000" if new_state == "ALARM" else "2EB67D"
payload = {
"@type": "MessageCard",
"@context": "http://schema.org/extensions",
"themeColor": theme_color,
"summary": f"CloudWatch Alarm: {alarm_name}",
"sections": [
{
"activityTitle": f"**CloudWatch アラーム通知**",
"facts": [
{"name": "アラーム名", "value": alarm_name},
{"name": "状態", "value": new_state},
{"name": "リージョン", "value": region},
{"name": "発生時刻", "value": timestamp},
{"name": "詳細", "value": reason},
],
"markdown": True,
}
],
}
req = urllib.request.Request(
TEAMS_WEBHOOK_URL,
data=json.dumps(payload).encode("utf-8"),
headers={"Content-Type": "application/json"},
)
with urllib.request.urlopen(req) as response:
print(f"Teams response status: {response.status}")
return {"statusCode": 200}
Webhook URLはコード内に直接埋め込まず、Lambdaの環境変数として設定します。
aws lambda update-function-configuration \
--function-name teams-notifier \
--environment "Variables={TEAMS_WEBHOOK_URL=https://xxxxx.webhook.office.com/...}"
さらに機密性を高めたい場合は、Webhook URLをAWS Secrets Managerに保存し、Lambda実行時に取得する構成に変更することを推奨します。
7. ステップ5:SNSトピックとLambdaのサブスクライブ設定
SNSトピックにLambda関数をサブスクライブさせます。
aws sns subscribe \
--topic-arn arn:aws:sns:ap-northeast-1:123456789012:ec2-cpu-alert-topic \
--protocol lambda \
--notification-endpoint arn:aws:lambda:ap-northeast-1:123456789012:function:teams-notifier
あわせて、SNSからLambdaを呼び出す権限を付与します。
aws lambda add-permission \
--function-name teams-notifier \
--statement-id sns-invoke \
--action lambda:InvokeFunction \
--principal sns.amazonaws.com \
--source-arn arn:aws:sns:ap-northeast-1:123456789012:ec2-cpu-alert-topic
8. 動作確認
CloudWatchアラームの状態を手動で変更し、一連の流れが機能するか確認します。
aws cloudwatch set-alarm-state \
--alarm-name "EC2-HighCPU-Alarm" \
--state-value ALARM \
--state-reason "Manual test"
Teamsチャネルに通知カードが投稿されれば成功です。投稿されない場合は、CloudWatch Logs(/aws/lambda/teams-notifier)でLambdaの実行ログを確認し、Webhook URLの誤りやHTTPステータスエラーがないかを確認します。
9. 運用時の工夫
通知のノイズを減らす工夫
CPU使用率は瞬間的なスパイクが発生しやすいため、–evaluation-periods を2〜3程度に設定し、「連続して閾値を超えた場合のみ」アラームが発火するようにするとノイズを抑えられます。
--evaluation-periods 3 \
--datapoints-to-alarm 2
上記は「直近3期間のうち2期間が閾値を超えたら発火」という設定で、単発のスパイクによる過剰通知を防ぎます。
複数のメトリクスをまとめて監視
CPU使用率だけでなく、メモリ使用率(CloudWatchエージェント導入が必要)やディスクI/Oも合わせて監視したい場合は、同じLambda関数を複数のSNSトピックで共有し、アラーム名から判別してメッセージ内容を出し分ける構成にすると管理がシンプルになります。
Infrastructure as Codeで管理
上記の手動構築手順は、CloudFormationやTerraformでコード化しておくことを推奨します。環境の複製や障害復旧時の再構築が容易になり、Webhook URLの変更にも迅速に対応できます。
10. おわりに
クラウドでは、サーバーやアプリケーションの状態をリアルタイムに把握し、異常をいち早く検知できることが大きなメリットの一つです。 しかし、アラートを設定するだけでは十分ではなく、「必要な人に、必要なタイミングで確実に届く仕組み」を整備して初めて、その価値を最大限に発揮できます。
AWSではCloudWatchやSNS、Lambdaといったマネージドサービスを組み合わせることで、複雑な監視システムを一から構築することなく、柔軟で拡張性の高い通知基盤を実現できます。今回紹介した構成も、CPU使用率だけでなく、メモリ使用率やディスク容量、アプリケーションエラーなど、さまざまな監視項目へ容易に展開できる点が魅力です。
また、日常的に利用しているMicrosoft Teamsへ通知を集約することで、メールを確認する手間を減らし、チーム全体で異常を共有しやすくなります。 結果として、障害発生時の初動対応を早めるだけでなく、運用業務の効率化やシステムの安定稼働にもつながります。








