高スループットの Amazon ECS ログの設定
ログスループットの高いシナリオでは、FireLens と Fluent Bit を組み合わせた awsfirelens ログドライバーを使用することをお勧めします。 Fluent Bit は、リソースを効率的に処理し、数百万のログレコードを処理できる軽量ログプロセッサです。ただし、大規模に最適なパフォーマンスを実現するには、その設定を調整する必要があります。
このセクションでは、システムの安定性を維持し、データ損失を回避しながら、高いログスループットを処理するための高度な Fluent Bit 最適化手法について説明します。
FireLens でカスタム設定ファイルを使用する方法については、「カスタム設定ファイルを使用する」を参照してください。その他の例については、GitHub の「Amazon ECS FireLens の例
注記
workers や threaded など、このセクションの一部の設定オプションでは、Fluent Bit バージョン 3 以降の AWS が必要です。使用可能なバージョンについては、「 AWS for Fluent Bit リリース
ファイルシステムのバッファリングを使用する
デフォルトでは、 Fluent Bit はメモリ内のすべてのデータをバッファします。データが出力にフラッシュされるよりも速く取り込まれると、バッファが満杯になります。満杯になると、入力プラグインはバッファスペースが使用可能になるまで一時停止します。これにより、バックプレッシャーが発生し、アプリケーションの速度が低下する可能性があります。
高スループットのシナリオでは、ファイルシステムのバッファリングを使用することをお勧めします。Fluent Bit がバッファリングとストレージを管理する方法の詳細については、 Fluent Bit ドキュメントの「バッファリングとストレージ
ファイルシステムのバッファリングには、次の利点があります。
-
バッファ容量が大きい — 通常、ディスクスペースはメモリよりも豊富です。
-
永続性 – バッファされたデータは Fluent Bit 再起動後も保持されます。
-
グレースフルデグラデーション – 出力の失敗時に、メモリの枯渇を引き起こすのではなく、データがディスクに蓄積されます。
ファイルシステムのバッファリングを有効にするには、カスタム Fluent Bit 設定ファイルを指定します。次の例は、推奨される設定です。
[SERVICE] # Flush logs every 1 second Flush 1 # Wait 120 seconds during shutdown to flush remaining logs Grace 120 # Directory for filesystem buffering storage.path /var/log/flb-storage/ # Limit chunks stored 'up' in memory (reduce for memory-constrained environments) storage.max_chunks_up 32 # Flush backlog chunks to destinations during shutdown (prevents log loss) storage.backlog.flush_on_shutdown On [INPUT] Name forward unix_path /var/run/fluent.sock # Run input in separate thread to prevent blocking threaded true # Enable filesystem buffering for persistence storage.type filesystem [OUTPUT] Name cloudwatch_logs Match * regionus-west-2log_group_name/aws/ecs/my-applog_stream_name $(ecs_task_id) # Use multiple workers for parallel processing workers 2 # Retry failed flushes up to 15 times retry_limit 15 # Maximum disk space for buffered data for this output storage.total_limit_size 10G
主な設定パラメータ:
storage.path-
Fluent Bit がバッファされたチャンクをディスクに保存するディレクトリ。
storage.backlog.flush_on_shutdown-
有効にすると、Fluent Bit はシャットダウン中にすべてのバックログファイルシステムのチャンクを送信先にフラッシュしようとします。これにより、Fluent Bit が停止する前にデータ配信を確保できますが、シャットダウン時間が長くなる可能性があります。
storage.max_chunks_up-
メモリに残っているチャンクの数。デフォルトは 128 チャンクで、各チャンクは最大 4~5 MB を使用できるため、500 MB 以上のメモリを消費する可能性があります。メモリに制約のある環境では、この値を小さくします。たとえば、バッファリングに 50 MB 使用できる場合は、これを 8~10 チャンクに設定します。
storage.type filesystem-
入力プラグインのファイルシステムストレージを有効にします。名前にかかわらず、 Fluent Bit は
mmapを使用してチャンクをメモリとディスクの両方にマッピングし、パフォーマンスを犠牲にすることなく永続性を提供します。 threaded true-
Fluent Bit のメインイベントループとは別に、独自のスレッドで入力を実行します。これにより、遅い入力がパイプライン全体をブロックすることを防ぎます。
出力設定の最適化
ネットワークの問題、サービスの停止、送信先スロットリングにより、ログの配信が妨げられる場合があります。適切な出力設定により、データ損失のない耐障害性を保証します。
出力フラッシュが失敗した場合、 Fluent Bit はオペレーションを再試行できます。次のパラメータは再試行動作を制御します。
retry_limit-
レコードを削除する前の最大再試行回数。デフォルトは 1 です。本番環境では、数分の停止に対応できるよう、エクスポネンシャルバックオフを用いた再試行数を 15 回以上に設定することをお勧めします。
scheduler.base-
再試行間の最小秒数。10 秒をお勧めします。
scheduler.cap-
エクスポネンシャルバックオフを使用する場合の再試行間の最大秒数。60 秒をお勧めします。
workers-
並列出力処理のスレッド数。複数のワーカーが同時フラッシュを許可し、多くのチャンクを処理する際のスループットを向上させます。
[SERVICE] セクションの Grace パラメータは、バッファされたデータをフラッシュするためにシャットダウン中に Fluent Bit が待機する時間を設定します。Grace 期間はコンテナの stopTimeout と調整する必要があります。SIGKILL を受信する前に Fluent Bit がフラッシュを完了できるように、stopTimeout が Grace 期間を超えていることを確認します。たとえば、Grace が 120 秒の場合、 stopTimeout を 150 秒に設定します。
次の例は、高スループットシナリオで推奨されるすべての設定を含む完全な Fluent Bit 設定を示しています。
[SERVICE] # Flush logs every 1 second Flush 1 # Wait 120 seconds during shutdown to flush remaining logs Grace 120 # Directory for filesystem buffering storage.path /var/log/flb-storage/ # Limit chunks stored 'up' in memory (reduce for memory-constrained environments) storage.max_chunks_up 32 # Flush backlog chunks to destinations during shutdown (prevents log loss) storage.backlog.flush_on_shutdown On # Minimum seconds between retries scheduler.base 10 # Maximum seconds between retries (exponential backoff cap) scheduler.cap 60 [INPUT] Name forward unix_path /var/run/fluent.sock # Run input in separate thread to prevent blocking threaded true # Enable filesystem buffering for persistence storage.type filesystem [OUTPUT] Name cloudwatch_logs Match * regionus-west-2log_group_name/aws/ecs/my-applog_stream_name $(ecs_task_id) # Use multiple workers for parallel processing workers 2 # Retry failed flushes up to 15 times retry_limit 15 # Maximum disk space for buffered data for this output storage.total_limit_size 10G
マルチ送信先ログを使用して信頼性を高める
複数の送信先にログを送信すると、単一障害点がなくなります。たとえば、CloudWatch Logs で機能停止が発生した場合でも、ログは Amazon S3 に到達します。
マルチ送信先ログには、次の利点があります。Amazon S3 出力プラグインは、gzip 形式や Parquet 形式などの圧縮オプションもサポートしているため、ストレージコストを削減できます。詳細については、「Fluent Bit ドキュメント」の「S3 圧縮
マルチ送信先ログには、次の利点があります。
-
冗長性 – 一方の送信先が失敗しても、ログはもう一方の送信先に到達します。
-
復旧 – 一方のシステムのギャップを他方のシステムから再構築します。
-
耐久性 – ログを Amazon S3 にアーカイブして長期保持します。
-
コスト最適化 – 最近のログを CloudWatch Logs などの高速クエリサービスに短期間保存し、すべてのログを低コストの Amazon S3 ストレージにアーカイブして長期保持します。
次の Fluent Bit 設定は、CloudWatch Logs と Amazon S3 の両方にログを送信します。
[OUTPUT] Name cloudwatch_logs Match * regionus-west-2log_group_name/aws/ecs/my-applog_stream_name $(ecs_task_id) workers 2 retry_limit 15 [OUTPUT] Name s3 Match * bucketmy-logs-bucketregionus-west-2total_file_size 100M s3_key_format /fluent-bit-logs/$(ecs_task_id)/%Y%m%d/%H/%M/$UUID upload_timeout 10m # Maximum disk space for buffered data for this output storage.total_limit_size 5G
どちらの出力も同じ Match * パターンを使用するため、すべてのレコードは両方の送信先に個別に送信されます。どちらか一方の送信先が停止しても、ログは引き続き他の送信先に流れ続け、失敗したフラッシュは後で再試行できるようにファイルシステムバッファに蓄積されます。
tail 入力プラグインでファイルベースのログを使用する
ログ損失が重大な懸念事項となる高スループットのシナリオでは、別の方法として、アプリケーションがディスク上のファイルにログを書き込み、tail 入力プラグインを使用してそれらを読み取るように Fluent Bit を設定します。このアプローチは、Docker ログドライバーレイヤーを完全にバイパスします。
tail プラグインを使用したファイルベースのログ記録には、次の利点があります。
-
オフセット追跡 – tail プラグインはデータベースファイルにファイルオフセットを保存できるため (
DBオプションを使用)、Fluent Bit 再起動した際に耐久性があります。これにより、コンテナの再起動時にログが消失するのを防ぐことができます。 -
入力レベルのバッファリング –
Mem_Buf_Limitを使用して入力プラグインでメモリバッファ制限を直接設定できるため、メモリ使用量をより詳細に制御できます。 -
Docker のオーバーヘッドを回避 – Docker のログバッファを経由することなく、ログはファイルから Fluent Bit に直接送信されます。
このアプローチを使用するには、アプリケーションが stdout ではなくファイルにログを書き込む必要があります。アプリケーションコンテナと Fluent
Bit コンテナの両方が、ログファイルが保存されている共有ボリュームをマウントします。
次の例は、ベストプラクティスを使用した tail 入力設定を示しています。
[INPUT] Name tail # File path or glob pattern to tail Path/var/log/app.log# Database file for storing file offsets (enables resuming after restart) DB /var/log/flb_tail.db # when true, controls that only fluent-bit will access the database (improves performance) DB.locking true # Skip long lines instead of skipping the entire file Skip_Long_Lines On # How often (in seconds) to check for new files matching the glob pattern Refresh_Interval 10 # Extra seconds to monitor a file after rotation to account for pending flush Rotate_Wait 30 # Maximum size of the buffer for a single line Buffer_Max_Size 10MB # Initial allocation size for reading file data Buffer_Chunk_Size 1MB # Maximum memory buffer size (tail pauses when full) Mem_Buf_Limit 75MB
tail 入力プラグインを使用する場合は、次の点を考慮してください。
-
ディスクの枯渇を防ぐために、アプリケーションログのログローテーションを実装します。基盤となるボリュームメトリクスをモニタリングしてパフォーマンスを測定します。
-
ログ形式に基づいて、
Ignore_Older、Read_from_Headおよび複数行パーサーなどの設定を検討してください。
詳細については、「Fluent Bit ドキュメント」の「Tail
FireLens に直接ログ記録する
awsfirelens ログドライバーがタスク定義で指定されている場合、Amazon ECS コンテナエージェントは次の環境変数をコンテナに挿入します。
FLUENT_HOST-
FireLens コンテナに割り当てられた IP アドレス。
注記
bridgeネットワークモードの EC2 を使用している場合、FireLens ログルーターコンテナ (コンテナ定義にfirelensConfigurationオブジェクトがあるコンテナ) を再起動した後で、アプリケーションコンテナのFLUENT_HOST環境変数が不正確になる可能性があります。これは、FLUENT_HOSTが動的 IP アドレスであり、再起動後に変更される場合があるためです。アプリケーションコンテナからFLUENT_HOSTIP アドレスへの直接的なロギングは、アドレスの変更後に失敗することがあります。個々のコンテナの再起動に関する詳細については、「コンテナ再起動ポリシーを使用して Amazon ECS タスク内の個々のコンテナを再起動する」を参照してください。 FLUENT_PORT-
Fluent Forward プロトコルがリッスンしているポート。
これらの環境変数を使用して、stdout に書き込む代わりに Fluent Forward プロトコルを使用してアプリケーションコードから Fluent
Bit ログルーターに直接ログを記録できます。このアプローチでは、Docker ログドライバーレイヤーをバイパスします。これにより、次の利点が得られます。
-
低レイテンシー – Docker のログインフラストラクチャを経由することなく、ログは Fluent Bit に直接送信されます。
-
構造化ログ – JSON エンコーディングのオーバーヘッドなしで、構造化ログデータをネイティブに送信します。
-
より良い制御 – アプリケーションは独自のバッファリングとエラー処理ロジックを実装できます。
次の Fluent ロガーライブラリは Fluent Forward プロトコルをサポートし、ログを Fluent Bit に直接送信するために使用できます。
-
Go – fluent-logger-golang
-
Python – fluent-logger-python
-
Java – fluent-logger-java
-
Node.js – fluent-logger-node
-
Ruby – fluent-logger-ruby
Docker バッファ制限を設定する
タスク定義を作成する際は、log-driver-buffer-limit で値を指定することで、メモリにバッファリングされるログの行数を指定できます。これにより、Docker と Fluent Bit の間のバッファが制御されます。詳細については、Docker ドキュメントの「Fluentd ロギングドライバー
このオプションは、スループットが高いために Docker がバッファメモリを使い果たし、新しいメッセージを追加するためにバッファメッセージを破棄する可能性がある場合に使用します。
このオプションを使用する場合は、次の点を考慮してください。
-
このオプションは、EC2 およびプラットフォームバージョン
1.4.0以降の Fargate でサポートされています。 -
このオプションは、
logDriverがawsfirelensに設定されている場合にのみ有効です。 -
デフォルトのバッファ制限は
1048576(ログの行数) です。 -
バッファ制限は、
0ログ行以上、536870912ログ行未満である必要があります。 -
このバッファに使用されるメモリの最大量は、各ログ行のサイズとバッファのサイズ積です。たとえば、アプリケーションのログ行が平均
2KiB の場合、4096 のバッファ制限では最大8MiB を使用します。タスクレベルで割り当てられるメモリの合計量は、ログドライバーのメモリバッファに加えて、すべてのコンテナに割り当てられたメモリ量よりも大きくなければなりません。
次のタスク定義は、log-driver-buffer-limit を設定する方法を示しています。
{ "containerDefinitions": [ { "name": "my_service_log_router", "image": "public.ecr.aws/aws-observability/aws-for-fluent-bit:3", "cpu": 0, "memoryReservation": 51, "essential": true, "firelensConfiguration": { "type": "fluentbit" } }, { "essential": true, "image": "public.ecr.aws/docker/library/httpd:latest", "name": "app", "logConfiguration": { "logDriver": "awsfirelens", "options": { "Name": "firehose", "region": "us-west-2", "delivery_stream": "my-stream", "log-driver-buffer-limit": "52428800" } }, "dependsOn": [ { "containerName": "my_service_log_router", "condition": "START" } ], "memoryReservation": 100 } ] }