fluentdメモ - (2) 設定ファイル概要

# はじめに
fluentdに関するメモ書きです。ここでは、設定ファイル周りについて記載します。

<環境>
RHEL V7.5
td-agent v3 (fluentd v1)

## 関連記事
[fluentdメモ - (1) インストール/簡易操作](https://qiita.com/tomotagwork/items/5765b8c1300b89590a7e)
[fluentdメモ - (2) 設定ファイル概要](https://qiita.com/tomotagwork/items/ed31db09ea98c09fd6f1)
[fluentdメモ - (3) 設定ファイル調査 Input/Fileter/Output編](https://qiita.com/tomotagwork/items/77ab0a7ca467f63d29ba)
[fluentdメモ - (4) 設定ファイル調査 Buffer編](https://qiita.com/tomotagwork/items/ef51fc60adbb2ca8db92)

# 概要

fluentdは、データの収集/加工に使われるソフトウェアであり、Logstashなどと同じように基本的には Input => Filter => Output という処理が行われます。
Logstashの設定ファイルは、この機能の名前と設定ファイルで指定する名前が一致する(設定ファイルでもInput/Filter/Outputというキーワードを使用する)ので分かりやすいですが、fluentdだとそこのネーミングが違っているので最初とっつきにくく感じます。

設定ファイルの基本的な構造は以下のようになっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/ec6e92c4-2663-a7bf-08f8-a44efff60c0e.png)

- **\<system\>**: ログレベルやスレッド数制御など、fluentd全体の動作に関する設定を行います。
- **\<source\>**: いわゆるInput処理に関する設定を行います。上の例だとTCPのポートを開けてメッセージを受け取り、JSONデータとしてハンドリングします。
- **\<filter\>**: いわゆるFilter処理(各種データの加工など)に関する設定を行います。この例では、field01の値を2倍した結果を保持するfield02というフィールドを追加しています。
- **\<match\>**: いわゆるOutput処理に関する設定を行います。この例では、標準出力に書き出すようにしています。

fluentdに入ってくるデータ(ログの1行相当)は、"タグ"と"タイムスタンプ"の情報が付与された"イベント"という単位で扱われます。
**"イベント" = "タグ"+"タイムスタンプ"+"レコード"**
fluentdではこの"タグ"によりルーティングの制御が行われます。Inputの処理で各イベントにはそれぞれ"タグ"が付けられ、後続のFilterやOutput処理では、各"タグ"に応じた処理を行うことになります。
上の例では、Input処理で各イベントには`tcp.event`というタグが付けられます。後続の`<filter tcp.**>`という箇所は、`tcp.**`というタグが付いたイベントについてはこのフィルターを通しますよ、という定義をしていることになります。同様に、Outputの所でも、`<match tcp.**>`となっているので、`tcp.**`というタグが付いたイベントについてはstdoutに出力しますよ、という定義をしていることになります。

基本はこのようにタグで処理の制御が行われますが、もう一つ"ラベル"という考え方もあり、ラベルを用いた制御も行うことができます。ラベルを使うと複雑な制御を行う際の定義が書きやすかったりするのですが、ここでは詳細は取り上げません。

また、さらにPerserプラグインやFormatterプラグインといった、各種加工をする機能が提供されていますが、それらはInput/Filter/Outputの中に組み込んで使われることになります。上の例では`<perse>`をInputプラグインで使用しています。プラグインの種類によって、どこに組み込んでどう使えるかというのは異なります。
参考: 
[Perser Plugins](https://docs.fluentd.org/parser)
[Formatter Plugins](https://docs.fluentd.org/formatter)

## 設定ファイル分割
ディレクティブが大量にある場合や、共有したい定義などがある場合、`@include`で別ファイルの定義を読み込むことができます。
参考: [(6) Re-use your config: the "@include" directive](https://docs.fluentd.org/configuration/config-file#6-re-use-your-config-the-include-directive)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/546d4549-78a8-3aea-7f8b-89f242ff7b3e.png)

ワイルドカード`*`指定ができるので、複数ファイルをまとめてincludeすることもできます。その場合ファイル名でソートされた順番に取り込まれることになります。
設定の順番に注意する必要がありますので、順序性を担保する必要があるものについては、include文を分けて順序を明確にするのがよいでしょう。

## 複数ディレクティブ指定
Input(`<source>`)/Filter(`<filter>`)/Output(`<match>`) がそれぞれ複数ある場合の挙動がちょっとややこしいです。

Input(`<source>`)については、複数指定すれば、複数の受け口が用意されるだけなので、まぁこれはよいです。

Filter(`<filter>`)については、定義された順にタグにマッチするイベントが処理されることになります。
参考: [Filter Plugins](https://docs.fluentd.org/filter#how-to-use)
>Once the event is processed by the filter, the event proceeds through the configuration top-down. Hence, if there are multiple filters for the same tag, they are applied in descending order. 

1つだけではなく、複数の異なる種類の加工をしたいことはよくあるので、まぁこれもよいでしょう。

Output(`<match>`)だけがちょっと特殊な感じがします。

参考: [Config File Syntax - Note on Match Order](https://docs.fluentd.org/configuration/config-file#note-on-match-order)
こちらに記述されているように、Output(`<match>`)の指定が2つあって、両方にマッチするタグを持つイベントがあったとしても、基本的には最初にヒットした方の定義しか処理されません。例えば、Elasticsearchとstdoutの両方に出力させたいと思った場合、同じタグに対して二つの`<match>`ディレクティブを定義したとしても、最初に定義した方にしか出力されません。
※これがちょっと直感的に分かりにくい所だと思います。
従って、`<filter>`と`<match>`の順番にも十分注意する必要があります。基本、設定ファイルは上から順番に処理されていく感じになりますが、`<match>`ディレクティブに合致するイベントがあって出力されるとそのイベントはそこで消失するイメージになるので、その後に定義された`<filter>`はタグがマッチしても処理されることはありません。
ちなみに、複数の宛先に出力させたい場合は、copyというOutputプラグインを使う必要があります。
参考: [copy](https://docs.fluentd.org/output/copy)

## Outputプラグイン(`<match>`)の位置づけ
Outputプラグインという名前が付いているくらいなので、基本はデータを出力するための定義を行います。例えばElasticsearchにデータを書きこんだり、Stdoutに出力したり。
ただ、そういう出力に関するものだけでなく、rewrite_tag_filterというプラグインがあったりします。
参考: [rewrite_tag_filter](https://docs.fluentd.org/output/rewrite_tag_filter)
これは、タグ情報を書き換えるためのプラグインで、感覚的にはFilter扱いなんじゃないの？という気もするのですが、Outputプラグインの位置づけとなっています。このrewrite_tag_filterというOutputプラグインは、ElasticsearchやStdoutと違って、これを処理した後に新たなEventが生成されることになるらしく、また最初からfluentdによる処理が行われるようです。(役割的にはfilterだけど内部実装の形態としてOutputなのでOutputプラグインの位置づけなんでしょうが、まぁ分かりにくいですね。)
その他、似たようなOutputプラグインとしては、"ラベル"を設定するrelabelというOutputプラグインなどがあります。
参考: [relabel](https://docs.fluentd.org/output/relabel)
基本はアウトプットされたらイベントは基本そこで消失するけど例外的なものもあるよ、という捉え方をしておくとよさそうです。

# 起動時の設定ファイル指定

## td-agentコマンドでの起動

-cオプションで設定ファイルを指定

```
[root@test08 /etc/td-agent]# td-agent -c td-agent-test.conf
...
```

## systemdによる起動

systemdによる操作
起動コマンド: systemctl start td-agent.service
停止コマンド: systemctl stop td-agent.service
確認コマンド: systemctl status td-agent.service

systemdの設定確認

```
[root@test08 /]# systemctl status td-agent
● td-agent.service - td-agent: Fluentd based data collector for Treasure Data
   Loaded: loaded (/usr/lib/systemd/system/td-agent.service; disabled; vendor preset: disabled)
   Active: inactive (dead)
     Docs: https://docs.treasuredata.com/articles/td-agent
```

```xxx:/usr/lib/systemd/system/td-agent.service
[Unit]
Description=td-agent: Fluentd based data collector for Treasure Data
Documentation=https://docs.treasuredata.com/articles/td-agent
After=network-online.target
Wants=network-online.target

[Service]
User=td-agent
Group=td-agent
LimitNOFILE=65536
Environment=LD_PRELOAD=/opt/td-agent/embedded/lib/libjemalloc.so
Environment=GEM_HOME=/opt/td-agent/embedded/lib/ruby/gems/2.4.0/
Environment=GEM_PATH=/opt/td-agent/embedded/lib/ruby/gems/2.4.0/
Environment=FLUENT_CONF=/etc/td-agent/td-agent.conf
Environment=FLUENT_PLUGIN=/etc/td-agent/plugin
Environment=FLUENT_SOCKET=/var/run/td-agent/td-agent.sock
Environment=TD_AGENT_LOG_FILE=/var/log/td-agent/td-agent.log
Environment=TD_AGENT_OPTIONS=
EnvironmentFile=-/etc/sysconfig/td-agent
PIDFile=/var/run/td-agent/td-agent.pid
RuntimeDirectory=td-agent
Type=forking
ExecStart=/opt/td-agent/embedded/bin/fluentd --log $TD_AGENT_LOG_FILE --daemon /var/run/td-agent/td-agent.pid $TD_AGENT_OPTIONS
ExecStop=/bin/kill -TERM ${MAINPID}
ExecReload=/bin/kill -HUP ${MAINPID}
Restart=always
TimeoutStopSec=120

[Install]
WantedBy=multi-user.target
```

systemdによる起動を行う場合、デフォルトでは上の通りFLUENT_CONFに指定されている/etc/td-agent/td-agent.confが使用されます。