さまざまなログをまとめて集中管理できるログ記録/管理ツール「fluentd」 2ページ

fluentdの設定ファイル

 RPMパッケージを利用してfluentdをインストールした場合、設定ファイルは/etc/td-agent/td-agnet.confとなる。この設定ファイルに収集したいイベントやログの出力先などを記述することで、ログの記録が可能になる仕組みだ。

 デフォルトではいくつかの設定が記載されている(リスト1)が、そこで記載されているものは必ずしも必要であるわけではないので、設定内容をすべて破棄し、一から設定項目を記述していったほうが良いだろう。

リスト1 td-agentパッケージに含まれているデフォルトの設定ファイル(抜粋)


## match tag=debug.** and dump to console
<match debug.**>
  type stdout
</match>

####
## Source descriptions:
##

## built-in TCP input
## @see http://docs.fluentd.org/articles/in_forward
<source>
  type forward
</source>

## built-in UNIX socket input
#<source>
#  type unix
#</source>

# HTTP input
# POST http://localhost:8888/<tag>?json=<json>
# POST http://localhost:8888/td.myapp.login?json={"user"%3A"me"}
# @see http://docs.fluentd.org/articles/in_http
<source>
  type http
  port 8888
</source>


 設定ファイルに記述するのは、「source」および「match」、「include」という3つの設定項目(ディレクティブ)だ。

 まず、sourceディレクティブはイベントの受信方法を指定するものだ。「type」キーワードで使用する入力プラグインを指定し、さらに続けてプラグインごとの設定項目を記述していく。

<source>
  type <使用するプラグイン>
  <設定項目1> <設定値1>
  <設定項目2> <設定値2>
  
  
</source>

 matchディレクティブは、受信したイベントをどのように処理するかを条件文とともに指定するものだ。イベントに付加されたタグが指定したた条件文にマッチした場合、指定したプラグインにそのイベントが渡される。書式はsourceディレクトリとほぼ同じだが、matchのあとに条件文を指定する点が異なる。

<match <条件文>>
  type <使用するプラグイン>
  <設定項目1> <設定値1>
  <設定項目2> <設定値2>
  
  
</match>

 条件文内では「*」や「**」といったワイルドカードや、{}を使って複数の条件を指定することができる(表1)。

表1 matchディレクトリの条件文で利用できる特殊記号
記号説明
*任意の単一要素にマッチする
**任意の要素にマッチする。その要素が存在しない場合でもマッチする
{}括弧内の少なくとも1つの要素にマッチする

 たとえば「a.*」という条件文を指定した場合、「a.b」というタグにはマッチするが、「a」や「a.b.c」というタグにはマッチしない。また、「a.**」というタグは「a」や「a.b」、「a.b.c」といったタグにマッチする。

 {}はor演算子のような役割をするもので、{}内でカンマで区切られた複数のタグのどれか1つにマッチすれば条件が成立する。たとえば「{a, b, c}」という条件文は、「a」や「b」、「c」というタグに対してマッチする。

 これらのワイルドカードや演算子は組み合わせて使うことが可能だ。たとえば、「a.{b, c}.*」は「a.b.*」もしくは「a.c.*」のどちらかにマッチすれば条件が成立する。

 最後の「include」ディレクティブは、別の設定ファイルに記述されている内容を読み込むものだ。書式は次のようになる。

include <読み込む設定ファイル>

 読み込む設定ファイルの指定では絶対パスおよび相対パスの両方が使用可能だ。また、ワイルドカード「*」も利用できる。さらに、URLを指定することでネットワーク越しに設定ファイルを取得することも可能だ。

入力プラグインと出力プラグイン

 前述のとおり、fluentdではイベントの入力やログの出力などはすべてプラグインという形で実装されている。

 まず入力プラグインだが、公式で用意されている(fluentdに同梱されている)のは、以下の6つだ(表2)。

表2 fluentdが標準で提供する入力プラグイン
プラグイン名説明
in_forwardTCP/IPを使ってイベントを受け取る。主にほかのfluentdや各言語向けのロギングモジュールからイベントを受け取るのに使われる
in_httpHTTPのPOSTリクエスト経由でイベントを受け取る
in_tailテキストファイルを監視し、そこに書き込まれたテキストをイベントとして受け取る
in_exec指定された外部プログラムを実行し、その出力をイベントとして受け取る。指定されたプログラムは永続的、もしくは指定された時間間隔で定期的に実行される
in_syslogUDPのsyslogプロトコル経由でイベントを受け取る
in_scribeFacebookが開発したログ収集サービス「Scribe」のプロトコル経由でイベントを受け取る

 入力プラグインに関する詳しい説明は、公式ドキュメントで提供されている。

 また、出力プラグインについては次の12個が公式プラグインという位置付けだ(表3)。それぞれの詳細は公式ドキュメントで説明されているので、詳しくはそちらを参照して欲しい。

表3 fluentdが標準で提供する出力プラグイン
プラグイン名種別説明
out_copyNon-Buffered1つ以上の出力先にログを転送する
out_nullNon-Bufferedなにも出力しない
out_roundrobinNon-Buffered指定した1つ以上の出力先にラウンドロビンアルゴリズムを使ってログを転送する
out_stdoutNon-Buffered標準出力にログを出力する
out_exec_filterBuffered引数としてログを与えて外部プログラムを実行し、その入力をイベントとして受け取る
out_forwardBufferedほかのfluentdにネットワーク経由でログを転送する
out_mongoBufferedMongoDBにログを記録する
out_mongo_replsetMongoDBにログを記録する
out_execTime Sliced引数としてログを与えて外部プログラムを実行する
out_fileTime Sliced指定したファイルにログを記録する
out_s3Time SlicedAmazon S3ストレージにログを記録する
out_webhdfsQTime SlicedHDFS(Hadoop Distributed File System)にログを記録する

 なお、出力プラグインについてはイベントを受け取ったら即座に出力する「Non-Buffered」型プラグインと、イベントを一定量蓄積してから出力する「Buffered」型プラグイン、そして一定の時間間隔で出力を行う「Time Sliced」型のプラグインがある。Buffered型プラグインの場合、Bufferとして使うデバイスをプラグインで指定することが可能だ。

 fluentdにはプリセットのBufferプラグインとしてメモリ内にログをバッファリングする「memory」とディスク上のファイルをバッファとして使う「file」が用意されており、どのBufferプラグインを利用するかは各プラグインの設定で指定できる。

設定例:Apacheのアクセスログを記録する

 fluentdの基本的な設定例として、まずはApacheのアクセスログを処理する例を紹介しよう。今回は入力プラグインとして「in_tail」を使用し、Apacheがデフォルトで出力するログはそのまま残したうえでfluentdでログを記録することにする。

 in_tailプラグインは、指定したテキストファイルを監視し、ファイルに新たな行が追加されたらその内容をログとして記録するという動作をする。なお、テキスト形式でログを記録する場合、logrotateというツールで一定期間ごとにログを別ファイルに切り替えたり、ログファイルを圧縮する、といった作業を行うことが多いが、in_tailプラグインではlogrotateを考慮したファイル監視を行うようになっているため、logrotateを利用している場合でも特に追加の設定などを行う必要はない。

 今回は、以下のような条件でApacheのログが記録されているとして設定を行っている。これ以外の環境の場合、適宜設定ファイルやログの形式を確認してほしい。

  • Apacheのログファイルは/var/log/httpd/access_log
  • ログの形式は、Combined Log Format(Apacheデフォルトの「combined」設定)

イベント収集に関する設定

 まず必要なのは、イベントの入力ソースの指定だ。今回は以下のように設定した。

# get apache log
<source>
  type tail  ←in_tailプラグインを指定
  path /var/log/httpd/access_log  ←アクセスログのパスを指定
  tag apache.access  ←ログに付けるタグを指定
  pos_file /var/log/td-agent/httpd-access_log.pos  ←ファイル内のどの行までを読んだかを記録しておくファイルを指定
  format apache2  ←パースするためにログの書式を指定
</source>

 「pos_file」という設定項目は必須ではないものの強く推奨される設定項目で、指定した監視対象ファイルのどの行までを読んだのかを記録しておくのに使用するファイルを指定するものだ。今回は「/var/log/td-agent/httpd-access_log.pos」というファイルを利用するよう指定している。

 また、in_tailプラグインでは指定したログファイルに書き込まれた内容をパースしてJSON形式のレコードに変換する仕組みがあり、「format」設定項目でパースに使用する正規表現を指定できる。主要なフォーマットについてはあらかじめ内部的にパース用の正規表現が組み込まれており、特定のキーワードを利用することでそれを利用できる。たとえば今回はApacheのconbinedフォーマットのログをパースするが、この場合「apache2」というキーワードが利用できる。このキーワードは、以下のような正規表現を指定したものと同様だ。

/^(?<host>[^ ]*) [^ ]* (?<user>[^ ]*) \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^ ]*) +\S*)?" (?<code>[^ ]*) (?<size>[^ ]*)(?: "(?<referer>[^\"]*)" "(?<agent>[^\"]*)")?$/

 これにより、記録されるレコードの「host」要素にはリモートホストが、「user」にはユーザー名が、「method」には使用されたメソッドが……といったように、ログが解析しやすい形で記録される。この場合、取得されたログのレコードの例は以下のようになる。

{
  "host": "**.***.***.***",
  "user": null,
  "method": "GET",
  "path": "/path/to/resource/",
  "code": 200,
  "size": 143320,
  "referer": "http://example.com/path/to/file",
  "agent":"Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0; Touch; MDDCJS)"}
}

ログ出力の設定

 続いて、ログ出力の設定を行っていく。まずはテストとして、ファイルへの出力を行う「out_file」プラグインを使用してみよう。

<match apache.access>  ←対象とするタグを指定
  type file  ←out_fileプラグインを指定
  path /var/log/td-agent/httpd/access.log  ←出力先ファイルを指定
  time_slice_format %Y%m%d  ←ファイル名に含める日時情報を指定
  time_slice_wait 10m  ←ログファイルの更新後に旧ログファイルへのログ記録を継続する時間を指定
  compress gzip  ←ログをgzip形式で圧縮
</match>

 out_fileプラグインは単純にマッチしたログをファイルに出力するだけでなく、日時ごとにログファイルを自動的に分割する機能が用意されており、そのファイル名は「time_slice_format」設定項目で、POSIXのstrftime関数で使われるのと同様のフォーマットで指定できる。今回の例では「%Y%m%d」を指定しているが、この場合はログの記録された日にちごとにファイル名に「.<年><月><日>」という文字列が追加されるようになる。

 なお、fluentdではイベントが発生した時刻と、実際にfluentdにそのログが通知される時刻の間に差が発生することがある。これはfluentdの仕様上避けられないのだが、これによってログファイル名の日時と、実際に記録されるログが異なるという状況が発生しうる。たとえば前日の23:55に発生したイベントが0時を過ぎてからfluentdに通知される、ということがあるのだ。この場合、日にちごとにログを分割するように設定していると、遅延して届いたイベントがログに記録されないという可能性がある。そのため、out_fileプラグインではログの分割時、分割する時刻になってから一定時間待機した後にログの書き出しを行うという仕様になっている。どれだけの時間待機するかは「time_slice_wait」設定項目で指定できる。今回の例の場合は「10m」、つまり10分が指定されている。

 また、ログファイルは日にちだけでなく、一定サイズを超過した場合でも自動的に分割される。デフォルトでは256MBごとの分割となっているが、このサイズはbuffer_chunk_limitオプションで変更可能だ。

 以上の設定を記述後、以下のように設定ファイルのリロードを実行することでイベントの収集とログの記録が開始される。

# /etc/init.d/td-agent reload
もしくは
# service td-agent reload