パラメータストアに設定を配置してCloudWatchLogsにログを送信する方法


#はじめに
ログ収集の設定をパラメータストアに設定しCloudWatchLogsにログ送信できるまで苦労したので記録しておきます。

#前提
・今回はamazonlinux上で試しています。
・事前にamazon-cloudwatch-agentを導入しています。
・事前にシステムマネージャーのマネージドインスタンスに登録しています。

#考え方
まず簡単な流れを説明しますと以下の流れとなります。
①設定の登録・・・パラメータストアにJSON形式でログ収集の設定を登録
②設定の配信・・・パラメータストアの設定をEC2に配信後、CloudWatchAgentに設定を再読み込みさせる

図上のファイルはそれぞれ以下のファイルです。以下の2ファイルは形式が違うだけで同じ内容が格納されます。
当初このことに気づいておらず混乱しました。色々試行錯誤したところ、まずはパラメータストアの内容で「jsonファイル」が作成され
その後に「jsonファイル」が「tomlファイル」に変換されてCloudWathchAgentに読み込まれているようです。

・「jsonファイル」
/opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.d/ssm_amazon-cloudwatch-agent
・「tomlファイル」
/opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.toml

![スクリーンショット 2021-02-06 11.42.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439918/387c61a2-e6b0-a10d-c3b4-f8459e452184.png)





#①設定の登録
以下の流れで設定を登録します。
1.設定の準備・・・json形式で設定ファイルを作成します。
2.設定の登録・・・作成したjsonファイルをパラメータストアに登録します。
3.設定の確認・・・パラメータストアに登録できたことを確認します。

##1.設定の準備
今回はtest.logファイルがcloudwatchLogsに送信されるようにします。
以下の内容で「amazon-cloudwatch-agent.json」ファイルを作成してください。
今回はec2-userのhomeディレクトリに作成しました。

```amazon-cloudwatch-agent.json
{
    "logs": {
        "logs_collected": {
            "files": {
                "collect_list": [{
                    "file_path": "/home/ec2-user/test.log",
                    "log_group_name": "test-group",
                    "log_stream_name": "test-stream"
                }]
            }
        }
    }
}
```

##2.設定の登録
下記コマンドを実行して、先ほど作成した「amazon-cloudwatch-agent.json」ファイルをパラメータストアに追加します。
上書きする場合は「--overwrite」オプションを付けると上書きできます。

```
aws ssm put-parameter --name "amazon-cloudwatch-agent" --value file:///home/ec2-user/amazon-cloudwatch-agent.json --type String 
```

以下の内容が表示されます。上書きしているとVersionがインクリメントされていきます。

```
{
    "Tier": "Standard", 
    "Version": 1
}
```


##3.設定の確認
以下のコマンドを実行し、登録されたパラメータストアの内容を確認します。

```
aws ssm get-parameter --name "amazon-cloudwatch-agent" --output text

```

「amazon-cloudwatch-agent.json」の内容が登録されていることが確認できます。

```
PARAMETER	arn:aws:ssm:ap-northeast-1:235548208075:parameter/amazon-cloudwatch-agent	text	1612580191.82	amazon-cloudwatch-agent	String	{
    "logs": {
        "logs_collected": {
            "files": {
                "collect_list": [{
                    "file_path": "/home/ec2-user/test.log",
                    "log_group_name": "test-group",
                    "log_stream_name": "test-stream"
                }]
            }
        }
    }
}

	1
```

#②設定の配信
パラメータストアに設定を登録できたので、次は以下の流れ配信を行います。
1.設定の配信
2.結果確認
3.ログ送信確認

##1.設定の配信

以下のコマンドを実行して設定を配信します。
インスタンスIDは今回使用しているEC2のインスタンスIDを指定してください。

```
aws ssm send-command \
--document-name "AmazonCloudWatch-ManageAgent" \
--targets "Key=instanceids,Values=インスタンスID" \
--parameters "action=configure, mode=ec2, optionalConfigurationSource=ssm, \
optionalConfigurationLocation=amazon-cloudwatch-agent, optionalRestart=yes" 
```

長々と結果が帰ってきますが、下の方にある「CommandId」を探してメモしておいてください。

```
〜〜〜〜〜〜〜〜〜〜〜〜
        "Comment": "", 
        "ExpiresAfter": 1612595024.449, 
        "DeliveryTimedOutCount": 0, 
        "CommandId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", 
        "Targets": [
            {
                "Values": [
                    "インスタンスID"
                ], 
〜〜〜〜〜〜〜〜〜〜〜〜
```

##2.結果確認

以下のコマンドを実行し、設定の配信が成功したか確認します。
「コマンドID」には前の手順でメモしたものを指定してください。

```
aws ssm list-command-invocations --command-id "コマンドID" --details
```

また長々と結果が返って来ますが上から数行目あたりにある「Status」が「Success」となっていることを確認してください。
失敗している場合はjsonの形式が間違えている可能性があります。詳細は「Status」より下を確認すると記述されています。

```
〜〜〜〜〜〜〜〜〜〜〜〜
{
    "CommandInvocations": [
        {
            "Comment": "", 
            "Status": "Success", 
            "CommandPlugins": [
〜〜〜〜〜〜〜〜〜〜〜〜
```


実際に設定ファイルが配信されているか確認してみるとパラメータストアに登録した内容ががそのまま配信されていることがわかります。

```
cat /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.d/ssm_amazon-cloudwatch-agent

{
    "logs": {
        "logs_collected": {
            "files": {
                "collect_list": [{
                    "file_path": "/home/ec2-user/test.log",
                    "log_group_name": "test-group",
                    "log_stream_name": "test-stream"
                }]
            }
        }
    }
}
```


同様にjsonからtoml形式に変換されたファイルも存在することが確認できます。

```
cat /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.toml

〜〜〜〜〜〜〜〜〜〜〜〜
    [[inputs.logfile.file_config]]
      file_path = "/home/ec2-user/test.log"
      from_beginning = true
      log_group_name = "test-group"
      log_stream_name = "test-stream"
      pipe = false
    [inputs.logfile.tags]
      metricPath = "logs"
〜〜〜〜〜〜〜〜〜〜〜〜

```



##3.ログ送信確認

ログ送信の設定ができたので実際に送信されるか確認します。


以下のコマンドで適当なログファイルを作成してみます。

```
touch test.log
echo send log test1 >> /home/ec2-user/test.log
echo send log test2 >> /home/ec2-user/test.log
echo send log test3 >> /home/ec2-user/test.log
```

次に以下のコマンドでログイベントとして登録されたか確認します。

```
aws logs get-log-events --log-group-name test-group --log-stream-name test-stream --output text
```

以下のような結果が返り、正常にログが登録されたことがわかります。

```
EVENTS	1612582074352	send log test1	1612582068598
EVENTS	1612582074352	send log test2	1612582069348
EVENTS	1612582079410	send log test3	1612582074407
```

#さいごに
以上、CloudWatchAgentの設定をパラメータストアにしてログを送信する方法でした。
今回はCLIで操作しないといけない理由があったのですべてCLIで行いましたが、コンソールを使えばもっとわかりやすい気がします。

#参考
CloudWatch エージェント設定ファイルを手動で作成または編集する
https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/CloudWatch-Agent-Configuration-File-Details.html

インスタンスログの CloudWatch Logs への送信 (CloudWatch エージェント)
https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/monitoring-cloudwatch-agent.html