職場でよく耳にするfluentdを試してみました

私なりにfluentdの情報を集め、実装してみました。

# fluentdとは

+ データのやりとりを管理するソフトウェア
+ データ、主にログをparse(分解)し転送先に格納出来る
+ 既存のプラグインが多く、出力先も多様である(ローカル、S3、MongoDB、Cassandraなど)
+ buffer機能により、長時間転送に失敗してもリトライが出来る

# 導入してみました

## インストール

■前提

+ ruby環境が必要
+ 実装先はEC2(CentOS6.5)
　
■はじめに
TreasureDataというデータウェアハウスより、td-agentというruby環境込みのパッケージ(td-agent)を取得する
　
■yum でインストールする
▽リポジトリを登録

```bash
 # vi /etc/yum.repos.d/td.repo
----------
[treasuredata]
name=TreasureData
baseurl=http://packages.treasure-data.com/redhat/$basearch
gpgcheck=0
----------
```

▽インストール

```bash
# yum install td-agent
```
　
■セキュリティグループでポート開放
転送先がEC2サーバである場合、fluentdのポートを開放する必要がある。
fluentdはデフォルトで24224番ポートを利用するため、以下のように開放する。

+ データ転送 TCP 24224番
+ 死活監視   UDP 24224番 


## 設定(td-agent.conf)の定義

■デフォルト設定ファイル
/etc/td-agent/td-agent.conf
　
■構文(主観)
・source定義で指定した入力
・マッチしたmatch定義の設定で出力

```bash
(a) インプットプラグインの設定
<source>
    type   インプットプラグインの種類の指定（tail、execなど）
    その他パラメーター（利用するインプットプラグインに応じて必要なパラメーターを追加指定）
</source>

(b) アウトプットプラグインの設定
<match タグパターン>
    type   アウトプットプラグインの種類の指定（file、stdoutなど）
    その他パラメーター（利用するアウトプットプラグインに応じて必要なパラメーターを追加指定）
</match>
```

※もっと詳細な設定が出来ると思います。今回は最小構成を提示しました。
　

```
▽タグのマッチングルール
　{} … <match A.{B,C}.D> の場合、「A.B.D」 もしくは、 「A.C.D」がマッチング
　　中括弧内に,(カンマ)区切りで要素を指定。その要素いずれかを含むものが対象となる。

　*  … <match A.*.C> の場合、「A.Z.C」や「A.9.C」などがマッチング
　　任意の1文字列が対象となる。

　** … <match A.**.C> の場合、「A.B.D.E.F.G.H.C」などにマッチング。
　　<match **> の場合、全てのタグにマッチング。
　　(注意、こちらを定義するとそれ以降の設定が評価されなくなるということ。*の箇所はなんにでもマッチング）
```
　

## 転送先の設定

+ 転送先がS3の場合は、バケットを用意するだけ
+ ElasticSearchならば、起動しておくだけ
+ 別サーバへ転送する場合、fluentd(td-agent)を起動しておく

簡単に言うとそれだけになります。

**導入は取り敢えず以上です**
　

## 補足(fluentプラグイン)を導入
　

■dstatログ用

```bash
# /usr/lib64/fluent/ruby/bin/fluent-gem install fluent-plugin-dstat
```
　

■elasticsearch

```bash
# /usr/lib64/fluent/ruby/bin/fluent-gem install fluent-plugin-elasticsearch

→以下エラーが出た場合
extconf.rb:39:in `<main>':   Can't find libcurl or curl/curl.h (RuntimeError)

以下をインストールしてから、リトライ。
# yum install curl-devel
```
　

■ELBアクセスログ用

```bash
# /usr/lib64/fluent/ruby/bin/fluent-gem install fluent-plugin-elb-log

→以下エラーとなった場合
ERROR:  Could not find a valid gem 'fluent-plugin-elb-log*' (>= 0) in any repository
ERROR:  Possible alternatives: fluent-plugin-elb-log, fluent-plugin-rds-log, fluent-plugin-backlog, fluent-plugin-sumologic, fluent-plugin-netflow

以下のコマンドでリトライ
# /usr/lib64/fluent/ruby/bin/fluent-gem install fluent-plugin-elb-log --no-ri --no-rdoc -V

▽参考:
ELBのアクセスログをfluent-plugin-elb-logを使ってkibanaで表示する
http://dev.classmethod.jp/cloud/aws/fluent-plugin-elb-log-to-kibana/
```
　

■ 出力するJSONを加工するのに利用

```bash
# /usr/lib64/fluent/ruby/bin/fluent-gem install fluent-plugin-map
```
　

■mongoDB

```bash
# /usr/lib64/fluent/ruby/bin/fluent-gem install fluent-plugin-mongo
```

　
# Tips

## td-agent起動時の障害対処
■前提:
・まずはログを見よう

```bash
# view /var/log/td-agent/td-agent.log
```
　
■事例①
「td-agentが起動しない」

・一見、起動しているように見えるが、失敗している場合

```bash
# service td-agent start
Starting td-agent:                                         [  OK  ]

# service td-agent status
td-agent が停止していますが PID ファイルが残っています
```

・ログを確認

```bash
# view /var/log/td-agent/td-agent.log
----------
2014-08-14 18:00:16 +0900 [error]: unexpected error error_class=Errno::EACCES error=#<Errno::EACCES: Permission denied - /var/log/fluent>
  2014-08-14 18:00:16 +0900 [error]: /usr/lib64/fluent/ruby/lib/ruby/1.9.1/fileutils.rb:247:in `mkdir'
  (以下略)
```

出力先のディレクトリが無い。
rubyがディレクトリを作成しようとするも、権限がなく作成出来ない。

　
■事例②
「ログを実行する権限がなくエラーとなる」

・以下のようにエラーが出力

```bash
# view /var/log/td-agent/td-agent.log
2014-08-14 19:06:00 +0900 [error]: Permission denied - /var/log/httpd/access_log
```

・/var/log/httpdのパーミッションが700で root:rootという所有権なのでtd-agentだと読み込めない


■解決策
・実行ユーザをrootに変更する

```bash
# vi /etc/init.d/td-agent
-------------------------
DAEMON_ARGS=${DAEMON_ARGS---user td-agent}
TD_AGENT_ARGS="${TD_AGENT_ARGS-/usr/sbin/td-agent --group td-agent --log /var/log/td-agent/td-agent.log}"
↓
DAEMON_ARGS=${DAEMON_ARGS---user root}
TD_AGENT_ARGS="${TD_AGENT_ARGS-/usr/sbin/td-agent --user root --group td-agent --log /var/log/td-agent/td-agent.log}"
```
　
　
以上になります。