by shigemk2

当面は技術的なことしか書かない

memo Keynote: Past & Future of Fluentd #fluentdmeetup

オープニング meetupの概要

  • v0.14.0 リリース
  • 概要
  • windows関係で何が起こるか
  • APIの変更

本編

  • Fluentdの昔と未来 2011/06/20に0.9.0リリース 5年
  • 5年プロダクトが続いているなら成功している部類
  • フルタイムコミッターが2名入ったことでアクティブにつづいている
  • 最近さらにアクティブになっている
  • 堅牢なOSSのコミュニティ まだまだ成長している

  • v0.14.0

    • 昨日 05/31
    • インストールしたらなんがしかのプラグインでバグがあるので、試してみて、Issueを登録してくれ

v0.12.0まで

以下の機能はリリース時にはなかった機能

  • label
    • @ERROR
    • 設定ファイルを構造化できるので使わない手はない
    • タグの書き換えをしなくてよい
  • filter
    • タグの書き換えをしなくてよい
  • forward
    • at-most-once at-least-once エラーが起きるとログが紛失する可能性があり、バッファを消さないようにする
  • heartbeatをtcp/DNSラウンドロビン
    • 分散環境構成(ココ2年)
  • configのフォーマット
  • log_level
  • fluentd-ui
  • buffer_queue
    • 例外を上げるかわりに一番古いチャンクを捨てるなどする

未来をどうするか

  • バックプレッシャー
    • バッファがつまったときに 賢く 転送する
    • in_tailで大量にやるときに転送量がつまる
  • PubSub/pull forward→Kafkaと似たようなもの
    • pushではなくpullすることで賢く
  • bufferの圧縮
  • bufferの分散とレプリケーション
    • ログの構造をレプリケーションするのはapacheとかではすでにやっている
  • service plugins
    • fluentdの上にのせるサービスはハックするしかない
    • source-match→serviceを使うことで、パッケージングしたサービスをFluentdのうえで走らせる
    • 例: ES/KibanaをFluentdのうえで走らせる
  • Schema-validate logging
    • 書き込み先のストレージに変なデータが入ると困る
    • validateされたログだけを転送したい
    • 変なデータを送信してエラーだとか帯域を圧迫するとかっていうのをやめて、余計なデータを送らないようにする
    • 認証とかも絡むかも
  • configを中央で管理する
    • ansibleとかshellとか使うのが今まで
    • Dockerを使ってデプロイする
    • fluentdの設定を、どこかのサーバで管理する
    • git pushするとconfigをばらまくとか
  • ロゴ
    • デザイナから「見にくい」っていうご指摘

memo: v0.14 Overview #fluentdmeetup

@repeatedly

v0.14.0 2016/05/31

  • API刷新
  • 時間のナノ秒対応
  • Windows

API

  • Input/Output pluginのAPI
    • 終了時にうまくシャットダウン出来ない
    • バッファ
  • APIの追加/削除
  • bufferAPIについて刷新を行ったのでそのあたりは互換性がない
  • v0.12 pluginのAPIはほぼ互換性がある
    • かなり無理なハックをやっている場合はこの限りではない

v0.12 buffer design

  • bufferのchunkは1つのキーに対して保存していた
    • 値がなかったらキーだけ
  • ESまわりで問題点
    • 一つのチャンクに全部のレコードを突っ込み、そのあと解体する
      • 1つのチャンクのなかに10レコード入っていたら、途中でエラーが走ったら全部失敗する
      • リトライすると重複が起こる

v0.14 buffer design

  • chunkを持つときにメタデータを利用し、データの保存を柔軟化
    • メタデータごとにチャンクを保存する
    • レコードとチャンクが完全分離したのでリトライしても重複が起きない

Plugin Storage

  • Plugin開発者向け
  • 状態を持ったままリスタートできる(KVS)
  • 個別に実装されていたのをFluentdに取り込んだ

  • input/parser/filter/buffer/output/formatter

  • input/parser/filter/buffer/output/formatter + helper/storage

ナノ秒対応

  • 時間の最小は秒単位
    • コンマ秒レベルでも全て同じ秒として視認
    • ESとかかなりしんどい
    • Fluentdで対応
  • ミリ秒ナノ秒で揉めたけどGoogleとかはナノ秒に対応しているのでこちらもナノ秒で
  • Integerっぽく振る舞う(多少プラグインの書き換えが必要になるかも)
  • 既存のエコシステムが壊れることはないけどバグがあったらIssueを投げて

ServerEngine based Superviser

  • 独自のモデルを使っていたのを、サーバエンジンをリプレイス
  • 社内で開発したRubyのworkerとかのノウハウを利用
  • より安定に

Windows Support

  • Linuxで特化した実装をクロスプラットフォームで
  • シグナルでBuffer FlushしていたけどWindowsは使えないので、HTTP RPCを利用

v0.14.x→v1

今後やりたいこと(v1)

  • fluentd issue 1000を見よ
  • version1を出すけど破壊的な新機能やAPIを壊すことはない
    • でもリリースした後に「そんなの聞いてないよ」って言われても困るので今のうちにフィードバックを出すこと
  • detatch_process関係は消したい(要望はあるけどKinesisとかで使っているユーザーがいるので良い方法が見つかれば)

  • マルチコアサポート

    • FluentdのうえでさらにFluentdを動かす→ マルチコア化
    • 立てた分だけポートを分ける必要があって、運用負荷が爆上がりする
    • supervisorを利用して、TCPを使ってworkerでシェアできる技術→パフォーマンス向上
    • バッファごとのメトリクス問題の解決→counter API
      • 統計的な値も取れる

TLS/Authn/Authz

  • セキュアフォワードとフォワードの使い分け

ベンチマーク

  • CPUの使用率が0.12より若干上がっている……(秒間10万行)
    • in_tail/out_forward 66%→70%
      • Busyなサーバでバージョンを上げると死ぬ
    • in_forward/flowcounter_simple 変わらず11%
    • in_forward/tdlog 38%→43%
  • でもまだまだオプティマイズする箇所があるから乞うご期待

Treasure Agent 3.0

  • td-agent2系ではfluentd v0.14は入らない
  • Ruby 2.3
  • CentOS 5とかUbuntu 10.04とかはサポートから外すので自前でビルドして。
  • リリース日は未定

memo: Fluentd ServerEngine Integration & Windows Support #fluentdmeetup

@naritta

ServerEngine is integrated

  • ServerEngine supervisor→server→worker
    • heartbeat via pipe
    • auto-restart
    • unicornと使い方は似ている
  • worker type thread/process/spawn
  • v0.14からspawnのworker typeを利用
  • Windowsにはforkの機能はないので、個別のプロセスを利用する

ServerEngineのメリット

AutoRestart

  • supervisorからworkerを死活監視→自動再起動
    • pstreeで確認できるよ
    • windowsでも同様に動くよ

LiveRestart

  • serverからworkerを自動再起動できる
  • workerをキル→再起動→読みなおし→別のworkerにシェア
  • send SIGHUP
  • RPC Serverとシグナル
  • api/config.reload
  • supervisor/server/worker
    • send USR2
    • 再起動無しで設定ファイルをリロードできる

Socket Manager

  • Socket Managerのほうにリクエストを飛ばす
  • 開いている場合は開く、ない場合は作る
    • UDS(unix)/TCP(Win)
  • get socket and accept in worker
  • server engine側のAPIを利用して、ServerEngine::SocketManagerと記述すると使える
  • server workerのすてきな関係

  • 最大のメリットは将来的にはマルチコアでソケットを使えること

  • マルチプロセスプラグインだとsourceが増えて面倒なのが、socketmanagerをつかうと1つのsourceになって実装がかなり楽になる
    • 将来的にはマルチコアを自由に設定出来るようにする
    • serverとworkerのプロセス関係はWindowsでも使える

Signal Handler

  • キューベースのシグナルハンドリング
    • シグナル同士の競合を防ぐ

Log Rotation

  • もともとServerEngineで実装されていたもの
  • ログローテーションをより簡単に
  • 細かいログレベルのトレースが出来る

まとめ

  • Live Restart/Auto Restart
  • Socket Manager
  • Signal Handler
  • Log Rotation

Windows(Unixで出来ることがWindowsでは出来ないため)

  • signal → rpc handler
  • no socket FD and UDS
  • fork based → spawn based

memo Fluentd v0.14 Plugin API Updates #fluentdmeetup

とぴっく

  • なぜAPIを変える必要があったのか
  • 新しいAPIで何が出来るか
  • その後のはなし

たごもりす

新しいプラグインAPI

  • 今までのAPIでは問題があった
  • プラグインAPI関係について体系的なドキュメントがなかった
    • 誰かが書き散らしたブログが参考記事
  • テストコード書きづらい
    • sleep 5みたいなバッドノウハウが蓄積
  • output_plugin
    • 4種類あって分かれていた
    • 考えて作らないといけない
    • 説明がわかりづらい
    • 違いを意識させないようにしたい
  • 設定ファイルを見た時に設定項目の変数が他でも使いまわせるのか分からない→とても不便
  • start/shutdown→なんとなく書かれていたコードが真似されまくってsuperじゃない
  • バッファリングが不便なやり方でしか出来ない
  • バッファはバイト数単位でしか出来ない
    • 100行までならいけるけど101行までならコケるとか
  • Rubyなんで、便利なことをやろうとすると難しい
    • Rubyで出来ることはなんでもやっていいんだ!みたいなサバンナをどうにかしたい
  • コアの設定をプラグインで簡単に上書きしてしまうので面倒
  • FluentdのRubyのコードはダメな例のオンパレードで、Rubyに詳しくない人よりインフラの人が使い始めたので、Rubyのひよコードがどんどん伝搬されていった
  • 自由なRubyのコードが跳梁跋扈していた

便利なようにしていきたい

互換性

  • 説明を、簡単に
  • 0.12 Fluent::Input Fluent::Filter Fluent::Output
  • 0.14 Compatibility layerを利用 Fluent::Compat::Klass -> Fluent::Klass(こういう代入に代表される変換)
    • 0.12→0.14で消失したメソッドとか変数とかを動的に生み出している ので、基本的には動くはず 一部のものは動かない
      • buffer pluginとか。
      • 使っている人が全世界で4人しかいないはずなので
    • 無茶なことをするためにテストコードでごまかしていたプラグインはオミットしてる
    • Engine.emit input_pluginで使われているが、無効、例外へ
      • labelでのルーティングが動かなくなるため(Router.emit)
    • version 0.12
  • 今まで使っていた設定ファイルはどうなるのか
    • ほぼ同じになるようにバージョンアップ
    • ユーザー自身に書き換えてもらうのが理想だけど、プラグインAPI側で自動変更するようにしばらくはAPI側で用意する
  • 0.12 0.14どっちでもいけるpluginは作れないようにした

新しい話

  • 全てのファイルはfleuent/plugin/*.rbで
  • 全てのクラスはFluent::Pluginの下で(いままでは直下でした)
  • サブクラスはFLuent::Plugin::Base
  • いくつかのメソッドについてはsuperを呼び出すように(#configure #start #shutdown)
    • これらのメソッドを呼ぶときにsuperを呼ばないとおかしなことになる(superを強制的に呼ぶ)

構造

  • v0.12
    • Fluent::Input
    • F::Filter
    • F::Output
    • 全部並列
  • v0.14
    • Fluent::Plugin::Baseのうえに、F::P::Inputとか

Fluentd::Plugin::Input

  • ほぼ変わらない
    • overall以外
  • Fluentd的には書きやすくなってる
  • 便利なブロックを組み合わせやすい

Fluentd::Plugin::Filter

  • ここもほぼかわらない
    • filterをかけてrecordかnilをかえす

Fluentd::Plugin::Output

  • けっこういろいろな変更がある
  • 4つのOutputプラグインを統合
    • bufferingの有無に関係なくoutput pluginを使える
  • バッファリングの変更を楽にできる
    • ファイルに書き出す
    • タグごとに分ける
    • などが出来る
    • レコード数指定が出来るようになる(new)
    • timekeyの時間指定が細かくなった(new)
    • レコードに入っているフィールドをチャンク分けできる(new)
    • これらの全部盛り(new)
  • no more forest plugin
  • 今まで4つのプラグインを使い分けないといけなかったのが1つのプラグインに統合

output pluginの実装済みメソッド

  • process
  • write
  • try_write
  • format

  • bufferセクションの有無、プラグイン側のバッファ関係の実装の有無によりAPI側で頑張ってくれる

  • 動的にメソッドを呼び出されて動的に挙動を決定するし、明示的に挙動を決めることも出来る
  • ただし動的な呼び出しは若干動きが複雑
  • 実装が共有できれば、実装済みメソッドを使える

Delayed commit

  • 高レイテンシだとACKがすごく長いので、スレッドがロックされてしまう
    • num threadsの数字を上げてごまかしているが、ACKの長さは変わらない→非同期処理
    • すぐにreturnを返して非同期で処理を行うことで処理を効率化(commit_writeが長く帰ってこなかったらretry)
  • データの一貫性が保持されていない場合がある→定期的にデータをチェックして一貫性が問題なければcommitする
    • 分散ファイルシステムは書いてもすぐに読めないことがある

chunk keys

  • buffer chunk_keysで設定を細かくできる
  • 設定なしだったらチャンクをひとまとめにする
    • flush_interval時にflush / いっぱいになったらflush
  • timekey → この設定の間隔でチャンクを分割(細かく設定するとchunkが分割されすぎるのでwarningにしたいから誰かissueに書いて)
  • ANY_KEYS

configuration flushing buffers

  • flush_mode(lazy interval immediate←レコードが書き込まれた瞬間にflush)
  • flush_interval flush_thread_count
    • 今までと同じ設定
  • delayed_commit_timeout
    • デフォルト60秒
    • コールバックが呼ばれなかったらリトライ

Retry/Secondary

  • Explicit timeout
    • retry_timeout: 72時間
    • retry_max_times: 17回
    • この設定、デフォルト設定を知っている人は少ない
  • retry_type
    • リトライすると間隔が2倍に増える/おなじ間隔でリトライとかを選べる
  • retry_secondary_threshold(percentage)
    • リトライ失敗して諦めたらファイルに書き出すとかっていうのを選べるプラグイン
    • 挙動に不安があるので結構不安だった
    • 今まではsecondaryの書き込みは一発勝負だった
    • 80%って書いてあったら、retry_timeoutが80%以上だったらセカンダリに書き込み始める

Buffer parameters

  • chunk_limit_size
  • buffer_queue_limit バッファがいっぱいになったと見なすもの
  • キューに入っていない書き込み中のチャンクがあり、このチャンクはbuffer_queue_limitに勘定していない
    • ディスク容量ギリギリにしちゃったらディスクが死ぬのでは

Chunk metadata

  • stores various information
    • formattingが自動で行われる
    • いろんな情報が入っている
    • TODOは忘れがち

他のプラグイン

  • primary plugin
    • コアから直接ロードされるプラグイン
  • owned plugin
    • fluentdのコアが直接ロードすることはないけど、primaryに所属して呼び出すプラグイン
    • 例 @type json
      • jsonプラグインを呼ばなくてもprimaryプラグインに所属していてそこから呼び出している
  • storage plugin
    • redisやconsulなどのストレージに接続できる プラグインも作りやすい
  • plugin helpers
    • 好き勝手mixinしていたのをやめた
    • 明示的に宣言してください
    • 新テストドライバ→sleep 3みたいなのが要らなくなる
    • 例: child_process_execute thread_create thread_current_running? timer_execute
    • TBD socket/server for tcp/udp/tls parser formatter
    • helpers: timerって書くと、timer pluginが使えるようになる

New Test Drivers

  • Test Driverが新しくなった
  • Fluent::Test::*TestDriver
  • Fluent::Test::Driver::Input/Output/Filter
    • ログがちゃんと確認できる
    • フォーマットチェック
    • flushのタイミングチェック
      • ここで sleep 5 みたいなのを書かないといけなかったけど不要になった

これからやりたいこと

  • マルチプロセス
    • 課題はまだあるけど
  • forward TLS/認証
  • buffer圧縮
  • プラグインジェネレータ → テンプレがないとひよコードプラグインが群雄割拠しやすい
  • グローバル変数制御
  • プロセス制御
    • 流量制御

書くべきこと

  • 開発者向けガイド(APIのドキュメント)
  • ユーザーガイド(バッファまわりをより詳細に)