なぜログを集中管理するのか:Fluentd が解決する問題
ログが数十のファイルと形式に散らばると何が問題になるか、そして Fluentd の収集、変換、送信のパイプラインがそれをどう解決するか。
1 つのログファイルに書き込む単一のアプリケーションは、読みやすいものです。実際のシステム、つまり複数のサービス、データベース、メッセージブローカー、入口のプロキシが、それぞれ異なる形式で、それぞれの場所にログを書き出すものは、そうではありません。このガイドでは、それが規模が大きくなるとなぜ現実の問題になるのか、そして Fluentd がそれを解決するために使うパイプラインモデルを説明します。
ログは実際に何のためにあるのか
ログは、単なるデバッグの後付けではありません。同じログデータが、通常、複数の異なる目的に同時に役立ちます。
- デバッグ:エラーの前後に何が起きたかを追跡する。
- セキュリティ:同じアドレスからのログイン失敗の繰り返しなど、時間やソースをまたいでイベントを相関させて初めて見える不審な活動を検出する。
- コンプライアンス:業界によっては、特定の記録を定められた期間保持することが求められる。
- 監査:「誰が、いつ、何にアクセスしたか」に、事後に答える。
これらのそれぞれが、個々のマシンに散らばるのではなく、検索可能な 1 か所にデータがあることを必要とします。
ナイーブなロギングが行き詰まる場所
一般的な 2 つの出発点は、システムが大きくなるにつれて、同じ壁にぶつかります。
ローカルファイルへの書き込み。 シンプルで、ほとんどのソフトウェアがデフォルトでログを記録する方法そのものですが、生のテキストファイルは分析向けに作られていません。リクエストがシステムを通ってきた経路を再構築するために、それぞれ形式の異なる 5 つのアプリケーションのログファイルのタイムスタンプを比較するのは、よくても面倒で、手作業ではしばしば現実的ではありません。
データベースへの直接のログ記録。 すべてを Elasticsearch などのストアに直接送ると、今度はすべてのアプリケーションが、独自のクライアントライブラリ、独自の接続処理、どのフィールドと形式を使うかについての独自の合意を必要とします。すべての開発者が、事実上、同じ統合の問題を解き直すことになり、2 回同じ方法で解く保証はどこにもありません。
どちらのアプローチも、コードを制御できないサードパーティコンポーネント、つまりデータベース、メッセージブローカー、ingress コントローラー、あるいは単なるシステムログには対応できません。これらは、自分たちのアプリケーションが決めた形式ではなく、それ自体が作られた形式でログを生成します。
パイプラインモデル:収集、変換、送信
Fluentd のアプローチは、ログが生成される場所と最終的にたどり着く場所の間に、独自のレイヤーとして位置し、3 つの段階を持つパイプラインとして構成されることです。
ソース Fluentd 宛先
┌─────────────┐ ┌───────────────────┐ ┌──────────────────┐
│ アプリログ │ │ │ │ Elasticsearch │
│ システムログ │ ───────▶ │ 収集 → パース │ ───────▶ │ S3 │
│ コンテナの │ │ → フィルター/ │ │ Kafka │
│ stdout │ │ エンリッチ │ │ データベースなど │
└─────────────┘ └───────────────────┘ └──────────────────┘
Fluentd は、ソースや元の形式に関係なく、ログが生成された場所から収集します。構造化されていないテキストをキーと値のデータに変えて、一貫した構造にパースして変換します。その途中で、有用なコンテキスト(どの Pod、どのホスト、どのコンテナがこの行を生成したか)でエントリをエンリッチしたり、不要なものを破棄したり機密フィールドをマスキングしたりしてフィルターしたりできます。最後に、結果を 1 つ以上の宛先に送信します。分析プラットフォーム、データストア、コールドストレージなどです。上流のすべてのアプリケーションが、自分のログが最終的にどこに行き着くかを知ったり、気にしたりする必要はありません。
タグ:Fluentd がパイプライン内でデータをルーティングする方法
Fluentd が収集するすべてのログエントリにはタグが付きます。これは、エントリがどこから来たかを設定する際に割り当てる文字列です。タグは、パイプラインの後段が、何に何を適用するかを決めるために使われます。「apache.access というタグのエントリは Apache のログ形式でパースする」「app.* というタグのエントリはフィルターしてフィールドを削除する」「*.errors というタグのエントリはこの宛先に、それ以外はあちらに送る」といった具合です。その設定の書き方の詳細は、このシリーズの次のガイドで扱います。ここで重要なのは概念です。タグは、データを、それが来たソースから、最終的に送られる場所まで結びつける糸です。
なぜ専用のレイヤーを置く価値があるのか
このようなパイプラインに代わる選択肢は「作業なし」ではなく、ログを出力するすべてのアプリケーションの内部で、同じパース、エンリッチメント、ルーティングのロジックが、一貫性なく、それぞれ少しずつ違う形で再実装されることです。それを 1 つの設定可能なレイヤーに集約することで、そのロジックは 1 度だけ書かれ、新しいアプリケーションは、最も簡単な形式(プレーンテキスト、JSON、サードパーティのツールがすでに書き出しているもの)でログを生成するだけで済みます。そこから先は、Fluentd がそれを一貫したものにします。