Fluentdの所感 その2

YARNについて書きたい気持ちを抑えて前回の続きです。

まだfluentdをがっつり導入しているわけじゃなく、独自プラグインや構成については改良の余地があるかもなので、まぁ参考程度に見ておいてください。



データフロー

APサーバのログ書き込みから、HDFSに書き込むまでの処理内容です。パスとかは適当に書き換えてます。なぜこんなフローなのかは後述。めんどいのでテキストで。

改造プラグインは後述なのでそれ以外を何点か。

APのログ

日時パスとかにせず固定パスにしているのは、シンプルかつlogrotateで簡単に移動&圧縮できるからです。さらに最後にHDFSに書き込むpathを可変にするためにpathのbasenameをtagにしています。そうしなければ、AgentごとにFluentd設定を変える必要がでるからです。前回書いた通り、様々な環境への導入を踏まえて、導入も運用もシンプルになるように心がけています。

負荷とflush_intarvalの関係

Agent -> Collector は flush_interval 10 でforward処理が少し重めなので、10秒毎にCollectorに負荷がかかります。なので1秒毎にして均一化すべきとも考えましたが、Agentは大量にいるので結果的に均一になるだろうと考え、送受信効率とのバランスをとって10秒にしてみました。
ちなみに、Agentは常にtailしているので常に負荷は均一です。

Collector -> HDFS も flush_interval 10 にしてあります。出来上がりファイルが1分単位なのに、1分毎にflushしたんじゃ少し遅いし、あまり小刻みでもAPPENDが不安なので10秒です。10秒といっても、Collectorが5台だとしたら平均2秒毎にAPPENDされることになりますが、今のところ大丈夫だと思っています。

改造プラグイン

プラグインの案と検証は俺ですが、コーディング自体は今回は相棒にやってもらいました(なんて楽なんでしょう!)。数回のダメ出しを経てとても良い仕上がりにしてくれました。プラグインを今後どう扱うかは考え中です。

改造tail

基本のtailに以下の機能を加えてあります。
  • pathに * (ワイルドカード)を使用可能
  • tag に %{basename} を使用可能 (ex: log.%{basename} )
  • pos_fileによる再開や、ログ削除後の再読み込み対応もそのまま

  • 改造forward

    (OUT)
  • compress_level によりgzip圧縮可能 (1~9は圧縮, 0は非圧縮)
  • password *** を設定すると暗号化 (暗号化方式は別の話なのでとりあえず秘密)
  • ハッシュ化してServerに送信
  • (IN)
  • ハッシュ解読して以降の処理へ
  • 暗号化されていたらpassword *** で復号化
  • 圧縮されていたら解凍

  • 改造webhdfs

  • pathに %{tag} を使用可能
  • APPEND効率の正常化 (上記機能による悪化を防いだ)

  • Fluentdの負荷試験

    CPUは Xeon L5520でやりました。
    OSはそれなりのサーバに20インスタンス以上ぶっこんだ仮想環境で、fluentdはAgentもCollectorも2vCPUにしてあります。なのでfluentdは問題ないですがHDFSは性能はいまいちな状態です。

    数値は、特にどこにもログ送受信に遅延が発生していない状態で、
    CPU100%換算処理行数/秒 です。

    CPU100%換算:ベンチマーク時に100%にしてしまうと待ちが発生して実際の性能がわからなくなるため、50~80%程度になるように負荷をかけて、それを100%に換算しています。…換算はしますが、実運用では半分近くなったら増設を考えますよ、と


    公開プラグインのみの場合

    (IN tail -> OUT roundrobin forward => IN forward -> OUT webhdfs)

    むぅ、速い。

    独自プラグイン3つ+flowcounter

    圧縮/暗号化している割に性能劣化は低く、20%減で済んでいるのが不思議です。不思議すぎて相棒にイチャモンつけて中身をわざわざ確認しましたが、ちゃんと圧縮/暗号化されてました・・・。今のrubyってこんなに性能いいの・・・。

    これは 1Agent, 1Collector, HDFS での性能です。
    他に 1Agent : 複数Collector や 複数Agent : 1 Collector 、複数 : 複数 も試しましたが、オーバーヘッド的なものは認められず、綺麗にスケールアウトしました。問題になるとしたら、大量Collector -> HDFS の部分だけですね。

    圧縮/可逆暗号化について

    なぜAgent -> Collector間にこのような処理を入れているかですが、CollectorがWANで受け取るからです。つまり、複数のIDCから受け取るということです。この時にいくつか選択肢があるので考えたのを書いてみます。

    圧縮だけする

    複数IDCの場合、GlobalIPアドレスで受け取るのが最も簡単です。トラフィック軽減で圧縮だけして、あとは平文でえぇやん、経路上の誰が盗むというのだ!言ってみろ!!

    VPNを使う

    暗号化できてPrivateLANで解決できる優れもの!まではいいのですが、IDC毎にVPNをはる必要があり、社内管理サーバだけならまだしもサーバ管理者が社外の場合があると、途端に色々めんどくさくなります。さらに、VPNは冗長化や負荷分散の点で弱く、途中に余計な経路も増えるので効率が下がります。

    SSH使えるぜ

    設定、トンネル、運用、いいとこないです。

    可逆暗号化しようか

    プラグイン作成の手間と若干の負荷が許容できれば、なかなか良い落とし所ではないでしょうか。

    monitによる監視

    モニタリングとかアラート系は別途やってるので、さらに1つ付け加える形です。
    実はAgent落ちてるんじゃないか、とかそもそもAPからログきてないんじゃないかとか。色々あると思いますが、今はやりすぎず少なすぎずに留めています。デーモン操作とかも必要なので monit を使っています。

    Agent

  • fluentdプロセスが無いと立ち上げる+アラート
  • flowcounter+スクリプトによるアラート(※後述)

  • Collector

  • LISTENしていないと立ち上げる+アラート
  • flowcounter 同上

  • flowcounter+スクリプトによるアラート

    まだ本番にぶっこんでないので調整しますが、こんな感じで考えています。
  • flowcounterで1時間あたりのログ行数を記録
  • そのログをスクリプトでチェックし、X時間内の最小値と最大値の差が10倍あったらアラート
  • ゼロ行もアラートとする

  • 行チェックはアラートだけに留めていますが、色々確信してきたらmonitに何か実行させるかもしれません。



    内容がもはや所感じゃなくなってますが、今の私の気持ちはこんな感じです。

    業務としてやってることを書く時にどこまで書くかが難しいところですが、
    このくらいなら大丈夫でしょう。多分。