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 にイベントが出力されれば読み取りは成功です。出力されない場合の原因は、起こりやすい順に次のとおりです。
- ログファイルを読む権限がない:
fluentd.logに Permission denied が出ます。fluent-package は専用ユーザー(_fluentd)で動き、Nginx のログは通常 adm グループだけが読めます。ls -l /var/log/nginx/で所有者を確かめ、sudo usermod -aG adm _fluentdでグループに加えてから再起動します。 - pos_file の場所に書き込めない: 同じく権限エラーが出ます。
/var/log/fluent/の下に置けば通常は問題ありません。 - 解析に失敗している: 「pattern not matched」などの警告が出ます。ログの実際の1行と、parse の設定(JSON の形式や正規表現)を見比べます。
- ファイルの途中から読み始めている: 初回は既定でファイルの末尾から読みます。既存の行も読ませたい場合は
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 へは書き込み専用ユーザーで送り、パスワードは環境変数で渡し、バッファに上限を設ける