Open15

Kinesis Agent

mappimappi

https://qiita.com/szk3/items/dba1071fb9d344bcd48c

ログ送信の対象となるファイルを選定する実装は、以下に記述されています。
/var/awslogs/lib64/python2.6/site-packages/cwlogs/push.py
ざっくり言うと、パスにマッチしたファイル一覧の中から、変更日付の一番新しいファイルに対して処理を行うようです。

mappimappi

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に転送してしまう気がする。

mappimappi

あるいはローテされたログは出力しないように設定するのも一案

~~中略~~
    "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}"
                    }
                ]
            }
        }
    },
~~中略~~
mappimappi

そもそもログローテーションとログ転送を担保するサービスは分けるべきではないのかもしれない

mappimappi

Kinesis Agent が重複レコードを送信するのはなぜですか?
これはファイルテーリングの設定ミスが原因です。各 fileFlow’s filePattern が それぞれ 1 つのファイルのみと一致するようにします。また、使用されている logrotate モードが copytruncate モードになっている場合にも発生することがあります。重複を避けるため、モードをデフォルトか作成モードに変更してみてください。重複レコードの処理に関する詳細は、「Handling Duplicate Records」を参照してください。

https://docs.aws.amazon.com/ja_jp/firehose/latest/dev/writing-with-agents.html

mappimappi

KinesisエージェントはfilePatternごとにチェックポイント/var/run/aws-kinesis-agent/checkpointsに記録されており、トラッキング対象がlogrotateでcopytruncateとなっている場合、Kinesisエージェントで記録したチェックポイントとの整合性が取れなくなって、当該エラーが発生するようです。

https://qiita.com/ldr/items/f02556a7d9b0c4f91306

mappimappi

Kinesis エージェントが重複するイベントを送信しています
Kinesis エージェントからログを送信するたびに重複を受信する場合は、一致パターンが正しく修飾されていない場所でファイルローテーションが行われている可能性があります。ログを送信するたびに、Kinesis エージェントはファイルパターンに一致する各ファイルの latestUpdateTimestamp をチェックします。デフォルトでは、Kinesis エージェントは、ローテーションパターンに一致するアクティブなファイルを識別し、最も最近更新されたファイルを選択します。複数のファイルが同時に更新された場合、Kinesis エージェントは追跡するアクティブなファイルを判別できません。したがって、Kinesis エージェントは更新されたファイルを最初からテールし始め、いくつかの重複を引き起こします。
この問題を回避するには、個々のファイルごとに異なるファイルフローを作成し、代わりにファイルパターンがローテーションを追跡するようにします。
注: ローテーションを追跡している場合は、copytruncate の代わりに、ログローテーション設定の 作成 または 名前変更 を使用することをお勧めします。
例えば、次のようなファイルフローを使用できます:
"flows": [
{
"filePattern": "/tmp/app1.log*",
"kinesisStream": "yourkinesisstream1"
},
{
"filePattern": "/tmp/app2.log*",
"kinesisStream": "yourkinesisstream2"
}
]

https://repost.aws/ja/knowledge-center/troubleshoot-kinesis-agent-linux

mappimappi

デフォルトでは、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に二重転送することもない。
かつ万が一ローテーションしたログファイルに更新があった場合であってもワイルドカード指定していればログ転送対象になるはず(ここは要検証)

mappimappi

結論

  • logrotate
    • createモードで設定
  • kinesis Agent
    • ワイルドカードを指定してローテーションする
"flows": [
{
"filePattern": "/tmp/app1.log*",
"kinesisStream": "yourkinesisstream1"
},
{
"filePattern": "/tmp/app2.log*",
"kinesisStream": "yourkinesisstream2"
}
]

ただし、今回はlogrotateのみであったが、アプリケーションでログローテーションする場合にcopytruncate方式をとっていた場合にはそもそもKinesis Agentが動作できないため、要検証。

mappimappi

所感

EC2から直接S3転送したいケースがない場合は、CloudWatch AgentかFluentbitを用いた方がいい気がする。
ログローテーションが単純であればいいが、アプリケーション側でハンドリングしている場合はKinesis Agent側でエラーになる可能性もある。
また、Kinesis Agentのupdateも2年前くらいで止まっているため、他にリスク発生する可能性もある。
https://github.com/awslabs/amazon-kinesis-agent

mappimappi

以下課題があるため要検証

  • SSMパラメータストアから取得した値のjq変換
  • 一部ログ参照にAccess Denied発生したため権限見直し
  • Kinesis AgentのメトリクスがCloudwatchに出力されていない