🚨

[memo]AWS 障害情報を AWS Health API から取得し、MS Teams へ送信する

4 min read

こんにちは、 @hirosys_ です。
今回は、AWSで発生した障害情報をできるだけ迅速に MS Teams で共有する方法について取り急ぎまとめてみました。
本記事でお伝えする内容を導入する前は、 Service Health Dashboard の RSS を AWS Lambda で定期的に読み取り、障害発生していたら、 MS Teams に POST するというものでした。

しかし、 RSS の URL はサービス毎、Availability Zone 毎に分かれていたり、Availability Zone によってはサービスの GA 状況が異なっていたりするうえ、GA 後 に自動的に取得対象にしたいなども考えていました。この辺りは、指定した RSS URL があろう(HTTP200)がなかろう(HTTP404)が GET しにいき、200 以外の場合は処理しないという、よくある作りにはしていました。
しかし、新規追加サービスの場合は嫌でも、改修が必要な作りにもなっていました。
※つまり、その改修が漏れるといつまで経っても障害情報取得の対象にならない

そこで、AWS Health API に目をつけました。
AWS Health API は AWS サポートの Business プランか Enterprise プランであれば利用可能な API で、前述の Service Health Dashboard に表示されている障害情報と、Personal Health Dashboardに表示される、アカウント毎の障害やメンテナンス情報といったものが取得できるものです。

AWS Health API の仕様、リファレンスは以下をご確認ください。

https://docs.aws.amazon.com/health/latest/APIReference/Welcome.html
https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/health.html

では、AWS Health API を実行し、AWS 障害情報を取得して MS Teams に POST する方法をお伝えします。

AWS Lambda から MS Teams へ POST するための事前準備

手前味噌ですが、このあたりをご確認いただけたら幸いです。

Lambda 関数

環境変数

teams: Microsoft Teams の Incoming Webhook のエンドポイント URI を指定する。

必要なモジュール

requests: https で Microsoft Teams の Incoming Webhook に POST するため
本記事では、Lambda Layer で requests を作成・設定済み

IAM Role

AWS Health に対する各種アクション、任意のリソースに対して許可設定

実行間隔

Amazon EventBridge でスケジュールルールを作成し、 固定速度毎で 5分 を設定
Cloudwatch Events で作成する場合でも同様。
rate式の例は以下。

rate(5 minutes)

タイムアウト

デフォルト3秒から変更する。一旦、マックスである15分に設定。必要に応じて短くする。

コード

import json
import requests
import os
import datetime
import boto3

teams = os.getenv('teams', '')

def postTeams(title, msg):
    try:
        payload = {
            "title": title,
            "text": msg
        }

        payload_json = json.dumps(payload)

        res = requests.post(teams, data=payload_json)
        print(res)

        return

    except Exception as e:
        print("Teams post Error")
        print(e.message)


def lambda_handler(event, context):
    toDateTime = datetime.datetime.now()
    fromDateTime = toDateTime - datetime.timedelta(seconds=360)

    health = boto3.client('health', region_name='us-east-1')

    try:
        jpevents=health.describe_events(
            filter={
                'regions': [
                    'ap-northeast-1',
                    'ap-northeast-3',
                    'global'
                ],
                'lastUpdatedTimes':[
                    {
                        'from': fromDateTime,
                        'to': toDateTime
                    }
                ]
            }
        )['events']

        for jpevent in jpevents:
            if jpevent['eventScopeCode'] == 'PUBLIC':
                response = health.describe_event_details(
                    eventArns=[
                        jpevent['arn']
                    ]
                )['successfulSet'][0]

                #makeTitle
                title=response['eventDescription']['latestDescription'].split('\n\n')[0]

                #makeMsg
                eDescription=response['eventDescription']['latestDescription'].split('\n\n')[-1]
                eRegion=response['event']['region']
                eService=response['event']['service']

                post_msg = "# **■対象リージョン**: "+ eRegion + "   **■対象サービス**: "+eService+"\r\n\r\n# **■事象**:\r\n\r\n"
                post_msg = post_msg + eDescription.replace('|', '\r\n\r\n \r\n\r\n').replace('。','。\r\n\r\n').replace('. ','. \r\n\r\n')

                postTeams(title, post_msg)

    except Exception as e:
        print("Teams post Error")
        print(e.message)

postTeams()

MS Teams の Incoming Webhook のエンドポイント URI と送信するメッセージのタイトルとテキスト部分を引数に取り、その内容に基づいて MS Teams へ送信する関数

lambda_handler()

実行されたら現時刻より 360 秒前の日時を算出し、その値から現時刻までに発生した東京リージョン(ap-northeast-1)と大阪リージョン(ap-northeast-3)、グローバルサービスでの障害、イベント情報を AWS Health から取得する。

そして、その情報が PUBLIC であるかを判定し、 PUBLIC であれば、各イベントの詳細情報を取得する。
取得した情報をもとに MS Teams へ送信するメッセージ形式に整形する。

整形の際に、改行コード(¥n¥n)毎に配列化し、0番目の配列をタイトルに、最後の配列(-1番目)を本文に埋め込むようにしています。現状は、障害・イベントがアップデートされるたびに改行で区切られており、最後の配列が最新の更新になっているためです。

動作確認

toDateTime 変数と fromDateTime 変数に適当な日時を datetime.datetime() で指定することで確認ができます。
以下は、動作確認を行った際の MS Teams での出力例です。

Discussion

ログインするとコメントできます