深夜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分以内に見つかる。

