AWS LambdaでWebサーバを死活監視し、Slackに投稿する

Webサーバーの死活監視をするためには、Webサーバー以外に別のサーバーを立てて、そこから相互監視する必要がありますが、2台以上サーバーを持っていない限りはコストが嵩んでしまいます。

今回は監視役にAWS Lambdaを使うことで、必要時にだけ一瞬サーバーを起動して、あとは無課金というコスパの良い監視に挑戦してみます。Lambdaは100ms単位の課金なので、本当の意味での従量課金になりますね。ちなみにLambdaは100万リクエスト/月の無料枠があるので、1日数回程度の使い方なら無料枠におさまってしまうのではないでしょうか。これは使わないのはもったいない!

 

1. Slack側の準備

-1. Slackのアカウントを作り、死活監視結果投稿用のチャネルを作成する

Slackのアカウントを持っていない方は、こちらからアカウントを作成して、死活監視結果投稿用のチャネルを作成します。今回つくるチャネルは「#test」とします(詳細割愛)。

-2. Slackに incoming-webhook をインストールする

スレッド – App から、右上の「App ディレクトリ」をクリック

「incomig webhook」で検索して、「Incoming Webhook」を選択

「Slackに追加」をクリック

「#test」チャネルを選択し、「Incoming Webhook インテグレーションの追加」をクリック

インストールできました。下記Webhook URLが、Slackの#testチャネルへの投稿アドレスとなります。/services 以下は、Lambda側のプログラムに転記する必要があるので控えておきましょう。

 

 

2. AWS Lambda 側の準備

-1. Lambda関数の作成

AWSにログインし、「Lambda」をクリック

AWS Lambda – 「関数の作成」をクリック

設計図の使用、「https」で検索して「https-request」を選択、設定をクリック

Lamda関数に適当な名前(今回はtest)をつけて、「関数の作成」をクリック

-2. Lambda関数の実装

Lambda関数のひな形ができたら、以下のコードをindex.jsに上書きコピペして保存後、「テスト」をクリックします。今回のサンプルコードの言語はNode.jsです。

監視対象の const CHECK_HOST = ‘ji0vwl.net‘;  と、先ほど控えておいたSlack投稿先 path: ‘/services/xxxxxxxx/yyyyyyyy/zzzzzzzzzzzzzzzzzzzzzzzzzzz, は、ご自身の環境に合わせて修正してください。

'use strict';

const https = require('https');
const querystring = require('querystring');

const CHECK_HOST = 'ji0vwl.net';
const NAME = 'test_slack_bot';
const ICON_FAIL = ':umbrella:';
const ICON_PASS = ':sunny:';


function sendSlack(message, icon){
//メッセージ設定
var data = JSON.stringify({"username": NAME,"text": message,"icon_emoji": icon});

//オプション情報設定
var  options = {
    hostname: 'hooks.slack.com',
    port: 443,
    path: '/services/xxxxxxxx/yyyyyyyy/zzzzzzzzzzzzzzzzzzzzzzzzzzz,
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
        'Content-Length': Buffer.byteLength(data)
    }
};

//リクエスト
var req = https.request(options, (res) =>{
    if(res.statusCode===200){
        console.log("OK:"+res.statusCode);
    }else{
        console.log("Status Error:"+res.statusCode);
    }
});

//そもそもなエラー時
req.on('error',(e)=>{
    console.log('error');
    console.error(e);
});

//データ送信
req.write(data);
//終わり
req.end();

console.log(data);
}

/**
 * Pass the data to send as `event.data`, and the request options as
 * `event.options`. For more information see the HTTPS module documentation
 * at https://nodejs.org/api/https.html.
 *
 * Will succeed with the response body.
 */
exports.handler = (event, context, callback) => {

    /**
     * paramList
     * host: 検証したいホスト
     * path: 検証したいパス(200が返ってくるところ)
     * auth: Basic認証の"username:password"
     */
    var paramList = new Array(
        { host: CHECK_HOST , path:'', auth: '' },
        { host: CHECK_HOST , path:'', auth: '' }
    );
    var index = 0;

    function checkAlive(index) {
        var option = paramList[index];
        if(index == paramList.length){
            context.succeed();
            return;
        }
        index++;

        // httpsでリクエストを送ってみる
        var req = https.request(option, function (response) {
            var code = response.statusCode;
            if(index > 0) {
                if (code != 200) {
                    // 異常
                    var message = "\n*【異常】* \n" + option.host + option.path + " は元気がないようです\n- STATUS CODE " + code;
                    var icon = ICON_FAIL
                    sendSlack(message, icon);
                }
                else{
                    // OK
                    var message = "\n*【OK】* \n" + option.host + option.path + " は元気があります!\n- STATUS CODE " + code;
                    //console.log(message);
                    var icon = ICON_PASS
                    sendSlack(message, icon);
                }
            }
            checkAlive(index);
        });
        req.on('error', function (error) {
            var message = "\n*【エラー】* \n" + option.host + " にリクエストを送信できません";
            message += "\n - ERROR MESSAGE : " + error.message + "\n";
            console.log(message);
            sendSlack(message, context);
            checkAlive(index);
        });
        req.end();
    }

    checkAlive(index);
}

※Node.js だと、Lambdaのコールドスタート直後にSlack通知ができないことがあるようなので、ダミーで2回監視を回して、2回目を通知しています。もし直し方がわかる方は、直し方を教えていただけると助かります。。

イベントに適当な名前(今回はevent)をつけて、「作成」をクリック

再度、「テスト」をクリック。これで、index.js が一回実行されます。

実行結果:成功 であれば、ここまでの実装は成功です!

test_slack_botからの監視結果が、Slack の #test チャンネルに飛んできました。

-3. 作成したLambda関数を、定時実行させる

先ほど作成したLambda関数を定期的に呼び出して、死活監視を自動化してみましょう。

Designer –  「+トリガーを追加」をクリック

トリガーを選択 – 「CloudWatch Events」 をクリック

ルール - 「新規ルールの作成」をクリック

適当なルール名(今回はtest)とルールの説明をつけて、スケジュール式をCron形式で入力します。指定時刻はUTC基準です。今回はサンプルとして 平日の18時(UTC 9時)に実行させるために以下の式を入力しました。

cron(0 9 ? * MON-FRI *)

CloudWatch Events が test 関数につながればOK。あとは、平日の18時を待って、Slack通知が飛んでくれば完成です。

余力があったら、5分毎など もっと頻繁に実行させて200(成功)の時は通知しない、ただし最低1日1回だけは200も通知させて監視が動いていることを目視確認するなどしても良さそうですね。

※以下の投稿を参考にさせていただきました。ありがとうございます!

AWS Lambdaでwebサイトの死活監視をして、Slackに報告する

 

 

 

 

 

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

リンクが含まれる投稿はサイト管理者の承認後に表示されます(スパム対策)