CloudWatch Syntheticsによる内部ネットワークのURL死活監視

# はじめに

アプリケーションのエンドポイントやURLの監視をCloudWatch Syntheticsで行うことができるそうです。

CloudWatch Syntheticsとは何ぞやについて以下の公式ブログを参照して下さい。
https://aws.amazon.com/jp/blogs/aws/new-use-cloudwatch-synthetics-to-monitor-sites-api-endpoints-web-workflows-and-more/

外部と通信できないクローズドな環境における、CloudWatch Syntheticsでの監視方法について様々な記事を漁ってみたのですが、あまり無いようだったので備忘録として残してみます。

# システム構成図

以下のよう構成で実現したいと思います。
今回は飽くまで動作検証という立ち位置です。

<img width="650" alt="代替テキスト" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624409/55663093-433a-3738-c270-20bad925b8ef.png">

参考URL
https://aws.amazon.com/jp/blogs/mt/monitor-your-private-endpoints-using-cloudwatch-synthetics/
https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Synthetics_Canaries_VPC.html#CloudWatch_Synthetics_Canaries_VPC_troubleshoot

# 構築手順

1. Canary実行ログ保存用のS3バケットを作成する


2. プライベートサブネットの作成


3. VPCエンドポイント(S3,monitor)用セキュリティグループの作成


4. VPCエンドポイント(S3,monitor)の作成


5. EC2インスタンス(Webサーバ用)の作成


6. IAMポリシー、ロールの作成


7. Syntheticsの設定


8. 動作確認



### 1. Canary実行ログ保存用のS3バケットを作成する

Canary実行ログはS3に保存することができます。
バケット名やバージョニング等については適宜、要件に沿うように変更して下さい。

| 設定項目 | 設定値 | 備考 |
| :-- | :- | :-- |
| リージョン | ap-northeast-1 | Canaryと同じリージョンを選択すること |
| パブリックアクセスをすべてブロック | ON |  |

アクセスポリシーに関しては以下を設定します。
**bucketname**と**VPCID**については適宜修正して下さい。

```言語:アクセスポリシー
{
    "Version": "2012-10-17",
    "Id": "Policy1585781604328",
    "Statement": [
        {
            "Sid": "Stmt1585781599291",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": [
                "arn:aws:s3:::<bucketname>",
                "arn:aws:s3:::<bucketname>/*"
            ],
            "Condition": {
                "StringEquals": {
                    "aws:sourceVpc": "<VPCID>"
                }
            }
        }
    ]
}
```

### 2. プライベートサブネットの作成

特別な設定はしないので、こちらは割愛します。
新規に作成するなり、流用するなりでOKです。

なお、Canary（Lambda）やVPCエンドポイントも同じプライベートサブネットを利用する(＝プライベートIPアドレスを消費する)ので、それらを考慮したアドレスレンジで作成して下さい。

### 3. VPCエンドポイント(S3,monitor)用セキュリティグループの作成

VPCエンドポイント用のセキュリティグループを事前に用意しておきます。

HTTPSの443ポートを開けましょう。
ソースIPの開け方はできるだけ絞った方が良いと思います。
（私の環境では10.0.3.0/24と10.0.4.0/24がプライベートネットワークのアドレスです）

![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624409/289b37c4-91e9-c868-a4d0-c11caa7b3cfe.png)

### 4. VPCエンドポイント(S3,monitor)の作成

今回はインターネット接続が無い環境の為、VPCエンドポイントを経由してS3やmonitorのサービスを利用します。
以下の手順に従って、それぞれのVPCエンドポイントを作成して下さい。

なお、Interface型のVPCエンドポイントはお金がかかっちゃうので注意して下さい。

ルートテーブルはプライベートサブネット用のルートテーブルを選択します。
<img width="1000" alt="代替テキスト" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624409/6fcf33fe-7e06-7bb3-800b-1202f3a8b146.png">

プライベートDNS名を利用する場合はチェックを入れて下さい。
セキュリティグループには先程作成したものを指定します。
![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624409/6041b223-f8bf-ae28-b7be-06971a65bdab.png)

ポリシーはデフォルトのフルアクセスのままで。
![7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624409/9ccd94de-4cda-1349-b530-beab7a865d9a.png)

それぞれのステータスが使用可能になるのを確認します。
![8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624409/1e9bdb6f-e86a-cfa6-1b4c-f1ac2de911b5.png)


### 5. EC2インスタンス(Webサーバ用)の作成

ここについても手順は割愛します。
わざわざサーバを起動せず、S3で静的webホスティングさせてSorryページを監視するとかでも検証としては大丈夫だと思います。

一つだけ注意点として、EC2に割り当てるセキュリティグループにはLambdaからのHTTP:80を許可してあげて下さい。


### 6. IAMポリシー、ロールの作成

Canaryの実態はLambdaとなっています。

Canaryの仕組みとしてLambdaからCloudWatchやS3へアクセスしますので、Lambdaに付与するアクセス権限を事前に作成しておきます。(何故かCanaryの設定画面からIAMロールを新規作成できなかったため)

以下のポリシーが付与されているIAMロールが作成できればOKです。


```言語:IAMポリシーその➀
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:PutObject",
                "s3:GetBucketLocation"
            ],
            "Resource": [
                "*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogStream",
                "logs:PutLogEvents",
                "logs:CreateLogGroup"
            ],
            "Resource": [
                "*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:ListAllMyBuckets"
            ],
            "Resource": [
                "*"
            ]
        },
        {
            "Effect": "Allow",
            "Resource": "*",
            "Action": "cloudwatch:PutMetricData",
            "Condition": {
                "StringEquals": {
                    "cloudwatch:namespace": "CloudWatchSynthetics"
                }
            }
        }
    ]
}
```

```言語:IAMポリシーその➁
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents",
                "ec2:CreateNetworkInterface",
                "ec2:DescribeNetworkInterfaces",
                "ec2:DeleteNetworkInterface",
                "ec2:AssignPrivateIpAddresses",
                "ec2:UnassignPrivateIpAddresses"
            ],
            "Resource": "*"
        }
    ]
}
```

### 7. Syntheticsの設定

いよいよ本題のSyntheticsを設定していきます。

[CloudWatch]から[Canary]を選択して[Canaryを作成]をクリックします。
![9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624409/b1c1e3a1-8c65-e69d-a9ee-eab953453608.png)

[設計図を使用する]と[ハートビートのモニタリング]を選択します。
![10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624409/1616da17-d2aa-c5f2-891a-42e60a810224.png)

[アプリケーションまたはエンドポイントURL]に構築したwebサーバのIPアドレスを入力します。
![12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624409/76b90188-8fe1-7bb9-62f5-55a002f8dcb6.png)

[スクリプトエディタ]には既にコードが記述されています。
黒塗りになっている部分に上記で入力したwebサーバのIPアドレスが自動で記述されます。

なお、[Environment variables]で環境変数を設定できるようです。
![13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624409/25608ac3-9f93-a48f-7252-bf35bd41cb04.png)

[スケジュール]と[データ保持]でCanaryの実行スケジュールと保持するデータの期間が選択できます。
Canaryがタイムアウトで処理に失敗する場合は、[追加設定]のタイムアウトの時間を延ばすとよさそうです。

とりあえず今回はデフォルトのままにしてみます。
![14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624409/a735ecbd-3427-7908-a8ea-a648b0afcb7c.png)

[データストレージ]には冒頭に作成したS3を、[アクセス許可]には先程作成したIAMロールを指定します。
何故か、新しいロールを作成が選択できません。
![15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624409/ccecd67e-844f-ce3c-fa42-df6e64822e8f.png)

CloudWatch Alarmと連携することができるそうです。
監視結果の通知先として使えそうです。
![16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624409/215384d6-883f-66ea-273c-1f673ab68c88.png)

オプションの[VPC設定]にてLambdaをVPCに設定することができます。
今回、LambdaはVPC内のプライベートサブネットにアタッチする構成ですので設定していきます。
![17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624409/94918887-f936-6699-3824-cd86720dcfe0.png)

[Active tracing]オプションを有効にすると、X-Rayでトレースできるそうです。

一通り設定が完了したら、[Canaryを作成]をポチりしてみましょう。
![18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624409/582dee33-4ad0-6fd5-2ff4-97e89d63e96f.png)

裏でLambda作ったりしているので、そこそこ時間がかかるっぽいですね。
![19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624409/634f1969-f3f6-2351-b3c3-5e3d7cf898bc.png)

無事に作成されました。
![20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624409/ae0aefd1-5389-1de0-aba1-e18de0b034c9.png)

### 8. 動作確認

最後に動作確認してみたいと思います。

作成直後に既に動作しているので、しばらく待つと以下のように成功ステータスになります。
以降は設定した間隔(今回は5分間隔)でステータスが更新されていきます。
![21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624409/2855d5d0-513b-24f5-f5a0-8756dc8b53e0.png)

ちょろっと中身を見ていきます。

右下に詳細が記載されています。
[Status]がPassedになっていれば、[Destination URL]に存在するwebページ(index.html)が正常にアクセスできていることになります。
![23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624409/b8a375ad-e72b-22aa-00e4-4b0f2865230c.png)

[Screenshots]をクリックすると以下のように監視先のスクリーンショットが表示されます。
![24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624409/ae348c0e-afc5-db5a-7dbf-b5d44c554c2b.png)

次にCanaryの実行ログの保存先を確認していきます。
以下のように正常にCanaryの実行ログがログストリームとして出力されています。
![25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624409/7603eab9-908d-f328-05d0-12766788794b.png)

S3には実行によって生成されたhtmlファイルやJSONなどが出力されています。
![26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624409/da5dc4bd-2d24-c863-b96e-adcc71bddde8.png)

# 最後に
以下、構築をしていてハマったポイントです。

・DocumentRootにhtmlファイルを置いておかないとタイムアウトエラーになる
・LambdaもVPCに設定する必要がある
・Canaryはプライベートサブネットに置かなければならない
・EC2のSGにLambdaからのURL監視用の通信(HTTP:80)を許可する必要がある

以上