今回やること
WindowsのEC2のユーザーデータ実行ログ(標準出力すべて)をCloudWatchLogsに集約したい。
毎度RDPでログを覗きに行くのは非常につらい。
対象の環境
- Windowsインスタンス(Windows Server 2022)
- EC2LaunchV2を使っている
- CloudWatchへ送りたいログはユーザーデータの全Powershell実行ログ
事前にわかっていること
1.ユーザーデータの実行ログ
EC2LaunchV2の場合、Powershell実行ログは決まったファイルに出力される
EC2Launch v2: C:\ProgramData\Amazon\EC2Launch\log\agent.log
2. CloudWatchLogsのログの集約の仕方
EC2にインストールされたCloudWatchLogsエージェントを使って、
実行ログをCloudWatchへ送ることができる。
2通りやり方がある。
- 方法1: CloudWatchエージェントが任意の指定したログファイルをポーリングし、AWS側へ送信
- 方法2: CloudWatchエージェントをUserdata(Powershell)からキックして任意のログメッセージをAWSへ送信
やってみる
2つの方法を試した。
方法1 任意の指定したログファイルを送信
Step1 ユーザーデータの確認
ユーザーデータを記述
<powershell>
date
</powershell>
<persist>true</persist>
インスタンスでログファイルの中身を確認
2023-09-24 06:44:32 Info: Script file is created at: C:\Windows\system32\config\systemprofile\AppData\Local\Temp\EC2Launch3280685567\UserScript.ps1
2023-09-24 06:44:33 Info: Error file is created at: C:\Windows\system32\config\systemprofile\AppData\Local\Temp\EC2Launch3280685567\err.tmp
2023-09-24 06:44:33 Info: Output file is created at: C:\Windows\system32\config\systemprofile\AppData\Local\Temp\EC2Launch3280685567\output.tmp
Sunday, September 24, 2023 6:44:42 AM
複数のEC2LaunchXXXXXXX
フォルダの配下にログが出来る様子。
これはEC2Launchの仕様ではあるが、
agent.log
には大したUserdataの出力結果が残らない。
output.tmp
にUserdataの標準出力が残る様子。
Step2 CloudWatchエージェントのインストール
手順1. Windows Server用のエージェントをインストールする。
手順2. ウィザードを元にConfigファイルを作成する
configをSystemsManagaerのParmaterStoreに保存でき、
そのためのIAMポリシーをインスタンスプロファイルに含めておく必要である。
CLIから対話型でConfig.jsonを生成することができる。
手順3. Cloudwatchエージェントを開始する
cd 'C:\Program Files\Amazon\AmazonCloudWatchAgent\'
& "C:\Program Files\Amazon\AmazonCloudWatchAgent\amazon-cloudwatch-agent-ctl.ps1" -a fetch-config -m ec2 -s -c file:config.json
logファイルが1行ずつCloudLogsにパブリッシュされる。
1行ずつ読まれてログが発行されている様子。
新しく対象のログに行を追加するとCloudWatchのログも増える。
ただし、拡張子が.tmp
のファイルだとCloudWatchエージェントで読み取ってくれなかった。
これではやりたいこと(Userdataの標準出力すべてをCloudWatchへ集約)ができない。
Step3 ユーザーデータに1行加える(Start-Transcript)。
PowershellのStart-Transcript
を使う。
1行設定を加える
<powershell>
Start-Transcript "C:\Users\Administrator\Desktop\output.log"
date
</powershell>
<persist>true</persist>
CloudWatchAgentでこのログを参照するよう設定し、サービスを再スタートする。
{
"logs": {
"logs_collected": {
"files": {
"collect_list": [
{
"file_path": "C:\\Users\\Administrator\\Desktop\\output.log",
"log_group_name": "output.log",
"log_stream_name": "{instance_id}",
"retention_in_days": -1
}
]
}
}
},
結果:無事CloudWatchエージェントに送信できた。Stop-Transcript
が無くても送信できた。
方法2 ユーザーデータ直接からCloudWatchエージェントにログをPushする
方法1でやりたいことはできたが、一応お試しで下記ハンズオンのままやってみた。
この方法だと、Write-LogsEntry
で明示的に指定したエントリだけPublishされる様子。
これでは「Powershell実行ログ全て」が拾えないので、この方法はドロップ。
最後に
CloudWatchエージェントを使ってEC2のWindowsインスタンスのユーザーデータ実行時の標準出力をすべて送信できるようにした。
SSMをインストールしておけば、SSMパラメータストアへのバックアップ、RunCommandでConfig.json
の設定の書き換えもできるっぽい。これ全部使えばでWindowsインスタンスの運用が大分楽になる。全部やらなくては・・・。