2026年8月25日

2026年8月25日

Fluentdのインストールとログ収集設定(fluent-packageでNginx・PHPのログをElasticsearchへ送る)

Fluentd でログを集めるには、公式パッケージの fluent-package を入れ、設定ファイルに「どこから読むか(source)」「どこへ送るか(match)」「送れないときにどう溜めるか(buffer)」の3つを書きます。この記事では、WordPress サーバーの Nginx アクセスログと PHP のエラーログを読み取り、Elasticsearch に送るまでを、動作確認と権限エラーの対処を含めて説明します。

fluent-package と td-agent の関係

Fluentd の配布パッケージは、以前は「td-agent」という名前でした。td-agent はすでにサポートが終了しており、後継が「fluent-package」です。古い記事にある td-agent の手順は、パス名やサービス名が異なるため、そのまま使えません。主な違いは次のとおりです。

項目 td-agent(旧) fluent-package
設定ファイル /etc/td-agent/td-agent.conf /etc/fluent/fluentd.conf
サービス名 td-agent fluentd
自身のログ /var/log/td-agent/ /var/log/fluent/
プラグインの導入 td-agent-gem fluent-gem

fluent-package には、長期サポート(LTS)の系列と通常の系列があります(2026年10月現在)。サーバーで長く動かすなら LTS 系列を選びます。対応 OS と導入コマンドは公式ドキュメントの Installation のページにまとまっています。

なお、コンテナ環境やリソースの少ない環境では、より軽量な Fluent Bit が選ばれることもあります。設定の考え方は似ていますが、設定ファイルの書式やプラグインは別物です。

手順1: fluent-package をインストールする

公式ドキュメントでは、OS ごとのインストール用スクリプトが案内されています。スクリプトはリポジトリの登録とパッケージの導入を行うものですが、curl ... | sh でそのまま実行せず、一度ファイルに保存して中身を確認してから実行すると安心です。

# スクリプトのURLは公式ドキュメントで OS と系列に合わせて確認する
curl -fsSL -o install-fluent-package.sh "公式ドキュメントに記載のURL"
less install-fluent-package.sh
sudo sh install-fluent-package.sh

sudo systemctl enable --now fluentd
sudo systemctl status fluentd

インストールの前後で、サーバーの時刻同期(chrony や systemd-timesyncd)が動いているかも確認しておきます。ログの時刻がずれると、後で Kibana などで見たときに並び順がおかしくなります。

手順2: Nginx のログを JSON 形式で出力する

Fluentd は Nginx の標準形式のログも解析できますが、ログの形式を JSON にしておくと、項目の追加や解析の失敗に強くなります。Nginx の http ブロックに次のような形式を定義します。

log_format json_wp escape=json
  '{"time":"$time_iso8601",'
  '"remote_addr":"$remote_addr",'
  '"method":"$request_method",'
  '"path":"$uri",'
  '"status":$status,'
  '"body_bytes_sent":$body_bytes_sent,'
  '"request_time":$request_time,'
  '"referer":"$http_referer",'
  '"user_agent":"$http_user_agent"}';

access_log /var/log/nginx/access_json.log json_wp;

$uri はクエリ文字列を含みません。クエリ文字列には、検索語やメールアドレスなどが入ることがあるため、必要がなければ記録しない方が個人データの扱いの面でも無難です。IP アドレスもログに残る個人に関わる情報なので、保存期間を決め、プライバシーポリシーの記載と合っているかを確認します。

設定後は sudo nginx -t で構文を確認してから再読み込みします。

手順3: 読み取り元(source)を設定する

/etc/fluent/fluentd.conf を編集します。変更前にコピーを取っておきます。まずは送り先を標準出力にして、読み取りができているかだけを確かめるのが安全な進め方です。

<source>
  @type tail
  path /var/log/nginx/access_json.log
  pos_file /var/log/fluent/nginx-access.pos
  tag nginx.access
  follow_inodes true
  <parse>
    @type json
    time_key time
    time_format %Y-%m-%dT%H:%M:%S%z
  </parse>
</source>

<match nginx.access>
  @type stdout
</match>

各項目の意味は次のとおりです。

  • @type tail: ファイルの末尾に追記された行を読み続けます。
  • pos_file: どこまで読んだかを記録するファイルです。再起動しても続きから読めます。Fluentd の実行ユーザーが書き込める場所に置きます。
  • tag: イベントに付ける名前です。match はこのタグで送り先を振り分けます。
  • follow_inodes: ログのローテーションでファイルが入れ替わっても、読み漏れや二重読みを起こしにくくする設定です。
  • <parse>: 1行をどう分解するかの指定です。ここでは JSON として読み、time 項目をイベントの時刻にします。

PHP のエラーログ(複数行)を読む

PHP のエラーログは、スタックトレースのように1件が複数行にまたがります。1行ずつ別のイベントにならないよう、行頭の日時を手がかりにまとめます。WordPress のデバッグログを使う場合は、WP_DEBUG_LOG にパスを指定して公開ディレクトリの外へ出力しておきます。

<source>
  @type tail
  path /var/log/php/wp-error.log
  pos_file /var/log/fluent/wp-error.pos
  tag wp.php_error
  multiline_flush_interval 5s
  <parse>
    @type multiline
    format_firstline /^\[\d{2}-[A-Za-z]{3}-\d{4} /
    format1 /^\[(?<time>[^\]]+)\] (?<message>.*)/m
    time_format %d-%b-%Y %H:%M:%S %Z
  </parse>
</source>

format_firstline に一致した行から次の一致行の手前までが1件になります。multiline_flush_interval を付けないと、最後の1件が次のエラーが出るまで送られないことがあります。

手順4: 設定を検証して起動する

設定を書き換えたら、再起動の前に構文を検証します。

sudo fluentd --dry-run -c /etc/fluent/fluentd.conf
sudo systemctl restart fluentd
sudo tail -f /var/log/fluent/fluentd.log

Nginx にアクセスして、fluentd.log にイベントが出力されれば読み取りは成功です。出力されない場合の原因は、起こりやすい順に次のとおりです。

  1. ログファイルを読む権限がない: fluentd.log に Permission denied が出ます。fluent-package は専用ユーザー(_fluentd)で動き、Nginx のログは通常 adm グループだけが読めます。ls -l /var/log/nginx/ で所有者を確かめ、sudo usermod -aG adm _fluentd でグループに加えてから再起動します。
  2. pos_file の場所に書き込めない: 同じく権限エラーが出ます。/var/log/fluent/ の下に置けば通常は問題ありません。
  3. 解析に失敗している: 「pattern not matched」などの警告が出ます。ログの実際の1行と、parse の設定(JSON の形式や正規表現)を見比べます。
  4. ファイルの途中から読み始めている: 初回は既定でファイルの末尾から読みます。既存の行も読ませたい場合は read_from_head true を加えます。

手順5: Elasticsearch へ送る

読み取りを確認できたら、送り先を Elasticsearch に切り替えます。fluent-package には Elasticsearch 用のプラグインが同梱されていることが多いですが、念のため確認します。

sudo fluent-gem list | grep elasticsearch

プラグインの版と Elasticsearch の版の組み合わせによっては、接続時にエラーになることがあります。その場合はプラグインの README で対応表を確認してください。

Elasticsearch への接続には、管理者の elastic ではなく、ログ用インデックスへの書き込み権限だけを持つユーザーを使います。パスワードは設定ファイルに直接書かず、環境変数で渡します。sudo systemctl edit fluentd で次の設定を加えます。

[Service]
EnvironmentFile=/etc/fluent/es.env
# /etc/fluent/es.env の中身は ES_PASSWORD=your-es-password の1行
sudo chmod 600 /etc/fluent/es.env

送り先の設定は次のようになります。

<match nginx.access>
  @type elasticsearch
  host 127.0.0.1
  port 9200
  scheme https
  ssl_verify true
  ca_file /etc/fluent/certs/http_ca.crt
  user fluentd_writer
  password "#{ENV['ES_PASSWORD']}"
  logstash_format true
  logstash_prefix nginx-access
  <buffer>
    @type file
    path /var/log/fluent/buffer/nginx-access
    flush_interval 10s
    chunk_limit_size 8MB
    total_limit_size 1GB
    retry_max_interval 60s
    overflow_action drop_oldest_chunk
  </buffer>
</match>

logstash_format true を指定すると、nginx-access-2026.10.18 のように日付ごとのインデックスに書き込まれ、Kibana では nginx-access-* で一括して扱えます。ca_file には Elasticsearch の CA 証明書のコピーを置き、_fluentd ユーザーが読めるようにします。

バッファの設定は、Elasticsearch が止まっている間の振る舞いを決めます。

  • @type file: 送れなかったログをディスクに溜めます。Fluentd を再起動しても失われません。
  • total_limit_size: 溜める量の上限です。上限がないと、送り先の障害が長引いたときにディスクを使い切ります。
  • overflow_action: 上限に達したときの動作です。drop_oldest_chunk は古いものから捨てます。ログを捨てたくない場合は別の動作を選びますが、その分、読み取り側が止まることを理解したうえで決めます。

まとめ

  • Fluentd は fluent-package で導入する。td-agent の手順はパスやサービス名が違うので使わない
  • 設定は source(読み取り元)・match(送り先)・buffer(溜め方)の3つで考える
  • Nginx のログは JSON 形式にし、クエリ文字列や IP の扱いはプライバシーポリシーと合わせる
  • まず stdout へ出して読み取りを確かめ、--dry-run で検証してから再起動する
  • 読めないときは、_fluentd ユーザーの権限、pos_file、解析設定の順に確認する
  • Elasticsearch へは書き込み専用ユーザーで送り、パスワードは環境変数で渡し、バッファに上限を設ける

お気軽にご相談ください

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