UbuntuにFluent Bitをインストール:システムログとDockerコンテナのログ収集、Elasticsearchへの転送

Ubuntu tutorial - IT technology blog
Ubuntu tutorial - IT technology blog

深夜2時17分。Slackにアラートが飛んできた——APIサービスが500エラーを連発している。サーバーにSSHして、各コンテナでdocker logs --tail 100 api_containerを実行し、journalctl -u nginx --since "5 minutes ago"を叩き、PostgreSQLのログファイルをgrepした。15分後もroot causeが見つからない——ログが6カ所に散らばっているからだ。

翌日、2時間かけてFluent Bitを構築した。それ以来——Ubuntu Server 22.04を20台以上のVPSにインストールしてきたが、Fluent Bitのセットアップは必ず最初にやる作業の一つになっている。設定が完了すると一安心できる——次に深夜のインシデントが起きても、手動でgrepしなくて済むとわかっているから。

ログ収集ツールの比較:Logstash、Fluentd、Filebeat、Fluent Bit

インストールに入る前に、適切なツールを選ぶ必要がある。選択を誤ると、後で移行に時間を取られることになる。

Logstash — 高機能だがRAMを大量消費

Elastic Stackのコアメンバーとして、Elasticsearchとのインテグレーションはほぼゼロコンフィグ。柔軟なパイプラインDSLと豊富なプラグインが揃っている。ただし、JVM上で動作するためアイドル時でも300〜500MBのRAMを消費し、ピーク時には1〜2GBに達することもある。アプリケーションが稼働中の2GB RAMのVPSでは、Logstashは小さな部屋に持ち込んだ象のような存在だ。

Fluentd — バランスが取れており、エコシステムが最強

Rubyで動作し、Logstashより軽量(RAM約40〜100MB)。真の強みはその広さにある:Fluentdは数十のソースからログを受け取り、集約・変換して複数の宛先に同時にルーティングできる——思いつくほぼすべてのものに対応するプラグインがある。FluentdとFluent BitはTreasure Dataが開発した兄弟プロジェクトだ。多くの大規模システムでは、各ノードでFluent Bitをエージェントとしてログを収集し、中央のFluentdアグリゲーターに転送して重い処理を行う構成が採用されている。

Filebeat — 軽量だが機能が限定的

Goで書かれており、LogstashとともにElastic Stackファミリー。フットプリントは約30〜50MBとコンパクト。問題は、Filebeatはログをシップするために作られているという点——ファイルを読んで送信する、それだけだ。複雑なログのパースやエンリッチメントが必要な場合は、その処理をElasticsearch Ingest Pipelineに委ねる必要がある。

Fluent Bit — 超軽量で必要十分

C言語ベース。アイドル時のメモリフットプリントはわずか約450KB——間違いではない、メガバイトではなくキロバイトだ。50以上の入力プラグインと40以上の出力プラグインを備え、転送前にパース・フィルタ・エンリッチ・ルーティングを処理できる。systemd + Docker → Elasticsearchのユースケースにおいて、より少ないRAMでより多くのことができるツールは存在しない。

実際のメリット・デメリット分析

  • Logstash:非常に強力で、Elastic Stackとの統合も完璧——ただしRAM 300MB以上のため、小規模VPSの候補から外れる
  • Fluentd:プラグインエコシステムが最強。複数サーバーからのログを集中処理するアグリゲーターノードとして理想的
  • Filebeat:軽量でインストールが簡単だが、フィルタ機能が不足しているためElasticsearchの処理に依存する
  • Fluent Bit:超軽量で、ほとんどのユースケースに十分な機能——フリート内のすべてのノードでエージェントとして実行するのに理想的

結論:各サーバーでFluent Bitを実行し、systemdとDockerからログを収集してElasticsearchに直接転送する。フリートが数十台以内であれば、中間アグリゲーターは不要だ。

Ubuntu 22.04へのFluent Bitインストール

Fluent Bitには公式のaptリポジトリがある——この方法でインストールすれば、以降のapt upgradeで自動的に更新され、追加の手順を覚える必要がない:

# GPG keyと公式リポジトリを追加
curl -fsSL https://packages.fluentbit.io/fluentbit.key | sudo gpg --dearmor -o /usr/share/keyrings/fluentbit-keyring.gpg

echo "deb [signed-by=/usr/share/keyrings/fluentbit-keyring.gpg] https://packages.fluentbit.io/ubuntu/jammy jammy main" | \
  sudo tee /etc/apt/sources.list.d/fluent-bit.list

sudo apt-get update
sudo apt-get install -y fluent-bit

# サービスを有効化して起動
sudo systemctl enable fluent-bit
sudo systemctl start fluent-bit
sudo systemctl status fluent-bit

デフォルトの設定ファイルは/etc/fluent-bit/fluent-bit.confにある。変更前にバックアップを取るのが良い習慣だ:

sudo cp /etc/fluent-bit/fluent-bit.conf /etc/fluent-bit/fluent-bit.conf.bak

システムログとコンテナログの収集設定

systemd/journaldからのログ収集

Fluent Bitのsystemdプラグインはjournaldから直接読み取るため、ファイルを経由しない——ログローテーション時にログを見逃さないという重要な利点がある。設定ファイルに追加する:

[SERVICE]
    Flush        5
    Daemon       Off
    Log_Level    info
    Parsers_File parsers.conf

[INPUT]
    Name            systemd
    Tag             system.*
    Systemd_Filter  _SYSTEMD_UNIT=nginx.service
    Systemd_Filter  _SYSTEMD_UNIT=postgresql.service
    Systemd_Filter  _SYSTEMD_UNIT=docker.service
    Read_From_Tail  On

すべてのシステムログを収集したい場合はSystemd_Filterの行を削除する。ただし、Elasticsearchが受け取るデータ量を減らしてクエリを高速化するため、通常はサービスでフィルタリングしている。

Dockerコンテナからのログ収集

最もシンプルな方法は、Dockerが/var/lib/docker/containers/に作成するログファイルをFluent Bitに直接読み取らせることだ:

[INPUT]
    Name              tail
    Tag               docker.*
    Path              /var/lib/docker/containers/*/*.log
    Parser            docker
    DB                /var/log/fluent-bit-docker.db
    Mem_Buf_Limit     5MB
    Skip_Long_Lines   On
    Refresh_Interval  10

Fluent Bitは専用ユーザーで動作するため、Dockerディレクトリの読み取り権限が必要だ。コマンド一つで解決できる:

sudo usermod -aG docker fluent-bit
sudo systemctl restart fluent-bit

ログデータのフィルタリングとエンリッチメント

systemdの生ログは散らかっていることが多い——サービス名の代わりにコンテナID、アプリケーション間でタイムスタンプが不統一、Elasticsearchには不要な余分なメタデータが大量にある。数行のFILTERでスッキリ整理できる:

# すべてのログレコードにhostnameと環境情報を追加
[FILTER]
    Name   record_modifier
    Match  *
    Record hostname ${HOSTNAME}
    Record env      production

# DockerコンテナのERROR/WARNログのみを保持
[FILTER]
    Name  grep
    Match docker.*
    Regex log (ERROR|WARN|WARNING|FATAL|CRITICAL)

# Node.jsまたはPython structlogアプリのJSONログをパース
[FILTER]
    Name         parser
    Match        docker.*
    Key_Name     log
    Parser       json
    Reserve_Data True

Elasticsearchへのログ転送

es出力プラグインはFluent Bitに組み込まれており、追加インストール不要だ:

[OUTPUT]
    Name              es
    Match             *
    Host              elasticsearch.internal
    Port              9200
    Index             server-logs
    Type              _doc
    Logstash_Format   On
    Logstash_Prefix   server-logs
    Logstash_DateFormat %Y.%m.%d
    Retry_Limit       5

    # Elasticsearchに認証がある場合
    HTTP_User         elastic
    HTTP_Passwd       your_password

    # HTTPSを使用する場合
    tls               On
    tls.verify        Off

Logstash_Format Onを設定すると、Fluent Bitはserver-logs-2026.11.14というフォーマットでインデックスを作成する——Logstashと同じ方式で、後でKibanaのILM(Index Lifecycle Management)を設定する際に便利だ。

テストと結果の確認

サービスを再起動する前に、設定ファイルの構文を確認しよう:

# 設定ファイルの構文チェック(ドライラン)
sudo fluent-bit -c /etc/fluent-bit/fluent-bit.conf --dry-run

# エラーがなければ再起動
sudo systemctl restart fluent-bit

# Fluent Bitのログを監視
sudo journalctl -u fluent-bit -f

ログがElasticsearchに届いているか確認する:

# インデックスが作成されたか確認
curl -X GET "http://elasticsearch.internal:9200/_cat/indices?v&index=server-logs*"

# 最初のレコードをいくつか表示
curl -X GET "http://elasticsearch.internal:9200/server-logs-*/_search?pretty&size=5"

Elasticsearchにserver-logs-YYYY.MM.DDインデックスが表示されれば、ハードな部分は完了だ。Kibanaでインデックスパターンserver-logs-*を作成してDiscoverに移動すれば、すべてのサービスからのログがリアルタイムで流れ込んでくる。

運用上の注意点

  • ディスクバッファリング:Elasticsearchが一時的にダウンしても、Fluent Bitはデータを失う代わりにログをディスクにバッファできる。[SERVICE]セクションにstorage.type filesystemを追加し、storage.pathを指定する
  • バックプレッシャー:Elasticsearchがログ収集速度より処理が遅い場合、Fluent Bitは自動スロットルの仕組みを持っている。小規模サーバーでのOOMを防ぐため、各INPUTでMem_Buf_Limitを制限する
  • フラッシュ間隔:多数のサーバーを持つフリートでは、デフォルトの5の代わりにFlush 10を設定する——リアルタイム性にほとんど影響を与えずにElasticsearchへのリクエスト数を半減できる
  • ログローテーション:tailプラグインはDBパラメータを通じてログローテーションを自動で処理する——追加のlogrotate設定は不要だ

次に深夜2時にアラートが来たとき、6カ所を手動でgrepする代わりに、Kibana Discoverを開いて時間範囲とサービス名でフィルタリングするだけ——root causeはたいてい2分以内に見つかる。

Share: