Fluentd meetup #2

9,091 views

Published on

Fluentd Meetup #2の発表資料です

Fluentd meetup #2

  1. 1. Fluentd & TreasureDataで こっそり始めるログ集計 Fluentd Meetup #2 @mikeda 1
  2. 2. 自己紹介• @mikeda – インフラエンジニア – Fluentd歴3ヶ月• 会社:CROOZ – モバイルメインのWEBサービス – ブログとかソーシャルゲームとか – サーバ450台くらい• 最近個人的に作ったもの – 『ざびたんウィジェット』 – あんまり反響が(´・ω・`) 2
  3. 3. 今日は「Fluentd流行ってますよ。御社でも使ってみませんか?」「でも導入たいへんなんじゃ・・・」「だいじょうぶ、そんなことありません!!!」という話と、実際にどういうふうに使っているかについてです。 3
  4. 4. FluentdとTreasureDataについて• Fluentd – 構造化されたデータ – プラグインによる高い自由度 – リアルタイム性 →データストリームを統合管理する基盤• TreasureData – TreasureData .inc – クラウドなHadoop(Hive) – Fluentdから簡単にデータを投入できる 4
  5. 5. 今やってること グラフ&保存(検索/集計)• アクセスログ:2億/day – グラフ:PV、レスポンスタイム、遅延件数(アラート設定) – 保存:TreasureData• アプリケーションのエラーログ – グラフ:Warning、Errorの件数 – 保存:とりあえず無し• メールログ(試験中) – グラフ:キャリアごとのメール受信数 – 保存:MongoDB 傾向分析と詳細調査の両方が簡単にできるように 5
  6. 6. 構成概要各サーバにtd-agentをインストール APPサーバ APPサーバ メールサーバ その他 WEBサーバ WEBサーバ WEBサーバ WEBサーバ WEBサーバ WEBサーバ WEBサーバ WEBサーバ WEBサーバ WEBサーバ WEBサーバ WEBサーバ td-agent td- td-agent td- td-agent td- 集約サーバ Active/Standby 集約サーバ 新規サーバ td-agent td- 6
  7. 7. 構成概要集約サーバにログを集約、各種処理とアウトプット APPサーバ APPサーバ メールサーバ その他 WEBサーバ WEBサーバ WEBサーバ WEBサーバ WEBサーバ WEBサーバ WEBサーバ WEBサーバアクセスログ WEBサーバ アプリログ WEBサーバ メールログ ??? WEBサーバ WEBサーバ ??? td-agent td- td-agent td- td-agent td- 集約サーバ Active/Standby 集約サーバ 新規サーバ td-agent td- Zabbixサーバ Zabbixサーバ ファイル TreasureData MongoDB 7
  8. 8. グラフのイメージサービス単位でグラフ作成(Zabbix) レスポンスコードごとのPV レスポンスコードごとのPV レスポンスタイム レスポンス遅延 アプリケーションエラー件数 8
  9. 9. 導入に至った経緯• 『おもしろそう』からスタート – 渋谷の居酒屋でC社の@oraXXXさん、D社の@ryiXXさん Fluentdおもしろいよー syslog-ngでいいじゃん syslog-ngオワコンじゃん (´・ω・`)ショボーン 。。。(話を聞く) おもしろそうだからとりあえず使ってみるわー※もちろんその後に事前検証、メリット検討しました! 9
  10. 10. 普通に導入しようとすると「えー、ログとかそんながんばんなくていいでしょ」 となるかも(どうしても裏側は後回しになりがち) 10
  11. 11. でもこのあたりを抑えれば• 人と工数• 費用(サーバ OR お金)• 既存システムへの影響 ちょっとやってみようか、という雰囲気を作れる 実際どうだったか? 11
  12. 12. 人と工数• 人→ほぼ自分だけ – 中堅どころのLinux力 – 初心者に毛が生えたくらいのRuby力 – 調整力&政治力・・・しがない1エンジニアです(´・ω・`)• 工数→うろ覚えだけどきっとそんなにいらない・・・ – 導入、展開は簡単→td-agent(全部込みパッケージ) 1. yum install td-agent 2. コンフィグ編集 OR rsync 3. /etc/init.d/td-agent start – 基本は設定ファイルベース • ググってコピペ 12
  13. 13. 費用(サーバ OR お金)• Fluentd – 最初は追加サーバ1台 →2億/dayのアクセスログ+α – 障害発生 →冗長化して2台(片方はスタンバイ) – マルチプロセス化などの負荷対策は特に無し – もちろん規模によりけり • 50億/Day、100,000msg/secな人は@tagomorisさんに• TreasureData – 500GBまで無料(圧縮サイズで) – それ以上の容量、CPU予約したい場合は中の人に相談 13
  14. 14. 費用(サーバ OR お金) 集約サーバ負荷:CPU• 古めのサーバ(HP DL360G5)1台 →けっこうつらめ – CPU:Xeon E5430 2.66GHz 4コア – →user 20%(1プロセスなのでけっこうギリギリ) – メモリ:8G(平常運転で使用量1G) HDD:SAS 15krpm、ライトキャッシュ無し →I/O wait 8%• もうちょっと新しめのサーバにリプレース画策中 14
  15. 15. 費用(サーバ OR お金) 集約サーバ負荷:トラフィック• 気にするほどじゃない – IN(各サーバからの転送):ピークで20Mbps – OUT(TreasureDataへの転送):ピークで3Mbps 15
  16. 16. 既存システムへの影響• 既存サーバの負荷増加 – 無視できるレベル →APPサーバに導入(2000万/day)• パッケージの依存関係 – ほぼなし →td-agent(専用のruby、gem、fluentd同梱)• 既存環境の設定変更&アプリケーションの修正 – いったんいじらない →既存ログからデータ取得 ほぼ影響なし →ダマで入れても絶対バレない!!! 16
  17. 17. というわけで• ある程度までの規模であれば• そんなに難しいことをしなくても簡単に導入できました みなさんも気軽に導入してみましょう! 17
  18. 18. ここから・・・実際の構成、設定について 18
  19. 19. その1-1 アクセスログ Fluentd 19
  20. 20. 使ってるプラグイン• WEBサーバ側 – tail:アクセスログをtail – forward:集約サーバに転送• 集約サーバ側 – forward:WEBサーバからログ受け取り – exec_filter:フィルタリング(また後で) – copy:出力を分岐 – tdlog:TreasureDataにデータ送信 – datacounter:条件付きカウント(@tagomorisさんThx) – zabbix:カウント結果をZabbixに送信(@fujiwaraさんThx) 20
  21. 21. プラグイン構成 21
  22. 22. グラフのイメージサービス単位でグラフ作成(Zabbix) レスポンスコードごとのPV レスポンスコードごとのPV レスポンスタイム レスポンス遅延 22
  23. 23. APPサーバ側設定• 設定ファイルの構成 /etc/td-agent/ |-- conf.d | |-- site1.conf | `-- site2.conf `-- td-agent.conf• 1サービス1コンフィグ(ちょっと管理めんどう) 23
  24. 24. APPサーバ側設定 共通設定• td-agent.conf # サイトごとの設定をinclude include conf.d/*.conf # forward.**は集約サーバに転送 conf.d/*をinclude <match forward.**> type forward <server> host 192.168.1.101 port 24224 standby </server> <server> host 192.168.1.102 port 24224 集約サーバにforward </server> buffer_type file buffer_path /var/log/td-agent/buffer/forward flush_interval 60s </match> # Fluentdのログ <match fluent.**> type file Fluentd本体のログ、 path /var/log/td-agent/fluent.log </match> # マッチしなかったログ マッチしなかったログはファイルに <match **> type file path /var/log/td-agent/no_match.log </match> 24
  25. 25. APPサーバ側設定 サービスごとの設定• conf.d/site01.conf – アクセスログのtail<source> type tail format format /^(?<host>[^ ]*) [^ ]* [^ ]* ¥[(?<time>[^¥]]*)¥] "(?<method>¥S+) +(?<path>[^ ]+) +¥S*" (?<code>[^ ]*) (?<size>[^ ]*) "(?<referer>[^¥"]*)" "(?<agent>[^¥"]*)" (?<restime>[^ ]*)/ time_format %d/%b/%Y:%H:%M:%S %z path /var/log/httpd/site01-access_log.link tag forward.access.site01 pos_file /var/log/td-agent/site01-access_log.pos</source> 25
  26. 26. 集約サーバ側設定• 設定ファイルの構成 /etc/td-agent |-- conf.d | |-- site01.conf | `-- site02.conf |-- filter | |-- mobile_access_log_filter.rb | `-- social_access_log_filter.rb `-- td-agent.conf• 1サービス1コンフィグ(ちょっと管理めんどう)• ログの種別ごとにフィルタプログラム 26
  27. 27. 集約サーバ側設定 共通設定• td-agent.conf <source> type forward port 24224 転送を受け付ける bind 0.0.0.0 </source> include conf.d/*.conf conf.d/*をinclude <match fluent.**> type file path /var/log/td-agent/fluent.log </match> Fluentd本体のログ、 マッチしなかったログはファイルに <match *.**> type file path /var/log/td-agent/no_match.log </match> 27
  28. 28. 集約サーバ側設定 サービスごとの設定1段目• conf.d/game01.conf• 1段目:exec_filterでフィルタリング <match forward.access.game01> type exec_filter command /etc/td-agent/filter/mobile_access_log_filter.rb in_keys host,method,path,code,size,referer,agent,restime,dcmuid,auuid,sbuid,spuid out_keys host,method,path,code,size,referer,agent,restime,uid tag filtered.access.game01 </match> 28
  29. 29. 集約サーバ側設定 サービスごとの設定2段目• 2段目:カウンティングとTreasureDataへのデータ送信 <match filtered.access.game01> type copy <store> type tdlog apikey XXXXXXXXXXXXXXXXXXXXXXX buffer_type file buffer_path /var/log/td-agent/buffer/game01/td use_ssl true auto_create_table flush_interval 300s TreasureDataに送信 </store> <store> type datacounter count_key code aggregate all tag count.access.game01.code count_interval 300 pattern1 2xx ^2¥d¥d$ pattern2 pattern3 3xx 4xx ^3¥d¥d$ ^4¥d¥d$ レスポンスコードごとにカウント pattern4 5xx ^5¥d¥d$ </store> <store> type datacounter count_key restime aggregate all tag count.access.game01.restime count_interval 300 pattern1 0to100ms ^¥d{1,5}$ pattern2 100to200ms ^1¥d{5}$ pattern3 pattern4 200to500ms ^[2-4]¥d{5}$ 500to1000ms ^[5-9]¥d{5}$ レスポンスタイムごとにカウント pattern5 1000to4000ms ^[0-3]¥d{6}$ pattern6 over4000ms ^([4-9]¥d{6}|¥d{8,})$ </store> </match> 29
  30. 30. 集約サーバ側設定 サービスごとの設定3段目• 3段目:カウンティングした値をZabbixへ送信 <match count.access.game01.*> type copy <store> type file path /var/log/fluent/count.access.game01.log </store> <store> type zabbix zabbix_server 192.168.1.10 port 10051 host service_game01 name_key_pattern (xx_count|ms_percentage|4000ms_count)$ </store> </match> 30
  31. 31. exec_filterについて • 外部プログラムで自由にフィルタを作れるプラグイン – データ構造をちょっといじる • 各携帯キャリアごとのUID → 共通のUIDカラムに統合 • クエリストリングから情報を取得 – 個人情報の暗号化 – 不必要なデータを除外(静的ファイルのアクセスログなど) – • 乱用するとカオス化しそう – ログ自体をいじれるならそっちで解決しよう! ※TSVよりmsgpackのほうがいいかも 31
  32. 32. exec_filterの例 • モバイルサイトのアクセスログフィルタ – キャリアごとのUID→統合UID、静的ファイルの除外 #!/usr/lib64/fluent/ruby/bin/ruby require digest/sha1‘ path_filter = Regexp.new "^/(img|swf|css|js|healthcheck)/" while line = STDIN.gets line.chomp! host,method,path,code,size,referer,agent,dcmuid,auuid,sbuid,spuid = line.split("¥t") next if path_filter =~ path uid = "" [dcmuid, auuid, sbuid,spuid].each do |id| if id != "-" uid = Digest::SHA1.hexdigest id break end end puts [host,method,path,code,size,referer,agent,uid].join("¥t") end 32
  33. 33. その1-2 アクセスログ TreasureData 33
  34. 34. TreasureData • クラウドなHadoop – Fluentdでデータを投入 – Hive:HiveQL(SQLっぽい言語)でデータ参照 • td-agentをインストールするだけでひと通り使える – データの投入 • Fluentdプラグイン:tdlog • CLI:td – 各種操作(テーブル操作、クエリ発行、結果参照) • CLI:td • Rubyのライブラリ ※各種言語のライブラリもあります:Java、PHP 34
  35. 35. 構成概要集約サーバからのアウトプット先の1つ APPサーバ APPサーバ メールサーバ その他 WEBサーバ WEBサーバ WEBサーバ WEBサーバ WEBサーバ WEBサーバ WEBサーバ WEBサーバアクセスログ WEBサーバ アプリログ WEBサーバ メールログ ??? WEBサーバ WEBサーバ ??? fluentd fluentd fluentd 集約サーバ Active/Standby 集約サーバ fluentd Zabbixサーバ Zabbixサーバ ファイル TreasureData MongoDB 35
  36. 36. データの投入• Fluentdに設定を追記するだけ <match filtered.access.game01> type tdlog apikey XXXXXXXXXXXXXX buffer_type file buffer_path /var/log/td-agent/buffer/game01/td use_ssl true auto_create_table flush_interval 300s </match> 36
  37. 37. CLIでデータ参照• データ確認 $ td table:tail access game01 “size”:“234880”,“uid”:“XXXX”,“host”:“xx.xx.xx.xx”,“restime”:“95961”, {“referer”:“-”,“time”:1345590016,“method”:“GET”,“code”:“200”, “agent”:“Mozilla/5.0 ","path":"/mypage/"}• 集計 $ td query -w -d access "SELECT COUNT(distinct uid), COUNT(*) ¥ FROM blog ¥ WHERE unix_timestamp()-60*60*24 < time“ +---------+----------+ | _c0 | _c1 | +---------+----------+ | 1927724 | 70917556 | +---------+----------+ たいてい数分から十数分で完了(クエリと契約CPU数に依存) ※ td schema:setを実行するとv[‘uid’]じゃなくuidと書けるようになる 37
  38. 38. どういうふうに使ってるかいったんは定期集計ツールではなく、『かゆいところに手が届く調査ツール』として使ってます• 簡単な管理画面を作成 – Ruby & Sinatra – Ruby部分96行、テンプレート部分は合計99行 – プロトタイプ版の一部はブログにアップしてます 38
  39. 39. 管理画面 Home 39
  40. 40. 管理画面 Database/Table一覧 40
  41. 41. 管理画面 クエリ(ジョブ)発行 41
  42. 42. 管理画面 ジョブ一覧 42
  43. 43. 管理画面 ジョブ詳細、結果確認 43
  44. 44. 実際の集計例 44
  45. 45. TreasureDataの集計例レスポンス遅延が発生してるのはどのページ!?クエリSELECT split(path, ¥¥?)[0], COUNT(1) AS numreq FROM game01 WHERE unix_timestamp()-1*60*60 <= time AND restime > 3000000 GROUP BY split(path, ¥¥?)[0] ORDER BY numreq DESC※直近1時間で3秒以上かかっている件数 をパスごとに出力 45
  46. 46. TreasureDataの集計例問合せ調査 「タイムアウトばっかりでアクセスできません」クエリSELECT time, restime, path FROM game01 WHERE unix_timestamp()-24*60*60 < time AND uid = XXXXXXX ORDER BY time マイページアクセスが5秒以上かかっている マイページアクセスが5※指定ユーザのアクセスパスと処理 →特定ユーザの場合のみ 時間を時系列で出力 タイムアウトが発生するバグがあった 46
  47. 47. TreasureDataの集計例リリース直後に5分ごとのPVとUUを確認したい!クエリSELECT from_unixtime(CAST(time/(5*60) AS INT)*5*60) AS day, COUNT(distinct uid), COUNT(1) FROM game01 WHERE code = 200 AND unix_timestamp()-60*60 <= time GROUP BY CAST(time/(5*60) AS INT) ORDER BY day※5分ごとのUUとPVを出力 ごとのUUとPVを UU 特定ページのみといった りこみも簡単 ページのみといった絞※特定ページのみといった絞りこみも簡単 47
  48. 48. TreasureDataの集計例チュートリアルの離脱ポイントはどこ?クエリSELECT split(path, ¥¥?)[0], COUNT(1) AS numreq FROM game01 WHERE unix_timestamp()-15*60 <= time AND path LIKE /tutorial/% GROUP BY split(path, ¥¥?)[0] ORDER BY numreq DESC※/tutorial/から始まるパスをアクセス数 順に出力 48
  49. 49. TreasureDataの集計例サイトトップからの遷移状況が知りたい!クエリSELECT path COUNT(1) AS numreq FROM mikeda WHERE unix_timestamp()-60*60*24 <= time AND referer = http://mikeda.jp/ GROUP BY path SORT BY numreq DESC LIMIT 10※リファラーで絞り込んで遷移状況調査 49
  50. 50. もっと高機能なのが欲しかったら• TreasureDataが提供するダッシュボードもある(有料) 50
  51. 51. 導入して• 今まで – 集計システムは集計チームが作りこみ • 細かいことは対応しづらい – 特別に知りたいことがあったら • 集計チームに依頼する • 自分のPerlワンライナーが炸裂• 導入して – 「知りたいと思った人」か「その隣の人」がすぐ集計できる – 情報取得のコスト↓、意味のある情報を知るチャンス↑ – 草の根啓蒙中 51
  52. 52. アクセスログまわりの今後• サイト単位の設定がめんどう →forestプラグインで統合を検討中• ログのフォーマットを整理したい – 整理できればexec_filterいらないかな 52
  53. 53. その2 Postfixのmaillog ※試験中 53
  54. 54. メールログ解析• モバイル系のサイトはメールが多い – ブログ投稿、新規登録 – 不正も多い・・・• グラフ化&検索できるようにしたい※試験導入なので参考程度に。遅延時の挙動など未確認 54
  55. 55. Maillogのパース• すごくたいへん – 複数行で1セット&混ざりまくり – 複数サービスで共有(to=<xx@yyy>で振り分けが必要) モザイクもの• 単純にカウントするだけならto=だけ取得すればいいけど・・・• もっとFluentdっぽくやりたい! 55
  56. 56. in_tailを拡張する• 必要な情報を独自プラグインで組み立ててから転送• 標準プラグインのin_tailを拡張 – ローテート対応、デーモン停止時の取りこぼし防止などはin_tail にまかせる – やっていいか迷ったけどすでにやってるのがあった ※追記)@frsyki『in_tailはそういう設計で作ってるのでどんどん継承 しちゃってください』 – 自作プラグインは/etc/td-agent/plugin/に置くだけで動く – in_tailのコードは最初の100行くらい読めばいい ※コードのプロトタイプは@mikedaのGistにアップしてます 56
  57. 57. プラグイン構成 57
  58. 58. 使っているプラグイン• メールサーバ側 – maillog_tail:(in_tailの独自拡張) – forward• 集約サーバ側 – forward – rewrite_tag_filter:サイト単位に振り分け – forest:タグを見て動的にプラグインを複製 – mongo:mongodbにデータを出力 – datacounter:特定キーで件数カウント – zabbix:カウント結果をzabbixに送信 58
  59. 59. メールサーバ側の設定、出力データ• コンフィグ(基本的にin_tailと同じ)<source> type maillog_tail path /var/log/maillog tag maillog.test pos_file /var/log/td-agent/maillog.pos</source>• 出力データ2012-08-05T04:02:27+09:00 maillog.test { "qid":"AF06E10339D7", "from":"mikeda@mikeda.jp", "to":"oranie@oranie.com", "orig_to":nill, "size":"114364", "relay":"local", "delay":"1.5", "status":"sent"} 59
  60. 60. 集約サーバ側の設定 1段目• 1段目:rewrite_tag_filterでサービス単位にバラす →送信先ドメインでタグを付け替え<match forward.mail.rcv> type rewrite_tag_filter rewriterule1 orig_to @blog¥.mikeda¥.jp$ filtered.mail.rcv.blog rewriterule2 orig_to @wiki¥.mikeda¥.jp$ filtered.mail.rcv.wiki</match> 60
  61. 61. 集約サーバ側の設定 2段目• 2段目:各種キーでカウンティング&mongodbにデータ投入<match filtered.mail.rcv.*> type copy <store> type forest subtype datacounter remove_prefix filtered.mail.rcv <template> count_key from aggregate all tag count.mail.rcv.__TAG__ count_interval 300 pattern1 docomo [@.]docomo¥.ne¥.jp$ pattern2 au [@.]ezweb¥.ne¥.jp$ pattern3 softbank [@.](softbank¥.ne¥.jp|vodafone¥.ne¥.jp)$ </template> </store> <store> type mongo 61
  62. 62. 集約サーバ側の設定 3段目• 3段目:カウントした結果をZabbixに送信<match count.mail.rcv.*> type forest subtype zabbix remove_prefix count.mail.rcv <template> type zabbix zabbix_server 192.168.1.10 port 10051 host service___TAG__ add_key_prefix mail.rcv name_key_pattern count$ </template></match> 62
  63. 63. グラフできた! 63
  64. 64. 気になったら集計• 気になるところがあったらmongodbで集計『業者さんや・・・』 64
  65. 65. その3 アプリケーションエラーログ 65
  66. 66. 省略! 66
  67. 67. まとめ その1 Fluentd• けっこう簡単に導入できる!• 現状:アクセスログ、メールログ、アプリエラーログ – まだまだ試験中な感じですみません – 使わないとできないわけではないけど、使うとすごく楽 – in_tailはこっそり集計のキモ • ちょっと手を加えたい時はexec_filterかin_tailいじるか?• 検討、要望 – アプリチームを巻き込んで次の段階を検討中 →自由にログ出してもらってGrowthForecastで自動グラフ化 – プラグインの設定、内部状態ダンプ機能が欲しい 67
  68. 68. まとめ その2 TreasureData• とにかく簡単にHadoopが使える – Fluentdでデータ投入 – HiveでSQLっぽく集計• 1エンジニアが勢いで最初の一歩を突破できる! 最初の一歩が大きな壁だった コスト:HW、技術的コスト コスト:HW、技術的コスト リスク:コストとメリットが不明確 (´・ω・`)ショボーン 68
  69. 69. 終わり!!! 69

×