CloudWatchメトリクスを長期的に保存する！with Amazon Data Firehose(旧Amazon Kinesis Data Firehose)

# CloudWatchメトリクスには保存期間が存在する

以下の記事がとてもわかりやすいです。

https://qiita.com/ryota_886/items/ceb1199400c485ad6596

>AWS CloudWatchのメトリクスデータの保持期間には制約があります。AWSの公式サイトに、以下のような保持期間が設定されていると記載があります。
>
>>60秒未満のデータポイント: 3時間
1分間隔のデータポイント: 15日間
5分間隔のデータポイント: 63日間
1時間間隔のデータポイント: 15か月間
>
>このため、1分間隔のデータポイントは15日間のみ保存され、その後はデータがロールアップされてしまいます。これにより、保持期間を超えたデータポイントは失われてしまいます。

結構な落とし穴ですよね・・・。

今回は、記事で紹介されていた、Cloudwatchメトリクスを、Metric Streams → Data Firehose経由でs3に保存する方法を試してみようと思います！

![cap1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/240e3d78-d46d-972a-6451-e668134753b0.png)

参考：
メトリクスストリームは、AWS Data FirehoseやDatadogなどにメトリクス情報をストリームするサービスです。

https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/CloudWatch-Metric-Streams.html

AWS Data Firehoseは、S3やRedshiftなどにストリームデータを加工・投げ込んでくれるサービスです。

https://docs.aws.amazon.com/ja_jp/firehose/latest/dev/what-is-this-service.html

# 動作確認
## Data Firehose → S3の動作確認
### バケット、Firehose用IAMロールを準備する
メトリクスログを保存するS3バケットを準備します。

![cap02.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/ab1d2f42-faa4-76df-3245-a12876c382aa.png)

下記ドキュメントを参考に、Data Firehoseにアタッチするサービスロールを作成します。

https://docs.aws.amazon.com/ja_jp/firehose/latest/dev/controlling-access.html#using-iam-s3

こんな感じのポリシーを持つロールを作りました。

```policy.json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "s3:PutObject",
                "s3:ListBucketMultipartUploads",
                "s3:ListBucket",
                "s3:GetObject",
                "s3:GetBucketLocation",
                "s3:AbortMultipartUpload"
            ],
            "Effect": "Allow",
            "Resource": [
                "${aws_s3_bucket.main.arn}",
                "${aws_s3_bucket.main.arn}/*"
            ]
        }
    ]
}
```

### Firehoseストリームを作成する

準備ができたので、Firehoseストリームを作成します！

#### マネコンに移動する

![cap03.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/354e27f5-d48c-e6ba-3303-6b96d4950c75.png)

「Firehose ストリームを作成」をクリックします。

#### ソースと送信先を選択する

![cap04.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/43a4ef1c-a037-4762-2425-6054abf50863.png)

ソースをクリックします。

![cap05.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/1dc1d0c5-2c4d-1c3e-27a1-8eba45e9f25d.png)

Direct PUTを選択します。
CloudwatchメトリクスStreamを作成すると、そのリソースがPUT APIを叩いてくれます。

![cap06.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/39fa1f70-ae87-0cd6-48f1-1a5a413cbf3b.png)

送信先はS3を選択します。Datadogとか触ってみたいなー。

#### Firehose ストリーム名を設定する

![cap07.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/4959fe61-60dc-9607-8459-8ef2cd0d1c00.png)

任意のストリーム名を入力します。アカウント内で一意である必要があります。

#### （任意）レコードの変換設定を行う

![cap08.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/bb5b1db0-0ffa-5e0a-a64e-3aa81dff147e.png)

今回はスキップします。SAAの試験で良く問われるやつですね。

#### 送信先の設定を行う

![cap09.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/3f108a47-ec5e-f0f3-a29d-da506caa9039.png)

作成したS3バケットを設定します。

#### 詳細設定を行う

![cap10.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/0fa270f8-5a46-b26c-dbbc-929a0adb2e69.png)

簡単な動作確認なのでログ出力は無効化しておきます。

![cap11.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/6ccab5b8-1e4c-0c70-2629-143f3b9f4b65.png)

選択したIAMロールを使用するよう設定します。

![cap12.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/1eee8bfe-0845-27b3-10b1-c1e99e0678b7.png)

設定内容に問題がなければ、「Firehose ストリームを作成」をクリックします。

#### ストリームがアクティブになることを確認する

![cap13.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/122933c9-7e0c-68ac-e8ad-461f2b8a4e02.png)

ストリームの作成には最大5分かかるらしいです。少し待ちます。

![cap14.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/5ac962d1-2738-adec-1de5-060f05bcf7bd.png)

1分くらいで作成が完了しました。

#### デモデータでテストする
ストリーム詳細画面を下にスクロールします。

![cap15.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/f8848904-70da-30e3-95ba-1062e3a8e04f.png)

「デモデータの送信を開始」ボタンでデモデータをストリームに送信します。

![cap16.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/89305de9-622f-177f-83e8-35c653a58efa.png)

少し待った後、送信を停止します。

![cap20.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/ccdaa911-257a-a1a2-7ec4-eeeda5c32066.png)

デフォルトでは、ストリームは300秒に1度、配信先にデータを配信します。

![cap17.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/47db8de9-a1c4-2548-f783-6a2a4c610f0b.png)

少し待機し、S3を見に行きます。
それっぽいプレフィックスがきられています。

![cap21.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/51ec8916-28c0-b4b3-fd51-c516c867246f.png)

デフォルトでは、ストリームは「YYYY/MM/dd/HH」プレフィックスでオブジェクトを保存します。

![cap18.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/c99bc7d9-6fd4-5e6e-35d7-ab77b2694fc2.png)

デフォルトプレフィックスでオブジェクトが保存されていますね！！

![cap19.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/2eee500d-d797-f54f-e884-9e5cf762899b.png)

中身は意味不明ですが、動いていそうです。
Data Firehose → S3の動作確認ができたので、CloudWatchメトリクスをこのストリームへ配信するためのリソースを作成していきます。


## CloudWatch Metric Streams → Data Firehoseの動作確認
### Metric Streams用IAMロール、メトリクスを収集したいリソースを準備する

下記ドキュメントを参考に、Metric Streamsにアタッチするサービスロールを作成します。

https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/CloudWatch-metric-streams-trustpolicy.html

Metric Streamsは、メトリクスをstream形式で配信してくれるサービス、という認識で大丈夫です。

こんな感じのポリシーを持つロールを作りました。

```policy.json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "firehose:PutRecordBatch",
                "firehose:PutRecord"
            ],
            "Effect": "Allow",
            "Resource": "${aws_kinesis_firehose_delivery_stream.stream.arn}"
        }
    ]
}
```

次に、メトリクスを収集したいリソースを準備します。
今回は、複数のEC2のCPUUtilizationとNetworkOutを収集しようと思います。

![cap22.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/1e06c9a9-8d06-9123-a972-312962ce9fce.png)

適当にEC2を起動しました。


### Metric Streamsを作成する

準備が終わったので、Metric Streamsを作成し、メトリクスをstream形式でData Firehoseに配信してみます！！！

#### マネコンに移動する

![cap23.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/af3b7bcd-e872-d7b9-fa78-f447c0153b79.png)

cloudwatchのマネコンから、「ストリーム」をクリックします。

#### メトリクスストリーム作成画面に移動する

![cap24.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/9fb05f00-a8fe-9734-60ce-2a330fd14684.png)

「メトリクスストリームの作成」をクリックします。

#### セットアップ方法を選択する

![cap25.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/cdd2eb3d-9222-10c9-d82a-d89dbc28f9d9.png)

セットアップ方法が表示されます。

![cap26.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/3cc84c5f-d4ac-a96f-67be-fd85626a3178.png)

デフォルトのクイックセットアップでは、DataFirehoseまで一緒に作られてしまうので、右端の「Custom setup」を選択します。

![cap27.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/cbad2b2c-3102-8845-e004-86f70a412d37.png)

先ほど作成したDataFirehoseのストリームを選択します。

![cap28.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/7b4c7e66-283d-9c04-c4ea-53fd2140d8b0.png)

サービスロールを選択します。デフォルトから変更します。

![cap29.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/ee60bdf8-10c3-8fc1-8dd5-13f2cc85d82d.png)

先ほど作成したIAMロールを選択します。

#### 出力フォーマットを変更する

![cap30.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/8bcd0680-7019-388e-9391-5d229a5ae0fa.png)

今回はログファイルの中身をそのまま確認したいので、JSON形式を選択します。

#### ストリームするメトリクスを設定する

![cap31.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/d11dd1cd-6d0e-adb4-4c57-185d8710ba5c.png)

ストリーム対象のメトリクスを選択します。デフォルトでは全てのメトリクスが対象になっています。

![cap32.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/6c9a1da5-65aa-b123-2692-8d167d9a526b.png)

名前空間を指定します。今回はEC2を対象とします。
Select metrics → Include → EC2 の順に選択します。

![cap33.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/9f8c557d-222b-0798-3875-7e9b78da9251.png)

メトリクスを指定します。
任意のものを指定可能です。

#### メトリクスストリーム名を設定する

![cap34.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/1039e2a4-8cd2-6e97-b0bf-d0ce10450baf.png)

任意の名前を設定します。

#### リソースを作成する

![cap35.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/e6ee91af-215d-79ee-ed29-b5e3fce74be0.png)

「メトリクスストリームの作成」をクリックします。

![cap36.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/25505a31-14e1-fd54-b079-2361425dfc4e.png)

正常に作られました。

### S3にストリームが保存されることを確認する
5~10分ほど待機し、S3を確認します。

![cap37.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654730/09ca3571-9baf-b4ef-f864-e0ab56df0083.png)

来てますね！
中身を確認します。以下のようなjsonが得られました。

```plaintext
{"metric_stream_name":"my-metric-stream","account_id":"123456789012","region":"ap-northeast-1","namespace":"AWS/EC2","metric_name":"CPUUtilization","dimensions":{"InstanceId":"i-05528977c4a5b0e40"},"timestamp":1726301400000,"value":{"max":0.3416780559351978,"min":0.2249962500624989,"sum":0.5666743059976966,"count":2.0},"unit":"Percent"}
{"metric_stream_name":"my-metric-stream","account_id":"123456789012","region":"ap-northeast-1","namespace":"AWS/EC2","metric_name":"NetworkOut","dimensions":{"InstanceId":"i-05528977c4a5b0e40"},"timestamp":1726301400000,"value":{"max":19653.0,"min":19203.0,"sum":38856.0,"count":2.0},"unit":"Bytes"}
{"metric_stream_name":"my-metric-stream","account_id":"123456789012","region":"ap-northeast-1","namespace":"AWS/EC2","metric_name":"CPUUtilization","dimensions":{"InstanceId":"i-00b59eb5cdf98b054"},"timestamp":1726301400000,"value":{"max":0.3584169639582569,"min":0.2248089124244392,"sum":0.5832258763826961,"count":2.0},"unit":"Percent"}
{"metric_stream_name":"my-metric-stream","account_id":"123456789012","region":"ap-northeast-1","namespace":"AWS/EC2","metric_name":"NetworkOut","dimensions":{"InstanceId":"i-00b59eb5cdf98b054"},"timestamp":1726301400000,"value":{"max":23298.0,"min":19131.0,"sum":61704.0,"count":3.0},"unit":"Bytes"}

```

めっちゃ良い感じ！！！
動作確認は以上です。簡単にメトリクスの保存ができました。

# おわりに
メトリクスは永続的に保存されないことを知らず、
障害を復旧させた後、メトリクスを確認しようとしたら、メトリクスが消えていた・・・という経験があります。
今回のような対応で、しっかり永続化しておきたいですね。