Amazon Linux 2023でCloudWatch Agentを設定する

[インフォ・ラウンジ Advent Calendar 2023](https://qiita.com/advent-calendar/2023/info-lounge) の16日目です。
# やること
2023年3月にリリースされたAmazon Linux 2023にCloudWatch Agentをインストールしてメトリクスを収集します。

Amazon Linux 2023はFedoraベースとなって（ただしFeroraとの互換性はない）、パッケージ管理ツールがyumからdnfへの変更、5年間のサポートを基本とするライフサイクルなどの変更がありました。

そのため、今までAmazon Linux2で使用していたインストール手順が使えなくなったので改めてまとめてみます。使用したAMIは以下の通りです。

`al2023-ami-2023.2.20231113.0-kernel-6.1-x86_64`

# EC2の準備
まずはCloudWatchを使用できるロールを持ったEC2を立てます。コンソールから立てても構わないのですが、今回はAWS CDKで設定しました。概要は以下のような感じで、インスタンスロールに`CloudWatchAgentServerPolicy`を適用します。また、UserDataを使って起動時にエージェントをインストールしてしまいます。

```typescript
const instance = new ec2.Instance(this, 'Ec2Instance', {
  instanceType: ec2.InstanceType.of(
    ec2.InstanceClass.T3A,
    ec2.InstanceSize.MICRO
  ),
  machineImage: ec2.MachineImage.lookup({
    name: 'al2023-ami-2023.2.20231113.0-kernel-6.1-x86_64',
    owners: ['amazon'],
  }),
  vpc: vpc,
  // CloudWatchのポリシーを持ったロールを設定
  role: new iam.Role(this, 'MediagInstanceRole', {
    assumedBy: new iam.ServicePrincipal('ec2.amazonaws.com'),
    description: 'Role for Mediag Instance',
    managedPolicies: [
      iam.ManagedPolicy.fromAwsManagedPolicyName('CloudWatchAgentServerPolicy')
    ]
  }),
  ssmSessionPermissions: true
}
// dnfでagentをインストール・有効化
instance.addUserData(
  'sudo dnf install amazon-cloudwatch-agent',
  'sudo systemctl enable amazon-ssm-agent',
  'sudo systemctl start amazon-ssm-agent',
)
```

# agentの設定
`ssmSessionPermissions`を有効にしておいたので、セッションマネージャー経由でSSH接続することができます。エージェントは起動しているので、細かい設定をしていきます。

```bash
# インストール確認
$ rpm -qa amazon-cloudwatch-agent
amazon-cloudwatch-agent-1.300028.1-1.amzn2023.x86_64

# ステータスチェック
$ systemctl status amazon-cloudwatch-agent
● amazon-cloudwatch-agent.service - Amazon CloudWatch Agent
     Loaded: loaded (/etc/systemd/system/amazon-cloudwatch-agent.service; enabled; preset: disabled)
     Active: active (running) since Thu 2023-12-07 05:39:16 UTC; 1 week 1 day ago
   Main PID: 714650 (amazon-cloudwat)
      Tasks: 9 (limit: 1066)
     Memory: 50.2M
        CPU: 1h 1min 10.082s
     CGroup: /system.slice/amazon-cloudwatch-agent.service

$ amazon-cloudwatch-agent-ctl -a status
{
  "status": "running",
  "starttime": "2023-12-07T05:39:15+00:00",
  "configstatus": "configured",
  "version": "1.300028.1"
}
```

### 設定ファイル

設定ファイルは、以前(AmazonLinux2)は `/opt/aws/amazon-cloudwatch-agent/bin/config.json`というファイルを置いて読み込んでいたような気がするのですが、`/opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json`に置けば良いようです。ここが一番の注意点かもしれません。

jsonファイル自体は、以前のものを流用できました。ここでは、nginxのアクセスログと、EC2のメモリやディスク使用量を収集するようにしています。細かい設定項目はドキュメントがあります。ウィザードを使用して対話的に作成することもできるようですね。

https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/create-cloudwatch-agent-configuration-file.html


```bash
$ cat /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json
```
```json
{
    "agent": {
        "metrics_collection_interval": 60
    },
    "logs": {
        "logs_collected": {
            "files": {
                "collect_list": [
                    {
                        "file_path": "/var/log/nginx/access.log",
                        "auto_removal" : false,
                        "log_group_name": "/hoge/fuga",
                        "log_stream_name": "nginx_access.log_{instance_id}",
                        "timestamp_format": "%d/%b/%Y:%H:%M:%S %z"
                    }
                ]
            }
        }
    },
    "metrics": {
        "metrics_collected": {
            "mem": {
                "measurement": ["mem_used_percent"]
            },
            "disk": {
                "measurement": ["used_percent"],
                "resources": ["*"]
            }
        },
        "append_dimensions": {
            "ImageId": "${aws:ImageId}",
            "InstanceId": "${aws:InstanceId}",
            "InstanceType": "${aws:InstanceType}",
            "AutoScalingGroupName": "${aws:AutoScalingGroupName}"
        }
    }
}
```

設定ファイルを置いたら、再起動して変更を反映しましょう

```bash
$ sudo systemctl restart amazon-cloudwatch-agent
```

コンソールからCloudWatchを確認して、ロググループやカスタムメトリクスが収集されていればOKです。

うまく収集されていない場合は、ログを見てみるとよいかもしれません。デフォルトの状態ではjournalに出ているようです。

```bash
$ journalctl | grep cloudwatch

Dec 16 04:49:24 ip-10-0-0-87.ap-northeast-1.compute.internal start-amazon-cloudwatch-agent[1331795]: I! Detected the instance is EC2
Dec 16 04:49:24 ip-10-0-0-87.ap-northeast-1.compute.internal start-amazon-cloudwatch-agent[1331795]: 2023/12/16 04:49:24 Reading json config file path: /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json ...
Dec 16 04:49:24 ip-10-0-0-87.ap-northeast-1.compute.internal start-amazon-cloudwatch-agent[1331795]: 2023/12/16 04:49:24 I! Valid Json input schema.
:
```

# まとめ
Amazon Linux 2023でCloudWatch Agentの設定をしてみました。
Amazon Linux 2のサポートは2025年の6月までなので、今後は徐々にAmazon Linux 2023が増えてくると思います。少しずつ変更に慣れていくと良さそうですね。参考になれば嬉しいです。