CloudWatch Agent 仕込み済み AMI からEC2インスタンスを作成するときの注意点

# 概要
CloudWatch Agent 仕込み済み AMI から EC2インスタンス を作成すると、作成された EC2インスタンス の CloudWatch Agent の設定ファイルの "log_stream_name" には元のEC2インスタンスの情報が残ってしまう。
そのため、新しく作成したEC2インスタンスのログも、元のEC2インスタンスの CLoudWatch ロググループ (ログストリーム）へ送られてしまう。

例） 新しく作成した EC2インスタンス（インスタンスID: i-07711e9e622631299）の cloudwatch agent の設定ファイル
> /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.toml
>>
〜
  [[outputs.cloudwatchlogs]]
    file_name_field_key = "file_name"
    file_state_folder = "/opt/aws/amazon-cloudwatch-agent/logs/state"
    log_entry_field_key = "value"
    log_group_name_tag_key = "log_group_name"
    log_stream_name = "i-0f00fefdaa33fbc2a"　<font color="red">← 新しいEC2インスタンスIDではなく、元のEC2インスタンスIDになっている</font>
    log_stream_name_tag_key = "log_stream_name"
    log_timestamp_field_key = "log_timestamp"
    multi_line_start_field_key = "multi_line_start"
    offset_field_key = "offset"
    region = "ap-northeast-1"
〜

# 対策
CloudWatch Agent の設定ファイルを初期化するコマンドを cloud-init に仕込んで AMI を作成する。
その AMI を使って EC2インスタンス を作成すれば、EC2インスタンス初期起動時に CloudWatch Agent 初期化コマンドが実行されるので、新しい EC2インスタンスの CloudWatch Agent の設定ファイル を、その新しい EC2インスタンスの情報にアップデートすることができる。

* cloud-init に仕込む内容

> /etc/cloud/cloud.cfg
>>
〜<font color="red">
 \# CloudWatch Agent
runcmd:
- /opt/aws/amazon-cloudwatch-agent/bin/config-downloader --output-file /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json --download-source ssm:agent-config-linux --mode ec2 --config /opt/aws/amazon-cloudwatch-agent/etc/common-config.toml
- /opt/aws/amazon-cloudwatch-agent/bin/config-translator --input /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json --output /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.toml --mode ec2 --config /opt/aws/amazon-cloudwatch-agent/etc/common-config.toml
- /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent -schematest -config /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.toml
- /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -m ec2 -a stop
- /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -m ec2 -a start</font>

# 解説
上記 runcmd で実行させるコマンドの実行内容は、「[CloudWatch エージェントを開始する](https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/install-CloudWatch-Agent-on-EC2-Instance-fleet.html#start-CloudWatch-Agent-EC2-fleet)」の "Systems Manager Run Command を使用して CloudWatch エージェントを開始する" で行っていることと同等。

1. AWS Systems Manager の "agent-config-linux" という名前の Parameter Store をダウンロードして、/opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json に保存する
> /opt/aws/amazon-cloudwatch-agent/bin/config-downloader --output-file /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json --download-source ssm:agent-config-linux --mode ec2 --config /opt/aws/amazon-cloudwatch-agent/etc/common-config.toml

2. jsonフォーマット を toml フォーマットへ変換する
>/opt/aws/amazon-cloudwatch-agent/bin/config-translator --input /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json --output /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.toml --mode ec2 --config /opt/aws/amazon-cloudwatch-agent/etc/common-config.toml

3. schematest
> /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent -schematest -config /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.toml

4. amazon-cloudwatch-agent の再起動 (amazon-cloudwatch-agent.toml を読み込みなおすため）
>/opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -m ec2 -a stop
> /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -m ec2 -a start

# 2019/03/10更新

おそらく、[Amazon CloudWatch エージェントが Procstat プラグインおよび複数の設定ファイルのサポートを追加](https://aws.amazon.com/jp/about-aws/whats-new/2019/01/amazon-cloudwatch-agent-adds-support-for-procstat-plugin-and-multiple-configuration-files/0) のタイミングで、config-downloader コマンドから --output-file オプションがなくなった。
そして、次の一連のコマンドが、

```
/opt/aws/amazon-cloudwatch-agent/bin/config-downloader --output-file /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json --download-source ssm:cloudwatch-agent-basic-config --mode ec2 --config /opt/aws/amazon-cloudwatch-agent/etc/common-config.toml
/opt/aws/amazon-cloudwatch-agent/bin/config-translator --input /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json --output /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.toml --mode ec2 --config /opt/aws/amazon-cloudwatch-agent/etc/common-config.toml
/opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent -schematest -config /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.toml
```

次のコマンド１つで行えるようになった。

```
/opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -c ssm:cloudwatch-agent-basic-config -s
```

※参考
[開始方法: CloudWatch エージェントを最初のインスタンスにインストールする
](https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/install-CloudWatch-Agent-on-first-instance.html#CW-Agent-Instance-Create-Configuration-File-first)⇒コマンドラインを使用して Amazon EC2 インスタンスで CloudWatch エージェントを開始する



さらに、この新しいバージョンの CloudWatch エージェントを仕込んだ AMI から EC2インスタンス を作成すると、作成された EC2インスタンスは上記の様に cloud-init 設定とかを特に行わなくても、新しいEC2インスタンスの情報が反映されるようになり、CloudWatch ロググループにログが転送されるようになった。