CloudWatch Agent 設定ファイルの運用を考える

# はじめに

AWS Systems Manager のパラメータストアを利用した Cloudwatch Agent の設定方法があると思います。

https://dev.classmethod.jp/articles/ssm-cloudwatch-agent-parameter-store-run-commmand-setting-method-windows-ver/

この時、パラメータストアのサイズには **4Kもしくは 8K** の制限があり、このサイズを超えてしまった場合は直接 EC2 インスタンスに入り、Cloudwatch Agent の設定ファイルを更新する手間などが発生するかと思います。

https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/parameter-store-advanced-parameters.html

そのため、他の方法で運用できる方法はないか考えて見ました。


# 案1. S3 に設定ファイルを置き、Run Command で取得する

## 概要

![s3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/c32f0955-6609-7dbc-f7a8-10e8e5fd7775.png)


CloudWatch Agent の設定ファイルをあらかじめ S3 バケットにアップロードしておき、Run Command（AWS-RunPowerShellScript や AWS-RunShellScript など）を使って EC2 インスタンス上から aws s3 cp コマンドで取得・配置する方法です。

## バージョン管理

S3 のバージョニングを使って管理すれば良い。

## 前提

- EC2 インスタンスに以下をインストール済
  -  CloudWatch Agent
  -  AWS CLI (環境変数の path に「"C:\Program Files\Amazon\AWSCLIV2\aws.exe"」を追加済)

- RunCommond を実行できること

## 手順

CloudWatch Agent 設定ファイルの準備

大きなファイルまで準備するのは面倒だったので簡易的ですが、以下の CloudWatch Agent 設定ファイルを準備。

```amazon-cloudwatch-agent.json
{
    "agent": {
      "metrics_collection_interval": 60,
      "region": "ap-northeast-1"
    },
    "metrics": {
      "aggregation_dimensions": [
        [
          "InstanceId"
        ]
      ],
      "metrics_collected": {
        "LogicalDisk": {
          "measurement": [
            "% Free Space"
          ],
          "metrics_collection_interval": 60,
          "resources": [
            "*"
          ]
        },
        "Memory": {
          "measurement": [
            "% Committed Bytes In Use"
          ],
          "metrics_collection_interval": 60
        },
        "statsd": {
          "metrics_aggregation_interval": 60,
          "metrics_collection_interval": 10,
          "service_address": ":8125"
        }
      }
    },
    "logs": {
      "logs_collected": {
        "windows_events": {
          "collect_list": [
            {
              "event_levels": [
                "ERROR",
                "WARNING",
                "INFORMATION"
              ],
              "event_name": "Application",
              "log_group_name": "Windows-Application",
              "log_stream_name": "Application_{instance_id}"
            },
            {
              "event_levels": [
                "ERROR",
                "WARNING",
                "INFORMATION"
              ],
              "event_name": "System",
              "log_group_name": "Windows-System",
              "log_stream_name": "System_{instance_id}"
            }
          ]
        }
      }
    }
  } 
```

CloudWatch Agent 設定ファイルを S3 にアップロード

```bash
aws s3 cp amazon-cloudwatch-agent.json s3://<S3バケット名>/web/amazon-cloudwatch-agent.json
```

Run Command で PowerShell スクリプト「AWS-RunPowerShellScript」を実行

```powershell
# AWS CLI のフルパスを指定して S3 からファイルをコピー
& "C:\Program Files\Amazon\AWSCLIV2\aws.exe" s3 cp 's3://XXX-s3/web/amazon-cloudwatch-agent.json' 'C:\Program Files\Amazon\AmazonCloudWatchAgent\amazon-cloudwatch-agent.json'

# CloudWatch エージェントの設定をフェッチして起動
Write-Output "===== Fetching CloudWatch Agent configuration... ====="
& "C:\Program Files\Amazon\AmazonCloudWatchAgent\amazon-cloudwatch-agent-ctl.ps1" `
    -a fetch-config `
    -m ec2 `
    -c file:'C:\Program Files\Amazon\AmazonCloudWatchAgent\amazon-cloudwatch-agent.json' `
    -s

# エージェントのステータスを確認
Write-Host "===== Checking CloudWatch Agent status... ====="
& "C:\Program Files\Amazon\AmazonCloudWatchAgent\amazon-cloudwatch-agent-ctl.ps1" -a status
```

実行結果

```
Completed 1.7 KiB/1.7 KiB (4.1 KiB/s) with 1 file(s) remaining
download: s3://XXX-s3/web/amazon-cloudwatch-agent.json to ..\..\Program Files\Amazon\AmazonCloudWatchAgent\amazon-cloudwatch-agent.json
===== Fetching CloudWatch Agent configuration... =====
****** processing amazon-cloudwatch-agent ******
I! Trying to detect region from ec2
D! [EC2] Found active network interface
I! imds retry client will retry 1 timesSuccessfully fetched the config and saved in C:\ProgramData\Amazon\AmazonCloudWatchAgent\Configs\file_amazon-cloudwatch-agent.json.tmp
Start configuration validation...
2025/01/04 14:54:50 Reading json config file path: C:\ProgramData\Amazon\AmazonCloudWatchAgent\Configs\file_amazon-cloudwatch-agent.json.tmp ...
2025/01/04 14:54:50 I! Valid Json input schema.
D! [EC2] Found active network interface
I! imds retry client will retry 1 times2025/01/04 14:54:50 D! ec2tagger processor required because append_dimensions is set
2025/01/04 14:54:50 D! ec2tagger processor required because append_dimensions is set
2025/01/04 14:54:50 Configuration validation first phase succeeded
Configuration validation second phase succeeded
Configuration validation succeeded
AmazonCloudWatchAgent has been stopped
AmazonCloudWatchAgent has been started
===== Checking CloudWatch Agent status... =====
{
  "status": "running",
  "starttime": "2025-01-04T14:54:51",
  "configstatus": "configured",
  "version": "1.300049.1b929"
}
```


# 案2. SSMドキュメントに直接埋め込む

## 概要 

![ssm.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/3928c8e6-7ac6-7200-2cf4-cfe870e8ac1d.png)


SSMドキュメント（カスタムドキュメント）に設定ファイルを直接埋め込む方法です。

SSMドキュメントであれば、**64KB** まで可能なようです。

https://docs.aws.amazon.com/ja_jp/general/latest/gr/ssm.html

## バージョン管理

ドキュメントをバージョン管理すれば良い。

## 前提

- EC2 インスタンスに以下をインストール済
  - CloudWatch Agent

- RunCommond を実行できること

## 手順

設定ファイルを準備

```amazon-cloudwatch-agent.yaml
description: "Configure and start CloudWatch Agent with the specified configuration, and check its status"
schemaVersion: "2.2"
mainSteps:
  - action: "aws:runPowerShellScript"
    name: "SetupCloudWatchAgentConfig"
    inputs:
      runCommand:
        - |
          Set-Content -Path "C:\Program Files\Amazon\AmazonCloudWatchAgent\amazon-cloudwatch-agent.json" -Value @"
          {
              "agent": {
                "metrics_collection_interval": 60,
                "region": "ap-northeast-1"
              },
              "metrics": {
                "aggregation_dimensions": [
                  [
                    "InstanceId"
                  ]
                ],
                "metrics_collected": {
                  "LogicalDisk": {
                    "measurement": [
                      "% Free Space"
                    ],
                    "metrics_collection_interval": 60,
                    "resources": [
                      "*"
                    ]
                  },
                  "Memory": {
                    "measurement": [
                      "% Committed Bytes In Use"
                    ],
                    "metrics_collection_interval": 60
                  },
                  "statsd": {
                    "metrics_aggregation_interval": 60,
                    "metrics_collection_interval": 10,
                    "service_address": ":8125"
                  }
                }
              },
              "logs": {
                "logs_collected": {
                  "windows_events": {
                    "collect_list": [
                      {
                        "event_levels": [
                          "ERROR",
                          "WARNING",
                          "INFORMATION"
                        ],
                        "event_name": "Application",
                        "log_group_name": "Windows-Application",
                        "log_stream_name": "Application_{instance_id}"
                      },
                      {
                        "event_levels": [
                          "ERROR",
                          "WARNING",
                          "INFORMATION"
                        ],
                        "event_name": "System",
                        "log_group_name": "Windows-System",
                        "log_stream_name": "System_{instance_id}"
                      }
                    ]
                  }
                }
              }
            }
          "@

  - action: "aws:runPowerShellScript"
    name: "FetchingCloudWatchAgentConfig"
    inputs:
      runCommand:
        - |
          Write-Output "===== Fetching CloudWatch Agent configuration... ====="
          & "C:\Program Files\Amazon\AmazonCloudWatchAgent\amazon-cloudwatch-agent-ctl.ps1" -a fetch-config -m ec2 -c file:"C:\Program Files\Amazon\AmazonCloudWatchAgent\amazon-cloudwatch-agent.json" -s

  - action: "aws:runPowerShellScript"
    name: "CheckCloudWatchAgentStatus"
    inputs:
      runCommand:
        - |
          Write-Host "===== Checking CloudWatch Agent status... ====="
          & "C:\Program Files\Amazon\AmazonCloudWatchAgent\amazon-cloudwatch-agent-ctl.ps1" -a status
```

SSM ドキュメントを作成

```
aws ssm create-document \
    --name "CloudWatchAgentConfig-Web" \
    --document-type "Command" \
    --content file://amazon-cloudwatch-agent.yaml \
    --document-format YAML
```

Run Command で 作成した「CloudWatchAgentConfig-Web」を実行
  
実行結果

```
===== Fetching CloudWatch Agent configuration... =====
****** processing amazon-cloudwatch-agent ******
I! Trying to detect region from ec2
D! [EC2] Found active network interface
I! imds retry client will retry 1 timesSuccessfully fetched the config and saved in C:\ProgramData\Amazon\AmazonCloudWatchAgent\Configs\file_amazon-cloudwatch-agent.json.tmp
Start configuration validation...
2025/01/04 15:11:40 Reading json config file path: C:\ProgramData\Amazon\AmazonCloudWatchAgent\Configs\file_amazon-cloudwatch-agent.json.tmp ...
2025/01/04 15:11:40 I! Valid Json input schema.
D! [EC2] Found active network interface
I! imds retry client will retry 1 times2025/01/04 15:11:40 Configuration validation first phase succeeded
Configuration validation second phase succeeded
Configuration validation succeeded
AmazonCloudWatchAgent has been stopped
AmazonCloudWatchAgent has been started

===== Checking CloudWatch Agent status... =====
{
  "status": "running",
  "starttime": "2025-01-04T15:11:40",
  "configstatus": "configured",
  "version": "1.300049.1b929"
}
```


# 最後に

本記事では、AWS Systems Manager のパラメータストアを利用した Cloudwatch Agent の設定方法が使えない場合の代替え方法を主として紹介しているため、メトリクスやログが正常に取得できたところの画像までは記載していませんが、当方で確認したところ問題なくメトリクスやログは取得できていました。

そもそもですが、CloudWatch Logs に送るログを絞れば、AWS Systems Manager のパラメータストアで十分です。そのため、設計の段階で必要なログのみ送るようにすれば良いかと思います。