2026年8月21日

2026年8月21日

Fluent Bitの設定と軽量ログ転送方法(WordPressサーバーのログを集める手順)

Fluent Bit は、サーバー上のログファイルを読み取り、整形・絞り込みをしてから Loki や Elasticsearch、別のログ集約サーバーへ送る軽量なログ転送エージェントです。C 言語で書かれていてメモリ使用量が小さいため、WordPress を載せた小さな VPS にも入れやすいのが特長です。この記事では、Nginx のアクセスログと WordPress の debug.log を例に、インストール、入力・フィルター・出力の設定、転送先が落ちたときのバッファ、動作確認の方法までを説明します。

Fluent Bit の役割と Fluentd との違い

Fluent Bit の処理は「入力(input)→ パーサー(parser)→ フィルター(filter)→ 出力(output)」というパイプラインで組み立てます。ログファイルを読むのが input、1行の文字列を項目に分解するのが parser、不要な行の除外や項目の加工をするのが filter、送り先を決めるのが output です。各レコードには「タグ」が付き、filter と output は match でどのタグを処理するかを指定します。

よく比較される Fluentd は同じプロジェクト系列のツールで、Ruby 製でプラグインの種類が豊富な一方、常駐時のメモリは Fluent Bit より大きくなりがちです。各サーバーには Fluent Bit を入れて収集・転送だけを担わせ、集約側で Fluentd や Loki などが受け取る、という分担がよく使われます。1台の WordPress サーバーのログを外部に送りたいだけなら、Fluent Bit 単体で足ります。

インストールする

公式ドキュメントでは、主要な Linux ディストリビューション向けのパッケージリポジトリと、それを自動で設定するインストールスクリプトが案内されています。スクリプトをそのままシェルに流し込む方法も紹介されていますが、root 権限で実行するものなので、一度保存して中身を確認してから実行するほうが安全です。

curl -fsSL -o /tmp/fluent-bit-install.sh https://raw.githubusercontent.com/fluent/fluent-bit/master/install.sh
less /tmp/fluent-bit-install.sh   # 何をするスクリプトか確認する
sudo sh /tmp/fluent-bit-install.sh

sudo systemctl enable --now fluent-bit
systemctl status fluent-bit
/opt/fluent-bit/bin/fluent-bit --version

パッケージ版では、実行ファイルが /opt/fluent-bit/bin/fluent-bit、設定が /etc/fluent-bit/ に置かれるのが一般的です。古い記事では td-agent-bit というパッケージ名が出てきますが、これは旧名称です。バージョンの系列や配布方法は更新されるので、導入時に公式ドキュメントのインストールページで確認してください。本記事の設定例は、4 系以降の版を想定しています(2026年10月現在)。

設定ファイルの形式を決める

設定には、角かっこでセクションを区切る従来の「classic 形式」(.conf)と、YAML 形式の2種類があります。公式ドキュメントでは新しい機能の多くが YAML 前提で説明されており、classic 形式は将来廃止される方針が示されているため、これから書くなら YAML を選ぶのが無難です。

注意したいのは、パッケージに含まれる systemd のユニットが既定で fluent-bit.conf を読む設定になっている場合がある点です。YAML ファイルを使うときは、起動オプションの -c で YAML ファイルを指定するよう上書きします。

systemctl cat fluent-bit          # ExecStart の -c がどのファイルを指しているか確認
sudo systemctl edit fluent-bit    # 上書き設定を作る
[Service]
ExecStart=
ExecStart=/opt/fluent-bit/bin/fluent-bit -c /etc/fluent-bit/fluent-bit.yaml

ExecStart= を一度空にしてから書き直すのは、systemd では空行で元の値を消さないと「2つ目の ExecStart」と見なされてエラーになるためです。

まずは stdout で入力を確認する

いきなり外部に送ると、パーサーの誤りなのか通信の問題なのか切り分けにくくなります。最初は出力先を標準出力(stdout)にして、ログが期待どおりの項目に分解されているかを見ます。

service:
  flush: 1
  log_level: info
  parsers_file: /etc/fluent-bit/parsers.conf
  http_server: on
  http_listen: 127.0.0.1
  http_port: 2020
  health_check: on

pipeline:
  inputs:
    - name: tail
      path: /var/log/nginx/access.log
      tag: nginx.access
      parser: nginx
      db: /var/lib/fluent-bit/nginx-access.db
      mem_buf_limit: 10MB
      skip_long_lines: on

  outputs:
    - name: stdout
      match: '*'
sudo mkdir -p /var/lib/fluent-bit
sudo /opt/fluent-bit/bin/fluent-bit -c /etc/fluent-bit/fluent-bit.yaml

ポイントは次のとおりです。

  • parser: nginx:同梱の parsers.conf にある Nginx 用パーサーです。Nginx 既定の combined 形式を前提にしているため、log_format を独自に変えている場合は項目がずれます。その場合は JSON 形式でログを出すか、自分の形式に合わせたパーサーを定義します。
  • db:どのファイルのどこまで読んだかを記録するファイルです。これを指定しないと、再起動のたびに読み取り位置が分からなくなり、取りこぼしや重複の原因になります。
  • mem_buf_limit:送信が詰まったときにメモリへ溜める上限です。上限に達すると読み取りを一時停止するので、メモリを使い切ってサーバー全体を巻き込む事態を防げます。

画面に remote、path、code などの項目に分かれたレコードが流れれば入力は成功です。何も出ない場合は、まず Fluent Bit を動かしているユーザーがログファイルを読めるか(Nginx のログは adm グループのみ読める設定が多い)を確認します。

WordPress の debug.log を複数行で読む

WordPress の WP_DEBUG_LOG で出る wp-content/debug.log は、PHP の Fatal error の後にスタックトレースが複数行続きます。1行ずつ読むとトレースがバラバラのレコードになるため、「行頭が日時で始まる行から次の日時の行まで」を1件にまとめる multiline パーサーを定義します。

# /etc/fluent-bit/parsers_multiline.conf
[MULTILINE_PARSER]
    name          wp_debug
    type          regex
    flush_timeout 1000
    rule      "start_state"   "/^\[\d{2}-\w{3}-\d{4} \d{2}:\d{2}:\d{2} [^\]]+\]/"   "cont"
    rule      "cont"          "/^(?!\[\d{2}-\w{3}-\d{4} )/"                          "cont"
service:
  parsers_file: /etc/fluent-bit/parsers_multiline.conf

pipeline:
  inputs:
    - name: tail
      path: /var/www/example.com/wp-content/debug.log
      tag: wp.debug
      multiline.parser: wp_debug
      db: /var/lib/fluent-bit/wp-debug.db
      read_from_head: off

上の YAML は、先ほどの設定に追記する部分だけを抜き出したものです。YAML では同じキーを2回書けないため、Nginx 用の parsers.conf と併用するときは、[MULTILINE_PARSER] の定義を1つのパーサーファイルにまとめて parsers_file で指定するのが簡単です(版によっては YAML の multiline_parsers セクションに直接書く方法もあります)。

なお、debug.log を公開ディレクトリ内に置いたままにすると、URL から直接読まれるおそれがあります。WP_DEBUG_LOG にはファイルパスを渡せるので、公開ディレクトリの外に出力先を移し、そのパスを Fluent Bit の path に指定する構成をおすすめします。

フィルターで量と中身を整える

ログをそのまま全部送ると、転送先の保存容量や料金体系によってはすぐに負担が大きくなります。また、アクセスログの IP アドレスは個人情報として扱われる場合があります。送る前に Fluent Bit 側で絞り込み・加工しておくと、後工程が楽になります。

pipeline:
  filters:
    # 静的ファイルへのアクセスは送らない
    - name: grep
      match: nginx.access
      exclude: path ^/wp-content/(uploads|themes|plugins)/

    # どのサーバーのログか分かるように項目を足す
    - name: modify
      match: '*'
      add: hostname ${HOSTNAME}

    # IPv4 アドレスの末尾を伏せる(Lua スクリプト)
    - name: lua
      match: nginx.access
      script: /etc/fluent-bit/mask_ip.lua
      call: mask_ip
-- /etc/fluent-bit/mask_ip.lua
function mask_ip(tag, timestamp, record)
  local ip = record["remote"]
  if ip then
    record["remote"] = (string.gsub(ip, "%.%d+$", ".0"))
  end
  -- 1 = レコードを変更した
  return 1, timestamp, record
end

この Lua の例は IPv4 だけを対象にしています。IPv6 のアクセスがあるサイトでは別の処理が必要です。どこまで伏せるかは、サイトのプライバシーポリシーやログの利用目的に合わせて決めてください。

出力先を設定し、障害時に備える

入力と加工を確認できたら、出力を実際の転送先に切り替えます。ここでは Grafana Loki に送る例を示します。認証情報は設定ファイルに直接書かず、環境変数から読み込みます。

service:
  storage.path: /var/lib/fluent-bit/storage/

pipeline:
  inputs:
    - name: tail
      path: /var/log/nginx/access.log
      tag: nginx.access
      parser: nginx
      db: /var/lib/fluent-bit/nginx-access.db
      storage.type: filesystem

  outputs:
    - name: loki
      match: '*'
      host: loki.example.com
      port: 443
      tls: on
      tls.verify: on
      http_user: ${LOKI_USER}
      http_passwd: ${LOKI_PASSWORD}
      labels: job=wordpress, host=${HOSTNAME}
      storage.total_limit_size: 500M
      retry_limit: 10

storage.type: filesystem を指定すると、送信できなかったデータをメモリではなくディスクに退避するため、Fluent Bit の再起動や転送先の一時的な停止があってもデータを失いにくくなります。storage.total_limit_size で退避に使うディスク容量の上限を決めておかないと、長時間の障害でディスクを圧迫するので、空き容量と相談して設定します。

環境変数は systemd の上書き設定で Environment= か EnvironmentFile= を使って渡し、ファイルの権限を root のみ読めるようにします。${HOSTNAME} もシェルでは自動で入りますが、systemd から起動したプロセスには渡らないことが多いため、同じ方法で明示的に設定しておきます。Loki のラベルは種類が増えすぎると Loki 側の性能が落ちるため、URL や IP アドレスのような値の種類が多い項目をラベルにしないのが基本です。

動作確認と運用のポイント

設定を変えたら、まず構文を確認してから再起動します。

sudo /opt/fluent-bit/bin/fluent-bit -c /etc/fluent-bit/fluent-bit.yaml --dry-run
sudo systemctl restart fluent-bit
journalctl -u fluent-bit -n 50 --no-pager

# 内部の状態(受け取った件数・送信エラー件数など)
curl -s http://127.0.0.1:2020/api/v1/metrics | head
curl -s http://127.0.0.1:2020/api/v1/health

--dry-run が使えない古い版では、手動起動してエラーが出ないかで確認します。運用では次の点でつまずきやすいので覚えておくと役立ちます。

  • ログローテーション後に読まなくなった:tail 入力はローテーションを追跡しますが、path をワイルドカードにしている場合、ローテーション後の古いファイル(access.log.1 など)まで読んで重複することがあります。exclude_path で除外します。
  • HTTP サーバーを外に公開しない:監視用の 2020 番ポートは 127.0.0.1 で待ち受け、外部から見えないようにします。
  • 送信先が詰まったときの挙動:メトリクスのリトライ件数やエラー件数を Prometheus などで監視しておくと、ログが届いていないことに早く気づけます。

設定変更は、本番サーバーに入れる前にステージング環境か手元の仮想マシンで試し、/etc/fluent-bit/ の設定ファイルはバージョン管理しておくと、元に戻すのが簡単です。

まとめ

  • Fluent Bit は input → parser → filter → output のパイプラインでログを転送する、軽量なエージェントです。
  • 最初は stdout に出してパーサーの結果を確かめ、その後に実際の転送先へ切り替えると、問題を切り分けやすくなります。
  • db で読み取り位置を記録し、storage.type: filesystem と容量上限で転送先の障害に備えます。
  • WordPress の debug.log は multiline パーサーで1件にまとめ、公開ディレクトリの外に置きます。
  • IP アドレスなどの個人情報は送る前に加工し、認証情報は環境変数で渡します。

お気軽にご相談ください

お見積りへ お問い合わせへ
▲