Site Reliability Engineering Teamの@cubicdaiyaです。
今回はGo製のログ転送エージェントであるfluent-agent-hydraとメルカリでの利用事例について紹介します。
メルカリとFluentd
メルカリではAPIサーバのアクセスログやアプリケーション固有のログをはじめとする各サーバに散らばっているログデータを転送・集約するのにFluentdを活用しています。
具体的にはローカルに書き込まれるログファイルのin_tailやそれらを転送するための(out|in)_forward、ElasticsearchやBigQueryにログを放り込むためのプラグインを利用しているほか、いくつか特殊な用途のプラグインを独自に開発して運用してたりもします。
ログの流量とFluentdのパフォーマンス
多機能で柔軟なプラグイン機構を持つ便利なFluentdですが、ログの流量が大きくなってくるとパフォーマンスの面で辛くなることがたまにあります。そういった場合はフィルター等の重い処理の利用を見直したり、multiprocessプラグインでFluentdが複数のCPUコアを利用できるようにして性能を稼ぐといった対応が考えられます。中でもmultiprocessプラグインは1プロセスで複数のCPUコアを活用できないFluentdにとって非常に大きな性能向上をもたらしてくれます。以下は複数のFluentdプロセスをmultiprocessプラグインでforwarderとして稼働させている様子です。
ただ、multiprocessプラグインは効果が高い一方で若干運用しづらい面があります。例えば、
- プロセスが多くなる(監視対象が増える)
- listenするポートが増える(e.g. in_forwardを利用する場合)
といったことが挙げられます。また、ログのフォーマットにもよりますがin_tailとout_forwardでそれなりに書き込み量の多いログを複数個転送するようなケースだとFluentdプロセスのCPU使用率が高くなりがちです。実際、メルカリでは一部のサーバでFluentdのCPU使用率が無視できないくらい高くなるケース(in_tail & out_forwardの1プロセスで50〜60% at peak)が出てきました。
こういった事情から現在はFluentdとより低リソースで稼働するfluent-agent-hydraを併用しています。
fluent-agent-hydra
fluent-agent-hydraはFluentdやそのための各種ロガーとやりとりができるログ転送エージェントです。以下の機能や特徴を備えています。
- in_tail, (in|out)_forwardができる
- HTTPベースのモニタリングAPIが利用可能
- 1プロセスで複数のログをハンドリングできる
- ラウンドロビン転送をサポート
- ログフォーマットとしてLTSV、JSONをサポート
- Fluentdよりも高速・低リソースで動作する
- TOMLによるコンフィギュレーション
ただし、今のところFluentdのpos_fileやファイルバッファに相当する機能がないのでその点には注意が必要です。
分析基盤のログ転送エージェントとして導入
以前本ブログでも紹介したメルカリのログ分析基盤Pascalですが、当時は以下のような構成になっていました。
以前の構成
OpenRestyが出力する複数のログファイル(JSON)をFluentdがin_tail & out_forwardで転送するという構成です。現在はこの部分がfluent-agent-hydraに置き換わっています。また、この図には描かれていませんが、Pascalにはアプリからだけでなく、内部のAPIサーバからもFluentd経由でリクエストが飛んでくるようになっています。
現在の構成
実際に導入するにあたって少し機能を拡張する必要がありましたが、結果的にログ転送プロセスのCPU使用率は約半分になりました。
fluent-agent-hydraのアーキテクチャ
fluent-agent-hydraはin_tailやout_forward、monitor等の機能を担う各ゴルーチンが協調動作するアーキテクチャになっています。最初に起動したゴルーチンは各機能のためのゴルーチンを起動した後シグナルを待ち受ける状態になります。
各ゴルーチンはチャネルを利用してデータのやり取りをします。矢印はデータの流れる向きを表していて、monitorのゴルーチンはfluent-agent-hydraの各種統計や監視に必要な情報を各ゴルーチンから受信し、out_forwardのゴルーチンはin_tailやin_forwardのゴルーチンからメッセージを受信する仕組みです。
TOMLによるコンフィギュレーション
fluent-agent-hydraでは動作設定をTOMLで記述することができます(設定なしでも起動できます)。以下はその例です。
ReadBufferSize = 1048576 # 1MB ServerRoundRobin = true # 追尾するログ [[Logs]] File = "/var/log/nginx/access.log" Tag = "nginx.access.log" Format = "LTSV" # or JSON # 転送先ホスト [[Servers]] Host = "forward-server1" Port = 24224 # 転送先ホスト [[Servers]] Host = "forward-server2" Port = 24224 # モニタリングAPIのエンドポイント [Monitor] Host = "localhost" Port = 24200
設定ファイルを指定して起動するには-c
オプションを利用します。
$ fluent-agent-hydra -c /etc/hydra/hydra.toml
より詳細な設定例については公式のREADME.mdを参照するとよいでしょう。
fluent-agent-hydraのモニタリング
fluent-agent-hydraはモニタリング用のAPIを備えており、/system
ロケーションにアクセスするとGo内部(GCやメモリアロケーション、起動しているゴルーチンの数)に関する稼働状況が確認できます。
$ curl -s http://localhost:24200/system | jq ʻ.ʼ { "gc_pause": [ 0.412521 ], "gc_pause_per_second": 0.412521, "gc_per_second": 0.12935386000134802, "gc_num": 5435, "gc_last": 1449825990702757400, "gc_next": 99945471, ...
また、それ以外のロケーションにアクセスするとfluent-agent-hydraの稼働状況(追尾しているファイルのポジション、転送したメッセージの数やバイト数等)を確認できます。
$ curl -s http://localhost:24200/ | jq ʻ.ʼ { "receiver": null, "servers": [ { "error": "", "alive": true, "address": "forward-server1:24224" }, { "error": "", "alive": true, "address": “forward-server2:24224" } ], "files": { “/var/log/nginx/access.log“: { "error": "", "position": 472132311, "tag": “nginx.access_log” }, … …
メルカリではこれらの情報を元にZabbixでfluent-agent-hydraの稼働状況を確認しています。例えば追尾しているファイルのポジションが正常に更新されているかどうかは以下のようなファイルを用意してトリガーを設定することで確認することができます。
UserParameter=hydra[*], curl -s http://127.0.0.1:24200/ | jq '.files["$1"].position'
ポジションが一定時間更新されてないのを検知するとこんな感じでSlackに通知されます。
まとめ
Go製のログ転送エージェントであるfluent-agent-hydraとメルカリでの利用事例について紹介しました。今回の解説は先日開催されたGo Conference 2015 Winterの資料を元にしています。興味がある方はそちらも御覧ください。