📲

Amazon Connectを用いた無人監視(前編)

2023/10/03に公開

背景

新卒で入社した会社が他社のシステム監視を代行する業務をやっており、
また運用・保守でしばしば監視などに関わってきたことがあるため、
いつか無人で監視通知できる仕組みができたらいいなと思い、
今回機会がありましたので記事にさせていただきました。

概要

無人監視にする上で、システム化の難易度が比較的高いのが電話通知かと思います。
今回は障害アラートが発生した際に、Amazon ConnectのAPIを利用して、
システム担当者に自動で電話をかけ、アラートの内容を通知するということをやってみました。

前編では構成や仕組み、後編では工夫した点や考察などをまとめましたので適宜気になるところを読んでいただけると幸いです!

Amazon Connectとは

クラウド上にコールセンターを構築でき、
例えば製品やサービスの問い合わせ窓口等に利用するのが一般的ではないかと思います。
https://aws.amazon.com/jp/connect/

Amazon Connectには、アウトバウンドAPI(StartOutboundVoiceContact API)と呼ばれるものがあり、このAPIを使って電話をかけることができます。
今回はこの機能を使って障害アラートをシステム担当者に通知する想定で作ってみます。

電話をどのようにかけるかは、ConnectのContact Flowという機能で定義をすることができます。

様々なブロックと呼ばれるアクションを、
ドラッグ&ドロップで定義することができ、
例えば「顧客の入力を求める」というブロックではシステム担当者に1や3のボタンの押してもらい、ボタンによって処理を分岐するということができます。

その他にはContact Flow内からLambda関数を呼び出して、処理結果を受け取るというようなこともできます。

シナリオ

今回はシステム担当者3人に対して、
つながるまで順番に電話をかけて、3巡したら強制的に切断するような流れを考えて見ました。

システム担当者1→2→3→1→2→3→1→2→3→切断のようなイメージです。

構成

障害イベントの受付

NagiosやZabbixのようなAWS外部に監視システムをもっていても利用できるように、
API Gatewayで障害イベントを受け取れるようにしました。

API Gateway→Lambda→SQSでもよかったのですが、
シンプルにAPI Gateway→SQSにしてイベントを渡せるようにしてみました。

また、AWS内の障害イベントはCloudWatchから受け取るようにします。

障害イベントの送信にAWS CLIやSDKが使えるのであればEventBridgeでもよいかもしれません。

障害イベントの例

AWS外部の監視システムからAPI Gatewayには、以下のような形でイベントを渡します。
CloudWatchアラームもLambdaを介してイベントを整形して後続に渡します。

障害イベントの内容は、パラメータとしてAmazon Connectに渡すことで、
自動音声のメッセージ内に変数として代入することが可能です。

{
    "alertinfo": [
        {
            "host": "server1",
            "service": "CPU Utilization",
            "lastcheck": "2023-10-03 13:20:52",
            "systemname": "XYZ"
        }
    ]
}

例えば上記であれば「2023年10月3日にシステム名XYZのserver1でCPU Utilizationのアラートが発生しました」という自動音声が流れるようすることができます。

障害イベントの処理ロジック

障害イベントを受け付けたら、Step Functionsでどのように処理するのか定義します。

Step Functions内からLambdaを介してアウトバウンドAPIを実行することで、
Amazon Connectによる無人電話をかけることができます。

今回のシナリオでは、以下のように処理をする流れで定義をしてみました。

  1. アラートイベントのシステム担当者一覧をデータベースから取得(Get callorder)
  2. システム担当者に電話をかける、もし静観対象なら電話せずにフラグのみ立てる(Call)
  3. 静観のフラグが立っていれば処理を終了(Is it quite?→End of quite)
  4. 通話が正常に終了したかどうかを確認する、通話中なら30秒待機して再度確認をするポーリング処理(Check call status→Is it call end?→Wait 30s)
  5. アラートが確認されていれば処理を終了(Is it call end?→End of call and alert check end)
  6. アラートが確認されていなければ次の担当者にスキップする(Is it call end?→Is it continue to call?→Call)
  7. 指定した回数まで電話を行い、上限に到達したら強制的に処理を終了する(Is it continue to call?→End of call retry max)

Amazon Connectの構成

インスタンスの作成

コンソールにログインし、Amazon Connect>インスタンスを追加するを選択します。

ユーザはSMALベース認証などサポートされていますが、管理者のみアクセスできればよいのでローカルでユーザを用意するようにします。

テレフォニーは発信を許可にチェックを入れて作成します。

「インスタンスの作成」を押下するとインスタンスが追加されAmazon Connectが利用できるようになります。

電話番号の取得

事前に電話の発信元の番号を取得する必要がありますので、今回は米国番号を申請します。

電話番号の管理>電話番号の取得から取得することが可能です。

Contact Flow

電話が担当者に繋がったらどのように処理をするのかをContact Flow上で定義することができます。
いくつかポイントを紹介したいと思います。

  1. 変数を埋め込んだ自動音声
    アウトバウンドAPIを呼び出す際に変数を渡すことができるのですが、「プロンプトの再生」というブロックでその変数を代入して音声を再生させます。

以下はPythonでパラメータを渡すコードの例です。

   # API用のパラメータを作成
    params = {
        'ContactFlowId': contactflow_id,    # Contact FlowのID
        'DestinationPhoneNumber': dest_num, # 電話する相手の番号
        'InstanceId': instanceid,           # Amazon ConnectインスタンスのID
        'SourcePhoneNumber': source_num,    # 電話をかける側の番号
        'Attributes': {
            'host': ainfo[0],
            'service': ainfo[1],
            'systemname': ainfo[2],
	    'startdate': ainfo[3],
            'language': ainfo[4],
        }
    }
 
    # Ammazon Connect APIの実行
    connect_res = connect.start_outbound_voice_contact(**params)

渡されたパラメータを変数に代入する際には、「$.Attributes.['変数名']」のように記載をします。
例えば「statedate」(アラート発生時間)という変数を以下のように定義することができます。

  1. 入力されたボタンごとに処理を分岐
    システム担当者に番号の入力を求めて、アラート確認済みや静観の設定(12時間静観とか)、次の担当者へスキップなどをすることができます。

「顧客の入力を取得する」というボックスを使い、オプションで入力してもらう番号を設定します。

入力してもらったボタンの値は「コンタクト属性の設定」というブロックで変数に格納し、Lambdaなどに渡すことが可能です。

  1. 電話の処理ステータスの登録

ConnectのアウトバウンドAPIは非同期のため、
電話が終了しているかどうかステータスを確認する必要があります。

電話をかけると都度一意なContact IDが払い出されるのですが、
Contact IDを指定してDescribe Contact APIで現在のステータスを確認しようとしたところ、
残念ながら確認できないということがわかりました。

そのため、意図した通りに正常に通話が終了しているかどうかをContact Flow内の最後にLambdaを呼び出す形で定義し、
ステータスをDynamoDBに記録するようにしました。

データベース

システム担当者一覧やイベントの処理のステータスをDynamoDBで管理するようにしました。

システム担当者一覧

電話をかけるシステム担当者の一覧を格納したテーブルです。

例えば担当者ごとに言語情報を追加すれば、Contact Flow上で言語によって処理を分岐することはできます。

また、受付時間の属性情報など(営業日のみ電話OKなど)など要件に応じて複雑な電話のかけ方も実現できそうだなと思いました。

電話履歴

電話が正常に終了したかどうかをContact IDと紐づけて格納するテーブルです。
システム担当者が障害アラートを確認したかどうかをcheck_flagで判定し、
電話が切断されたり、不通になっていないかなどを例外を判定するのにdiscon_reasonを使って判定しています。
例外については後編の工夫した点の部分で補足したいと思います!

後編へ続く

https://zenn.dev/strix/articles/ba54166cc3d4a2

Discussion