すずけんメモ

技術メモです

広告ログ解析基盤にFluentdを使っている話

これはFluentd Advent Calendar 14日目の記事です。

私は現在、VOYAGE GROUPの子会社であるadingoで、DMP cosmiの開発をしています。今日はcosmiでのfluentd利用の話をしようと思います。

DMPについて

過去に勉強会でアドテクまわり及びDMPについて話したのでそれを貼っておきます。ざっというと、いい感じにいろんなログを受けいられるようにして、それらをモニタリングしながら整理して使えるようにする、という役割をもったプロダクトです。

Head First Ad Technology and DMP http://www.slideshare.net/suzuken/head-first-ad-technology-and-dmp

どこで使っているか

ほぼ全てです。構成としては

ログ収集サーバ
      | 
      | out-forward (roundrobin)
      |
中央ストリーム処理サーバ
      |
      | out-plugin (elasticsearch, dynamodb)
      |
   DynamoDB
 ElasticSearch

という形になっています。他にもいくつかapiが用意されており、それらのサーバにも全てfluentd(td-agent)が入っています。どのサーバでもファイルにログを出力したものをin_tailで拾ってきています。既存のログ運用と併用できますし、アプリケーションから直接fluentdプロセスに吐く手段もありますが、fluentdプロセスが落ちていた場合などを考えるとログが落ちなくなってしまうリスクとなりうるためです。とはいえfluentdプロセスが急に息をしなくなった、という場面はいまのところありません。また、カジュアルにfluentdプロセスを再起動したいというのもin_tailにしている理由だったりします。

ログ収集サーバ側ではバッファリングは全てメモリで

ログをいい感じに整理する、という話がありました。ログにも色々なフォーマットがあり、また新しい項目が増えることも多いので、ここはexec_filterを利用して外部プログラムで処理するようにしています。exec_filterを個人的にはとても気に入っていて、それは外部プログラム自体はfluentd以外のところでも利用できるという点にあります。このプログラムは単純に「ログをいい感じのフォーマットに前処理する」ということをやっていて、これはHiveのmapフェーズやHadoop Streamingでも再利用可能な設計になっています。省エネですね。

またログ収集サーバでのバッファリングはメモリで行っています。これはIO waitを避けるという意味もありますが、単純に元のログファイル自体がファイルシステム上にあるため、resume処理をやれば良い、という形になります。なお、この処理系においては、同じログを再送しても問題ない作りになっているので、カジュアルに再送できます。中央ストリーム処理サーバにラウンドロビンで転送しているのも、このへんの背景があるからだったりします。中央ストリーム処理サーバ自体は2台配置していて、流量としてはどちらか片方が落ちても許容できる程度のサーバが配置されています。

中央ストリームから各種データストアへの書き出し

ここはout pluginのelasticsearchとdynamodbを利用しています。elasticsearchはまだ評価中ですが、実データを突っ込んでどう使うかを設計しているというところです。ログに対しては割りと全文検索という手段は使い勝手が良いです。ただどの程度までデータを保持しておくかというあたりや、どの程度事前にメトリクスを作っておくかというところを検証しているようなフェーズです。fluentd側からはout_copyで単純にstreamを分けてあげて、それをelasticsearchに送り込んでいます。

DynamoDBへの書き込みは外部プログラムでやっていたのですが、最近DynamoDBプラグインでやるように変更しました。hash + rangeを扱いやすくするようなパッチを充てています。*1

検証用データの作り方

Fluentd運用で大事になるのが、検証プロセスです。たとえばexec_filter用に新しいプログラムを充てたいときや、新しいプラグインを試す時です。そういう場合には本番環境のログ収集サーバの一部から検証用環境にout_copyで送るようにしています。ここではsamplingするようになっていて、大体1/10程度のログを検証用に利用するようにしています。もちろん本番環境には通常通り全てのログが流れたままになっています。なぜ本番のログを検証用にも利用するかというと、生ログというのは生き物ですので、実データで試さないと性能の傾向などの見積りがしづらいためです。それまでは本番にとりあえず投入して、しばらく放置してから異変に気がつくというようなことをしていたりしましたが、この方法を撮るようにしてから大分捗るようになりました。out_copy素晴らしいですね。

ちなみにこのへんの検証用データの作り方については、AWS re:Invent 2013でLogglyがやっていた方法に似ています。*2 LogglyではKafka + Storm環境で同じようなパターンを作っているようです。

Fluentdを使う上で無くては生きられないもの、それはGrowthForecast

ほんとGrowthForecast無しでは、というくらい重宝してます。基本的にほぼ全てのmatch句においてcopyプラグインを利用しており、それぞれのストリームをflow-counterで収集しています。そしてそれらをGrowthForecastに送信するようにしています。すると各処理レイヤーでの変化が手に取るようにわかります。例えば、以下のような際には基本的にGrowthForecastを見るようにしています。

  • exec_filterでかませたプログラムを変更した場合
  • buffer_chunk_limit, buffer_queue_limit, flush_intervalなどの設定値を変更した場合
  • 新しいプラグインを導入した場合

前に気が付いたのは、out_copyを利用している場合に、前段のstoreで処理が死ぬと次のstoreに流れなくなる、というようなケースです。後々にdeep_copyを知ったのですが、変更した後にどういうことが起こっているかを把握するというのはやはり大事です。まだFluentdの挙動が完全に把握できているわけではないので、どういう振る舞いになっているかを把握しやすくするというのは運用上大切だと思っています。

なお、in_tailでFluentdにinputするのが面倒な場合には、古きよきcrontabにより簡単な集計をした上でGrowthForecastに送信している部分もあります。

細かいTipsとか微妙に考えるのを放置している部分とか使ってから気が付いた想定していなかったこととか今後やりたいこととか

  • もともと出力していたログはcronologでローテートされていた。ので、in_tailでログを食わせる際には-Hでハードリンクにするようにしている
  • flushの間隔を短くすればするほど最終的な書き込みまでの遅延がなくなるわけだけど、そのあたりの実験
  • s3への転送は歴史的事情によりcrontabでやってるんだけど、生ログを圧縮してs3に置くだけならtd-agent-liteを利用したほうがいいのかもしれない。
    • EC2インスタンスが死んだ時にcrontabだとログ失う可能性があるので、なるべくリアルタイムにs3に送っておきたい。でぃすぽーざぼーにしたい。
  • 結局プラグインを使う場合にはいろいろ挙動を見る前にコード読んだほうが分かりやすかったりする
    • ので最近は結局ドキュメントを読まずにコードを読む
  • data-counter + sampling-filter + GrowthForecastでいい感じにメトリクスつくろうと思ってたんけど、全部やろうとすると設定ファイルが盛々になるし管理しにくくなる
    • ので今はelasitcsearch + Kibana3でそのへんのメトリクスはつくればいいかなと思ってる
    • つまるところ、メトリクスを作るのはコストがかかるので、どこまで何を見たいかによるよねという話
    • 裏側はEMRがあるので、パッと時系列でモニタリングしたいのはGrowthForecastとKibana3でやって、それ以外のは基本的にEMRという戦術をとってはいる
  • Amazon Kinesisが出たらそこに流せるようにはしようと思っている

まとめ

まとめると、Fluentdつかってカジュアルにストリーム処理の色んな手段を試しています。あんまり奇をてらったことはしていないつもりです。@katzchang さんも書いていたように、Fluentdは保守的な構成をとることもしやすく、現にまだcrontabで動作している部分が残っていたりしますし、Fluentdでの処理が失敗しても運用上どうにかなるような仕組みになっています。もともとFluentdを使おうとは思っていたのですが、実は最初に身近で使い始めたのは @bash0C7 さんだったりして、なんだかんだそれから社内でも少しずつ使うところが増えていきました。ということで日々楽しくFluentdを利用しております。Fluentdやtd-agentのメンテナの方々やプラグインを公開してくださっている皆様のお陰です。感謝。

以上、Fluentd Advent Calendar 14日目でした。明日は @katsyoshi さんです。

*1:大分安定してきたのでPR予定です。それと、updateItemについても扱えるようにしようと考えています。

*2:参考: re:InventでのLogglyの分散ストリーム処理環境に関するセッションが面白かったのでまとめておく http://suzuken.hatenablog.jp/entry/2013/11/17/224830