ログを確実に送信する:出力プラグインとバッファリング
出力プラグインをインストールし、複数のソースを別々の宛先にルーティングし、バックエンドがダウンしてもデータを失わないようにバッファリングを設定します。
ログを収集してパースするのはパイプラインの半分に過ぎません。もう半分は、宛先が一時的に到達不能なときでも、ログを確実に有用な場所に届けることです。このガイドでは、出力プラグインのインストール、複数のソースをそれぞれの宛先にルーティングすること、そして配信を、ベストエフォートではなく信頼できるものにするバッファリング設定を説明します。
出力プラグインをインストールする
Fluentd の組み込み出力は基本的なものをカバーしています(file、stdout、別の Fluentd インスタンスへの forward)。しかし、Elasticsearch、クラウドストレージ、SaaS のログプラットフォームなど、実際の宛先のほとんどは、別のプラグインとして提供され、Fluentd が管理する RubyGems のラッパーである fluent-gem でインストールします。
sudo fluent-gem install fluent-plugin-elasticsearch
素の gem install ではなく fluent-gem を使うことが重要です。システムのデフォルトの Ruby ではなく、Fluentd が実際に使っている Ruby 環境にインストールされるからです。「プラグインをインストールしたのに、Fluentd がまだ見つからないと言う」という混乱の、よくある原因です。Fluentd をコンテナとして動かしている場合は、実行中のコンテナに手動でインストールするのではなく、公式イメージを元に独自のイメージをビルドする一環としてプラグインをインストールしてください。そうすれば、そのコンテナが次に起動したときに、実際に存在しています。
出力を設定する
インストールすれば、Elasticsearch の宛先は、もう 1 つの <match> ブロックにすぎません。
<match apache.access>
@type elasticsearch
host elasticsearch
port 9200
index_name fluentd-apache
</match>
異なるソースを異なる宛先にルーティングする
すべてのソースが同じ場所に行く必要はありません。それぞれ別のタグに限定した複数の <match> ブロックが、同じ設定内で、異なるデータを異なる宛先に送ります。
<match apache.access>
@type elasticsearch
host elasticsearch
port 9200
index_name fluentd-apache
</match>
<match docker.**>
@type elasticsearch
host elasticsearch
port 9200
index_name fluentd-docker
</match>
<match app.**>
@type forward
<server>
host aggregator.internal
port 24224
</server>
</match>
アプリケーションのログは 1 つのインデックスへ、コンテナのログは別のインデックスへ、3 つ目のソースはさらなる処理のためにまったく別の Fluentd インスタンスへ転送されます。これらはすべて同じパイプライン内です。1 つのソースを同時に複数の宛先に送る方法でもあります。同じタグに一致する 2 つの別々の <match> ブロックを定義する(または <copy> セクションを使う)ことで、1 つの Fluentd パイプラインは、ソースごとに 1 つの出力に限られません。
バッファリング:配信を実際に確実にするもの
デフォルトでは、プラグインは宛先に書き込む前にメモリ内でバッファリングします。これは高速ですが、Fluentd がクラッシュまたは再起動すると、まだフラッシュされていないものが失われることを意味します。転送中のログデータの損失が許されない場合は、代わりに明示的なファイルバッファを設定して、バッファリングされたエントリがディスクに永続化され、再起動後も残るようにします。
<match apache.access>
@type elasticsearch
host elasticsearch
port 9200
index_name fluentd-apache
<buffer>
@type file
path /var/log/fluent/buffer/apache
flush_interval 5s
retry_max_times 10
retry_wait 5s
</buffer>
</match>
これは、人々がよく「Fluentd は再起動してもデータを失わない」と説明する動作ですが、正確に言う必要があります。それが真であるのは、自動的にではなく、設定されたファイルバッファがあるからです。メモリバッファでは、フラッシュ中のクラッシュで、キューにあったものが失われます。特定の宛先で確実な配信が重要なら、デフォルトでカバーされていると仮定せず、その宛先に対してファイルバッファを明示的に設定してください。
一時的にダウンしている宛先への対応
同じバッファリング設定が、バックエンドのダウンにも適切に対処します。Elasticsearch(または宛先が何であれ)が到達不能になると、エントリは破棄されるのではなくバッファに蓄積され、Fluentd は retry_wait と retry_max_times で定義されたスケジュールで配信を再試行します。ファイルバッファを設定していれば、その間、バッファされたデータはディスク上で安全に保たれます。宛先が再び到達可能になると、Fluentd は中断したところから追いつきます。これにより、短時間のネットワークの途切れやバックエンドの再起動は、ログの欠落ではなく、何でもない出来事になります。
最終出力の前にマスキングとエンリッチメントを行う
<filter> は、source と match の間のどこにあっても、一致する出力の前に実行されます。そのため、機密データを、宛先に到達する直前に取り除けます。
<filter apache.access>
@type record_transformer
remove_keys remote_addr, user_agent
</filter>
record_transformer は、エンリッチメントに使われるのと同じプラグインです(前のガイドの hostname の例を参照)。remove_keys は、フィールドを追加するのではなく削除する、逆の方向にすぎません。メールアドレス、セッショントークン、内部 IP など、機密性のあるものを、サードパーティの宛先のために自分のインフラから出る前にマスキングするのに適した場所です。宛先が後から正しく処理してくれることに頼るのではなく、ここで行います。