[AWS] Lambdaからバッチ実行を監視してTeamsに投稿してみた

スポンサーリンク
AWS

AWS EC2 のインスタンスで毎日cronのバッチが実行されているが、そのログを監視して、「毎日正常にバッチが動いている」かを確認することになりました。

そこで、今回やるのは、
Lambdaを定期実行 → EC2のcronログをtail → 結果をTeamsに投稿
になります。図で表すと以下の通りです。

今回作るもの

今回必要となるのは、以下の通りです。

  • AWS Lambda
  • Python
    lambda_function.py ・・・Lambdaで実行されるメインプログラム。
    send_teams.py ・・・lambda_function.pyで呼ばれる。Teamsに投稿するプログラム
  • Event Bridge(Cloud Watch Events)

AWS Lambda

まずは、Lambdaの設定を行っていきます。
AWS Lambda > 関数 の右上にある、関数作成を押下します。

一から作成を選択したまま、
 ・関数名
 ・ランタイム(今回は、Pythonにしました。)

を設定します。設定が終わったら関数の作成ボタンを押します。

Pythonプログラムの作成

Lambda関数の作成が終わったら、Pythonプログラムを書いていきます。
コードタブに「lambda_function.py」が自動作成されているので、ここにメインプログラムを記載していきます。

【自動作成後の画面】

今回は、Teamsに投稿するプログラムを別途用意するので、コードソース下のタブにある File > New File でsend_teams.pyファイルを作成します。

各ソースの中身は、以下の通りです。

lambda_function.py

import json
import urllib.request
import boto3
import send_teams as st
import datetime
import dateutil.parser
import time

def lambda_handler(event, context):
    jst_datetime = datetime.datetime.now()
    
    command = "grep mailbatch.sh /var/log/cron | tail -20"
    instance_id = "xxxxxxxxxxxxxxxxxxx"
    ssm = boto3.client('ssm', region_name='ap-northeast-1')
    retry = 3
    
    # 最大でリトライ回数までコマンドを実行
    for i in range(1,retry):
    
        # コマンド実行
        r = ssm.send_command(
            InstanceIds = [instance_id],
            DocumentName = "AWS-RunShellScript",
            Parameters = {
                "commands": [
                command
                ]    
            }
        )
        command_id = r['Command']['CommandId']
        
        # 処理終了待ち
        time.sleep(3)
        
        # 結果取得
        res = ssm.list_command_invocations(
              CommandId = command_id,
              Details = True
            )
        invocations = res['CommandInvocations']
        status = invocations[0]['Status']
            
        # ステータスが"Success"の場合
        if status == "Success":
            # 処理を抜ける
            break
    
    # ステータスが"Success"の場合
    if status == "Success":
        # コマンドの実行結果部分を取得
        description = invocations[0]['CommandPlugins'][0]['Output']
    
        # 改行を<br>タグに変換
        description = description.replace('\n','<br>')
    
        # Teamsに投げるメッセージを作成
        message='<table><tr><th>取得日時</th> <th align="left">{}</th></tr><tr><th>内容</th><th align="left"><font size="1">{}</font></th></tr></table>'.format(jst_datetime.strftime("%Y/%m/%d %H:%M:%S"),description)  
        
    # ステータスが"Success"以外の場合
    else:
        message='<table><tr><th>取得日時</th> <th align="left">{}</th></tr><tr><th>内容</th><th align="left"><font size="1">{}</font></th></tr></table>'.format(jst_datetime.strftime("%Y/%m/%d %H:%M:%S"),"Lambda取得エラー ステータス=" + status)    

    # Teamsに投げるタイトルの設定
    title="バッチ稼働状況通知"

    # Teamsに送信
    st.send(title,message)
    #print(message)
    
    return {
        'statusCode': 200,
        'body': json.dumps('Hello from Lambda!')
    }

send_teams.py

import os
import urllib.request
import json


def send(title,message):
    send_data = {"title":title,"text": message}
    send_text = "payload=" + json.dumps(send_data)
    send_text =  json.dumps(send_data)
    request = urllib.request.Request(
        os.environ["NOTIFICATION_TARGET"], 
        data=send_text.encode("utf-8"),
        method="POST"
    )

    urllib.request.urlopen(request)

【プログラム修正後の画面】

Lambdaの設定

環境変数の設定で、Teamsの「Incoming Webhook」のURLを設定します。
まず、URLを取得しましょう。

Teamsのチャネルで左クリック > コネクタ > Incoming Webhook
でWebhookを作成します。

[Teams]

次に、WebhookでURLをコピーできたら、Lambdaの環境変数「NOTIFICATION_TARGET」に設定します。

[Lambda]

アクセス制限

LambdaとEC2でアクセスの許可がそれぞれ必要になります。

Lambda側

  • AmazonEC2ReadOnlyAccess
  • AmazonSSMFullAccess

EC2側

  • AmazonSSMManagedInstanceCore

トリガの設定(Event Bridge)

トリガーでLambdaの起動タイミングを設定します。
今回は、Event Bridgeで3時間おきに起動するようにしました。

Lambdaの画面で「トリガーを追加」から設定できます。

スケジュール式は、cron式で設定しました。ポイントは以下になります。

  • 左から[分] [時] [日] [月] [曜日] [年] 6つの必須フィールド。
  • / は、○○毎。
    ⇒今回は、3時間毎に動かしたいので、*/3。
  • 日フィールド及び曜日フィールドを同時に指定することはできない。
    一方のフィールドに値を指定すると、もう一方のフィールドで ? (疑問符) を使用する必要がある。
    ⇒毎日実行させたいので、日を*、もう一方を?にします。

稼働確認

設定が完了したら、3時間おきに稼働状況がTeamsに投稿されるはずです。

まとめ

今回は、LambdaでEC2のcronログを参照して、稼働確認をやってみました。これまでAWSに触れることがなかったので、Lambdaを作ってみて色々使っていく中で理解が深まりました。

Lambdaでは簡単にテストもできるし、利用できる言語も豊富なので、かなり使い勝手がよい印象でした。

今後も色々試してみたいと思います。

コメント

タイトルとURLをコピーしました