[AWS] Lambda(Python)とカスタムメトリクスを使って、VPN接続を監視する [CloudWatch]

こんにちは。
AWSでVPN接続をしたときに何かしらの監視の仕組みは必要だと思ったので、LambdaとCloudWatchのカスタムメトリクスを使って監視してみました！
コードに関しては、勉強不足です。ごめんなさい。
もっと汎用的で見やすいコードが書けるように勉強します！

#1.今回やること
・LambdaでVPNの接続ステータスの値を取得。
・取得した値をCloudWatchにプット。
・カスタムメトリクスの値は、UPしているVPNトンネルの本数。
　Ex)VPNトンネル2本ともアップしている場合、「2」を入れる。
・Lambdaのスケジュール機能を使って5分ごとにVPNの接続ステータスを確認。

#2.前提
・VPN1本、VPNトンネル2本の環境を想定してスクリプトを作っています。

#3.コード
pprintは、デバック用に残してあります。動作には特に関係ありません。

```
def lambda_handler(event, context):
    import boto3
    import datetime
    #import pprint

    i = 0
    ec2 = boto3.client('ec2')
    cloudwatch = boto3.client('cloudwatch')
    #pp = pprint.PrettyPrinter(indent=4)

    
    #Check VPN Status
    response = ec2.describe_vpn_connections()


    Vpn1 = response["VpnConnections"][0]["VgwTelemetry"][0]["Status"]
    Vpn2 = response["VpnConnections"][0]["VgwTelemetry"][1]["Status"]


    if Vpn1 == "UP":
                i = i + 1
    if Vpn2 == "UP":
                i = i + 1

    #PutMetricData
    PutMetricData = cloudwatch.put_metric_data(
                Namespace='VPN',
                MetricData=[
                            {
                                        'MetricName': 'vpnConnection',
                                        'Timestamp': datetime.datetime.utcnow(),
                                        'Value': i,
                                        'Unit': "Count"
                            },
                ]
    )

    PutMetricData

```




#4.ロール権限
Lambdaに設定するロールは以下のようになります。

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "cloudwatch:PutMetricData"
            ],
            "Resource": [
                "*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents"
            ],
            "Resource": [
                "*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "ec2:DescribeVpnConnections"
            ],
            "Resource": [
                "*"
            ]
        }
    ]
}
```


#4.Lambdaファンクション作成
Lambdaファンクションの作成までやっていきます。

・[Lambda]をクリックします。
![001.png](https://qiita-image-store.s3.amazonaws.com/0/95380/814c5765-5f5e-c390-6905-42cd4567cb5f.png)

・[Create a Lambda function]をクリックします。
![002.png](https://qiita-image-store.s3.amazonaws.com/0/95380/c9c7820e-f1fc-2812-23c1-941c5336f2cd.png)

・テンプレートは使用しないので、[Skip]をクリックします。
![003.png](https://qiita-image-store.s3.amazonaws.com/0/95380/9e48815b-d85a-f362-d0f8-9a508574b62d.png)

・[Name][Description]に任意の値を入力し、 [Runtime]で「Python2.7」を選びます。
　[Lambda function code]に、「3.コード」のコードをコピー&ペーストします。
![004.png](https://qiita-image-store.s3.amazonaws.com/0/95380/0b3f22f9-5a16-f856-1b9a-21c3c59a23d8.png)

・権限の設定をします。[Role]で「Create new role」- [Basic execution role]を選びます。
![005.png](https://qiita-image-store.s3.amazonaws.com/0/95380/af12c171-6520-1dff-972d-e155fd37a43c.png)

・[新しいIAMロール作成]を選び、[ロール名]に任意の値を入力します。
　そのあと、 [編集]をクリックし、「4.ロール権限」の値をコピー&ペーストします。
![006.png](https://qiita-image-store.s3.amazonaws.com/0/95380/d835e000-0730-9e70-0f4b-cc717e856abe.png)

・実行時間の設定をします。[Timeout]の時間を「30」に設定し、[Next]をクリックします。
　#もしかするともっと短くてもいいかもしれません。
![007.png](https://qiita-image-store.s3.amazonaws.com/0/95380/1d3be8c4-eefb-e3df-2c70-c4459b01a9b1.png)

・プレビューが表示されるので内容を確認して、[Create function]をクリックします。
![008.png](https://qiita-image-store.s3.amazonaws.com/0/95380/7c416129-c129-0a5f-f90f-5a565243a0db.png)

・これでLambdaファンクションの作成は完了です。
![009.png](https://qiita-image-store.s3.amazonaws.com/0/95380/4c9a4d76-ebe1-3576-1d76-67a7ea86e9cd.png)

#5.Lambdaスケジュール登録
次にスケジュールの登録をします。

・[Event sources]-[Add event source]をクリックします。
![010.png](https://qiita-image-store.s3.amazonaws.com/0/95380/c08b1e33-ac51-48d7-969d-7a694ccc8f73.png)

・[Cloudwatch Events - Schedule]をクリックします。
![011.png](https://qiita-image-store.s3.amazonaws.com/0/95380/cf7a64bf-318e-4dee-535c-ee086ab518e6.png)

・[Rule name][Rule description]に任意の値を入力します。
　[Schedule expression]で「rate(5 minutes)」を選択し、[Submit]をクリックします。
　スケジュールの詳しい内容は、[こちら](https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/with-scheduled-events.html)をご参照ください。
![012.png](https://qiita-image-store.s3.amazonaws.com/0/95380/b25b5f7b-2aea-fef2-9931-2a448323b44e.png)

・これでスケジュール登録も完了です。
![013.png](https://qiita-image-store.s3.amazonaws.com/0/95380/b551584c-d5fe-27b6-9d4d-f4ea04e4a84b.png)

・CloudWatchのカスタムメトリクスの値を確認すると、5分ごとに値が入っていますね。
　#VPNトンネルが両方ダウンしているので0を返しています。
![CloudWatch_Management_Console.png](https://qiita-image-store.s3.amazonaws.com/0/95380/42983d22-f336-93e5-1f92-7000c3148e32.png)


#6.最後に
・通知をする場合は、CloudWatchからアラートの設定をすればできますね。

・AWS内部の情報はAmazon側から提供されていない限りユーザー自身で監視しなければならないので、Lambdaを使った監視はすごく良いのではないかと思います。何かを監視するためだけにサーバーを立てていると費用もかかりますからね。もっともっとLambdaをうまく使えるように勉強します！

簡単となりますが、以上となります。
ご指摘事項などありましたら、ご連絡お願いいたします。


#99.参考

http://boto3.readthedocs.io/en/latest/reference/services/ec2.html#EC2.Client.describe_vpn_connections
http://boto3.readthedocs.io/en/latest/reference/services/cloudwatch.html#CloudWatch.Client.put_metric_data
https://siguniang.wordpress.com/2014/12/19/publish-custom-metrics-to-cloudwatch-with-awscli/
https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/with-scheduled-events.html

参考にさせていただきました。ありがとうございます。