fluentdでOSのいろんなログをまとめてS3に出力する設定考えてみた

こんにちは、臼田です。

fluentdの設定は自由度が高くて、逆にどうやるのが最適なのかなーと悩むことがよくあります。

今回は「apacheのログを出力したい」のような単体のログではなくて、「OSに保存されているいろんなログを(比較的)楽にS3に出力したい」という需要に答える設定を考えてみました。用途としてはとりあえずローカルの出力されているいろんなアプリログを拾ったりですとか、あとはコンプライアンス用件で細かい様々なログを全てS3に保管したいといったところが上げられると思います。

fluentdの設定値の役割についてもある程度解説しつつ、設定を紹介したいと思います。

なお、インストール方法などは省略します。公式ドキュメントなどをご参照ください。

いろんなログをまとめてS3に出力する設定

まず/etc/td-agent/td-agent.confの設定を共有します。

# read apache logs
<source>
  @type tail
  <parse>
    @type none
  </parse>
  path /var/log/httpd/access_log
  pos_file /var/log/td-agent/tmp/access.log.pos
  tag os.apache.access
</source>

# read secure logs
<source>
  @type tail
  <parse>
    @type none
  </parse>
  path /var/log/secure
  pos_file /var/log/td-agent/tmp/secure.pos
  tag os.secure
</source>

# send to S3
<match os.**>
  @type s3
  s3_bucket yourbucketname
  path ${tag}/
  s3_region ap-northeast-1
  time_slice_format %Y/%m/%d
  s3_object_key_format %{path}%{time_slice}/%{index}.%{file_extension}
  <format>
    @type single_value
  </format>
  <buffer tag,time>
    @type file
    path /var/log/td-agent/s3/${tag}
    timekey 30
    timekey_wait 30
    timekey_use_utc true
  </buffer>
</match>

いくつか設定の説明をします。

全体

複数のsourceを指定して、1つのmatchでS3に出力する構成です。

matchのtagをos.**とすることによってos.から始まるスキーマのタグを全て拾うようにしています。**を指定すると全てのタグを拾う設定になるので一見そちらでいいように感じられますが、実際にはfluentdが内部的に利用しているfluentd.**というスキーマのタグも拾われてしまうため、os.というスキーマを使うようにしてみました。

ワイルドカードの書き方について補足すると、*だと.で区切られた単体の領域のみのワイルドカードのため、複数の.で区切られたタグも一意に拾う場合には**で指定する形になります。ワイルドカードについての公式ドキュメントはこちら

sourceディレクティブ

sourceディレクティブはログが出力されるファイルパスを指定することになるので、取り込むログに対して1個1個指定する事を想定しています。サンプルでは2つだけですが、10個取り込みたいログファイルがあれば10個指定してください。

sourceディレクティブの中のparseディレクティブでnoneタイプを利用しているところが今回工夫している部分です。

例えば通常apacheのアクセスログを取り込む場合にはapache2タイプを利用したり、apacheのエラーログであればapache_errorタイプを選択します。しかしながら、全てのログに対してparseのフォーマットを適用しようとすると、標準に含まれていないparseのプラグインを導入したり、自分で書いたりしないといけないです。

そこまで深く考えずに、とりあえずログをそのままの形式で転送したい場合に利用するのがnoneタイプです。これを利用すると、特にログをパースしないで1つのメッセージとして扱われます。公式ドキュメントはこちら

あとは、tagをos.hoge.fugaとしてあげればOKです。ここで指定するtagがS3に出力する際のprefixに利用されるため、わかりやすい名前付けや階層分けを推奨します。.で分割する階層も任意の数で問題ありません。

matchディレクティブ

上述していますがos.**にて全てのsourceをまとめて1つのmatchで扱うように設定しています。

pathに${tag}を指定することによってログ種別毎にprefixが切られます。その配下はtime_slice等で分けていますが、このあたりは任意です。

sourceでnoneタイプを利用している場合には、出力側ではフォーマットにsingle_valueタイプを利用することが推奨されています。これは対になる役割となっており、メッセージをそのまま出力します。公式ドキュメントはこちら

また、複数のsourceをワイルドカードで扱う場合にはbufferを分けて保存する必要があるため、bufferセクションのpathでも${tag}を含めたり、tagとtimeを利用しているためbufferセクションのチャンクキーにてtag,timeを指定する必要があります。詳細はこちら

おまけ

今回は実施していませんが、例えばAuto Scalingなどで複数のEC2インスタンスからログを出力する際にはprefix等でインスタンスIDを入れたくなります。その場合にはfluent-plugin-ec2-metadataを利用しましょう。

まとめ

fluentdでいろんなログをまとめてS3に出力する設定とその解説をしました。

それぞれの設定値についていろいろ公式ドキュメントを調べる必要があり苦労したので、少しでもわかりやすいようにと思ってまとめました。

ぜひご活用ください。