はじめに

アプリケーション開発部の田村です。
自社で運営するウェブシステムの運用監視において、Amazon RDSやAmazon ECSなどのメトリクス監視の設定を行いました。
今回はアラームの通知先として、プロジェクト内の情報共有で利用しているMicrosoft Teamsを選択しました。

今回はその手順を実際に動く環境を構築して試すことが出来る記事を公開します。

構成図

今回の記事では、メトリクスとしてAmazon RDSのCPU使用率を監視し、CPU使用率が閾値を超過するとMicrosoft Teamsに通知する仕組みを構築します。
最終的な構成図は以下となります。

AWS CloudWatchでAmazon RDSのメトリクスを監視し、AWS CloudWatchアラーム発動時にAWS SNSへ連携します。
そしてAWS SNSへのアラーム連携をトリガーとしてTeamsへ通知するAWS Lambda関数を起動できるよう、SNSのサブスクリプションに当該の関数を設定します。

本記事を実施する上での要件

  • Git
  • AWS環境
  • Terraform v0.14.8
    • 手順簡略化のため実行時のIAMポリシーはAdministratorAccessとします
  • AWS CLI 1.19.31
  • EponaのTerraformモジュール
    • 特にインストールは不要です。Terraformのコードからmoduleとして参照します

AWS VPCとAmazon RDSの構築の作成

AWS VPC及び監視するAmazon RDSの設定をします。
ここは本記事の主題から外れるので、Terraformを使い詳細な手順は割愛します。
なお、Terraformのコードについてはcloudwatch-alarm-teamsにて公開しています。今回、こちらのコードを用いて構築します。

まずコードをGitのリポジトリから取得します。

git clone https://github.com/Fintan-contents/cloudwatch-alarm-teams.git

次にVPCを作成します。下記コマンドを実行します。

cd cloudwatch-alarm-teams/network
terraform init
terraform apply

変更点が表示されるので問題ないようであれば、「Enter a value:」に続いて「yes」と入力して実行します。

次にAmazon RDSを作成します。
Amazon RDSのユーザ情報をjsonファイル(secrets.json)で新規作成します。
cloudwatch-alarm-teams/database/secrets.json

{
"db_username": "postgres",
"db_password": "Passw0rd"
}

続いて下記コマンドを実行します。

cd cloudwatch-alarm-teams/database
terraform init
terraform apply

変更点が表示されるので問題ないようであれば、「Enter a value:」に続いて「yes」と入力して実行します。

これで検証に利用するAWS VPCとAmazon RDSが作成されました。

Microsoft TeamsのIncoming Webhookの設定

Microsoft TeamsのチャンネルにAWS Lambdaからの通知を受信するIncoming Webhookを設定します。

  1. 通知を受信するチャンネルの設定でコネクタを選択します。
  2. 「Incoming Webhook」を追加します。

    さらに次の画面でも追加ボタンを押下します。
  3. 再度、チャンネルのコネクタを選択し「Incoming Webhook」の構成を行います。
  4. 名前に「teams-test」と入力し作成します。
  5. 赤枠のコピーボタンで表示されているURLをコピーし控えておいてください。
    完了ボタンを押下します。

Microsoft Teamsに通知を行うAWS Lambda関数の作成

Microsoft Teamsへの通知はAWS Lambdaで行います。
下記の手順に従い、AWS Lambda関数を作成します。

  1. AWS Lambdaから関数の作成で「一から作成」、関数名「teams-test」で作成します。
  2. index.jsのコードを下記のコードで置き換えます。

    [Teams Incoming Webhook host part][Teams Incoming Webhook path part]にはMicrosoft TeamsのIncoming Webhookの設定で控えておいたURLを設定します。
    例)「https://xxxxxxxx.webhook.office.com/webhookb2/aaaa-bbbb-cccc-dddd」の場合

    var options = {
    hostname: 'xxxxxxxx.webhook.office.com',
    path: '/webhookb2/aaaa-bbbb-cccc-dddd',
    ...

    ※Webhookの情報も本来はAWS Systems Manager パラメータストアやAWS Secrets Managerで管理すべきですが、本記事では説明の簡素化のために平文で保持しています。

    const https = require('https');
    
    exports.handler = (event, context) => {
    for (var i in event['Records']) {
    const record = event['Records'][i];
    
    if (record['EventSource'] === 'aws:sns') {
    send_teams(record['Sns']['Subject'], record['Sns']['Message'])
    }
    }
    };
    
    function send_teams(title, msg) {
    const msgObj = JSON.parse(msg);
    
    // メッセージ本体です。Markdownが使えます。
    let body = `
    # 1. エラー概要
    
    | | |
    | :----------- | :--------------------------------- |
    | アラーム日時 | ${msgObj['StateChangeTime']} |
    | リソース | ${msgObj['Trigger']['Namespace']} |
    | メトリック | ${msgObj['Trigger']['MetricName']} |
    
    <br /><br />
    
    # 2. アラーム条件詳細
    \`\`\`json
    ${JSON.stringify(msgObj['Trigger'], null, 4)}
    \`\`\``;
    
    var data = JSON.stringify(
    {
    "title": title,
    "text": body
    });
    
    var options = {
    hostname: '[Teams Incoming Webhook host part]',
    path: '[Teams Incoming Webhook path part]',
    port: 443,
    method: 'POST',
    headers: {
    'Content-Type': 'application/json',
    'Content-Length': Buffer.byteLength(data)
    }
    };
    
    var req = https.request(options, (res) =>{
    if(res.statusCode!==200){
    console.log("Error:" + res.statusCode);
    }
    });
    
    req.on('error',(e)=>{
    console.error(e);
    });
    
    req.write(data);
    req.end();
    }
  3. Deployボタンで反映します。

AWS CloudWatch Alarmの設定

  1. AWS CloudWatch Alarmを作成します。
  2. 「メトリクスの選択」を押下します。
  3. 「RDS」を押下します。
  4. 「データベース別メトリクス」を押下します。
  5. 「teams-test」の「CPUUtilization」を選択します。
  6. 「条件」でしきい値に適切な値を入力し(例では80)「次へ」。
  7. 「通知の送信先」で「teams_test」を選択します。
  8. 「アラーム名」で「teams-test-RDS-CPUUtilization」と入力し「次へ」、次の画面で「アラームの作成」を押下します。

AWS SNSの設定

AWS SNSで「teams_test」トピックを作成し、サブスクリプションとして作成したAWS Lambdaを設定します。

  1. AWS SNSでトピック「teams_test」を作成します。タイプは「スタンダード」を選択します。
  2. AWS SNSで作成したトピック「teams_test」を選択します。
  3. 「サブスクリプションの作成」を選択します。
  4. 「エンドポイント」は先に作成したAWS Lambda関数「teams-test」を選択します。

テスト

以上で完成です。
下記コマンドを実行することでAWS CloudWatch Alarmの状態を強制的にアラーム状態にすることが出来ます。
勿論、意図的にAmazon RDSのCPU使用率を上げても構いません。

aws cloudwatch set-alarm-state --alarm-name teams-test-RDS-CPUUtilization --state-value ALARM --state-reason "test"

するとTeamsのチャンネルに通知が来ていることを確認できます。

後片付け

本手順において手動で作成したリソースは手動で削除をお願いします。
terraformで作成したリソースについては以下のコマンドで削除出来ます。

cd cloudwatch-alarm-teams/database
terraform destroy
cd cloudwatch-alarm-teams/network
terraform destroy

まとめ

簡単なコードと手順でAWS CloudWatchアラームの通知先をMicrosoft Teamsに出来ました。
同じようにMicrosoft Teamsへの連携を考えている方の参考になれば幸いです。

参考資料

※ AWS、Amazon RDS for PostgreSQL、 AWS Cloudwatch、 AWS SNS、 AWS Lambdaは、米国および/またはその他の諸国における、Amazon.com, Inc.またはその関連会社の商標です。


本コンテンツはクリエイティブコモンズ(Creative Commons) 4.0 の「表示—継承」に準拠しています。