読者です 読者をやめる 読者になる 読者になる

Septeni Engineer's Blog

セプテーニエンジニアが綴る技術ブログ

fluentdをとりあえず導入してみる

みなさまこんばんわ。さげはしです。
さてさて、今月は怒涛の忙しさで目を回しておりますが、そんな中でも試みというのがありましたので、とりあえずタイトルの通り、ひと波遅れた感じでfluentd導入検証記事となります。
f:id:s_hayase:20150722155157p:plain

fluentdの概要

fluentdについては今更説明不要だと思いますが、とりあえず動きとしては、ログの送信とかをするエージェントとそれを受信してゴニョゴニョするコレクターの2つ役割があって、あとはご想像の通りなんでもできちゃうんじゃないかなーという感じです。

そこで、今回はパフォーマンスは置いておいて、まずは動かす所に主題をおいて導入までをまとめます。
fluentdを入れて何をしたいって、Apacheログとかアプリログを準リアルタイムに順次処理するのをまずはイメージすると思うので、それを力技でやってしまいます。

なお、多分に漏れず、CentOS6系での動作を前提として、以下の環境と仮定します。
エージェント側:192.168.1.1
コレクター側 :192.168.1.2

インストール

何はともあれ、まずはインストールです。
色々調べると「エージェント側は公式rpmで、コレクター側はrubyのgemで最新を追え!」ということが書いてあったりしますが、それは全てトップランナーの方の言葉で〜という事もありますが、最近は結構rubyのバージョンが追いついてきてるので、クリティカルなことがなければ、公式rpmの方がいいと思います。

ということで、エージェント及びコレクター両方共、公式rpmからインストールします。
手順?公式サイトの導入手順があるのに、ここで説明するのも野暮でしょう。ただ一言だけ、

curl -L http://toolbelt.treasure-data.com/sh/install-redhat.sh | sh

です。

設定:エージェント側

ここから設定ファイルに突入です。
とりあえずファイルを送りたい、その一心で以下の様なファイルを用意します。

# /etc/td-agent/td-agent.conf
<source>
  type tail
  format ltsv
  path /tmp/app.log
  tag app.log
  pos_file /tmp/tda-pos.txt
</source>
<match app.**>
  type forward
  <server>
    host 192.168.1.2
    port 24224
  </server>
  flush_interval 1s
</match>

意味分からないですか?ですよね。とりあえず設定の内容を文章で説明すると、
【ltsvフォーマットの/tmp/app.logをtailして、app.logってタグを付けて192.168.1.2:24224に1秒おきに送信】という感じです。
ltsvについてはここを参照
分からなくても、とりあえずこれで動くので放置しますよ。
大事なのはとりあえず動く環境を作って、そこから自分のやりたいことを試行錯誤することなので。

設定:コレクター側

コレクター側はこんな感じ。

# /etc/td-agent/td-agent.conf
<source>
  type forward
  port 24224
</source>

<match app.**>
  type exec_filter
  tag app.test
  in_format json
  out_format json
  command /etc/td-agent/bin/exec_filter_test.rb
  flush_interval 1s
</match>

これは【Port:24224で受けたデータをjsonフォーマットで/etc/td-agent/bin/exec_filter_test.rbに渡す】というだけです。
本来はここで色々と設定すると色々とまあ出来るんですが、そこがまずハマりどころだと思うので、もう外部ファイルに全部任せちゃいましょう!これで殆どのことはクリアになり、exec_fileter_test.rbの処理に集中出来ます。

コレクター側外部スクリプト

今回のポイントがここになりますので、まずはサンプルから。

#!/usr/lib64/fluent/ruby/bin/ruby

require 'json'
require 'fileutils'

while line = STDIN.gets
  line.chomp!
  hash = JSON.parse(line)
  # do something...
  ...
end

というだけです。これで、ltsvで送られたデータ、例えば【host:web\tdata:xxxxx】という形のログが送られてきたら、このプログラムでhashにhost->web, data->xxxxxという形で渡されます。
後は各自の自由にどうぞ!

試す

service td-agent start # or "td-agent" command not daemon, for debug stdout.

としてプロセスをたちあげて、ログを送る側で

echo -e "host:aaa\tdata:bbbb" >> /tmp/app.log

としてあげれば自分の書いたスクリプトにデータが渡されますので、後はもうやりたい放題ですね!

パフォーマンス的によろしくないとかそういった話はありますが、パフォーマンス気にする所まで酷使するならもっとしっかり調査するべきですし、逆に今回のやり方だとなんでもやりたい放題だけど、実際にプラグインとか使ったら無理なのかといえばそうじゃないと思います。

プラグインの使い方とか考えてなかなか手が進まない人もいると思いまして、まずはこれで外部スクリプトに渡せるということが試せれば、後は本当にやりたいこと(not fluentdを導入すること自体)に集中できるんじゃないかと思います!