Kinesis Agent
懸念点:ログローテーション発生した場合にログ転送漏れが発生しないか確認したい
ログ送信の対象となるファイルを選定する実装は、以下に記述されています。
/var/awslogs/lib64/python2.6/site-packages/cwlogs/push.py
ざっくり言うと、パスにマッチしたファイル一覧の中から、変更日付の一番新しいファイルに対して処理を行うようです。
CloudWatch Agentの場合はマッチしたファイル一覧から変更日付の新しいファイルを転送する仕組み
logrotateした場合にCloudWatch Agent挙動を机上整理してみる。
参考)https://goat-inc.co.jp/blog/2702/
[前提]
- cloudwatch agentは対象ファイルをワイルドカードで指定する
~~中略~~
"logs": {
"force_flush_interval": 5,
"logs_collected": {
"files": {
"collect_list": [
{
"file_path": "/var/log/A.log*",
"log_group_name": "/var/log/A.log",
"log_stream_name": "{instance_id}"
}
]
}
}
},
~~中略~~
[検証]
A.copytruncate方式
①ログ作成
2024-03-22 0:00:00 /var/log/A.log
②ログファイルを作成
2024-03-23 3:00:00 /var/log/A.log
2024-03-23 3:00:00 /var/log/A.log_2024_03_23
③ログをコピー
2024-03-23 3:00:00 /var/log/A.log
2024-03-23 3:01:00 /var/log/A.log_2024_03_23 → コピーされる
④元ファイルのデータを削除
2024-03-23 3:02:00 /var/log/A.log →データ削除
2024-03-23 3:01:00 /var/log/A.log_2024_03_23
「マッチしたファイル一覧から変更日付の新しいファイルを転送する仕組み」に従うと③の段階でコピーしたログをCloudWatch Agentに転送してしまう気がする。
B.create方式/movecreate方式
①ログ作成
2024-03-22 0:00:00 /var/log/A.log
②ログファイルをリネーム
2024-03-23 3:00:00 /var/log/A.log_2024_03_23
③新ファイルを作成
2024-03-23 3:01:00 /var/log/A.log
2024-03-23 3:00:00 /var/log/A.log_2024_03_23
「マッチしたファイル一覧から変更日付の新しいファイルを転送する仕組み」に従うとやはり②の段階でログをCloudWatch Agentに転送してしまう気がする。
あるいはローテされたログは出力しないように設定するのも一案
~~中略~~
"logs": {
"force_flush_interval": 5,
"logs_collected": {
"files": {
"collect_list": [
{
"file_path": "/var/log/A.log",
"log_group_name": "/var/log/A.log",
"log_stream_name": "{instance_id}"
}
]
}
}
},
~~中略~~
そもそもログローテーションとログ転送を担保するサービスは分けるべきではないのかもしれない
Kinesis Agent が重複レコードを送信するのはなぜですか?
これはファイルテーリングの設定ミスが原因です。各 fileFlow’s filePattern が それぞれ 1 つのファイルのみと一致するようにします。また、使用されている logrotate モードが copytruncate モードになっている場合にも発生することがあります。重複を避けるため、モードをデフォルトか作成モードに変更してみてください。重複レコードの処理に関する詳細は、「Handling Duplicate Records」を参照してください。
KinesisエージェントはfilePatternごとにチェックポイント/var/run/aws-kinesis-agent/checkpointsに記録されており、トラッキング対象がlogrotateでcopytruncateとなっている場合、Kinesisエージェントで記録したチェックポイントとの整合性が取れなくなって、当該エラーが発生するようです。
Kinesis エージェントが重複するイベントを送信しています
Kinesis エージェントからログを送信するたびに重複を受信する場合は、一致パターンが正しく修飾されていない場所でファイルローテーションが行われている可能性があります。ログを送信するたびに、Kinesis エージェントはファイルパターンに一致する各ファイルの latestUpdateTimestamp をチェックします。デフォルトでは、Kinesis エージェントは、ローテーションパターンに一致するアクティブなファイルを識別し、最も最近更新されたファイルを選択します。複数のファイルが同時に更新された場合、Kinesis エージェントは追跡するアクティブなファイルを判別できません。したがって、Kinesis エージェントは更新されたファイルを最初からテールし始め、いくつかの重複を引き起こします。
この問題を回避するには、個々のファイルごとに異なるファイルフローを作成し、代わりにファイルパターンがローテーションを追跡するようにします。
注: ローテーションを追跡している場合は、copytruncate の代わりに、ログローテーション設定の 作成 または 名前変更 を使用することをお勧めします。
例えば、次のようなファイルフローを使用できます:
"flows": [
{
"filePattern": "/tmp/app1.log*",
"kinesisStream": "yourkinesisstream1"
},
{
"filePattern": "/tmp/app2.log*",
"kinesisStream": "yourkinesisstream2"
}
]
デフォルトでは、Kinesis エージェントは、ローテーションパターンに一致するアクティブなファイルを識別し、最も最近更新されたファイルを選択します。
B.create方式/movecreate方式
①ログ作成
2024-03-22 0:00:00 /var/log/A.log
②ログファイルをリネーム
2024-03-23 3:00:00 /var/log/A.log_2024_03_23
③新ファイルを作成
2024-03-23 3:01:00 /var/log/A.log
2024-03-23 3:00:00 /var/log/A.log_2024_03_23
②ログファイルをリネームの段階では、「更新」にならない可能性がある。
であればローテーションしたログをKinesis DataFirehoseに二重転送することもない。
かつ万が一ローテーションしたログファイルに更新があった場合であってもワイルドカード指定していればログ転送対象になるはず(ここは要検証)
結論
- logrotate
- createモードで設定
- kinesis Agent
- ワイルドカードを指定してローテーションする
"flows": [
{
"filePattern": "/tmp/app1.log*",
"kinesisStream": "yourkinesisstream1"
},
{
"filePattern": "/tmp/app2.log*",
"kinesisStream": "yourkinesisstream2"
}
]
ただし、今回はlogrotateのみであったが、アプリケーションでログローテーションする場合にcopytruncate方式をとっていた場合にはそもそもKinesis Agentが動作できないため、要検証。
所感
EC2から直接S3転送したいケースがない場合は、CloudWatch AgentかFluentbitを用いた方がいい気がする。
ログローテーションが単純であればいいが、アプリケーション側でハンドリングしている場合はKinesis Agent側でエラーになる可能性もある。
また、Kinesis Agentのupdateも2年前くらいで止まっているため、他にリスク発生する可能性もある。
検証用Terraformコードを以下に整理
以下課題があるため要検証
- SSMパラメータストアから取得した値のjq変換
- 一部ログ参照にAccess Denied発生したため権限見直し
- Kinesis AgentのメトリクスがCloudwatchに出力されていない