いますぐ実践! Linux システム管理 / Vol.270 / 読者数:2836名あけましておめ…いえ、大変おひさしぶりです。うすだです。 いま住んでいるマンションは、建ってから10年以上経ち、目下大規模修繕の真っ最中です。 社会人や学生のオアシスである大型連休中も、平日と土曜日は休みなく、 せっせと修繕をされていました。大変おつかれ様です、という感じです。 いちおう修繕委員のひとりですので、修繕内容や業者の選定など、 一連の流れに関わっています。こういうのは、 参加して経験しないと得られないことがありますので、 なるべく参加して意見を言うようにしています。
また、修繕委員でなくても、マンションの住人なら得られること、
事前のネットによる検索では得られなかった想定外のことが、結構あります。 想定外のこととは、ベランダや駐車場がときどき使えないとか、 作業している人と目があってお互い気まずい思いをしたりなど、 今のところは概ねたいしたことではないことばかりです。 …ある、ひとつを、除いては。 その、ひとつとは、騒音です。
まあ、とにかく、うるさい、のです。
とはいえ、大型連休29日〜8日のうち、平日と土曜日は4日間だけでした。 ですが、30日の騒音で出鼻をくじかれた後、エンジンがかからない状態のまま、 大型連休をだらだらと過ごしてしまいました。 これがやりたい! これをやろう! という意志が希薄だと、 どんなささいなことでもそれをやらない理由にしてしまうということを、 身をもって知ることができました。 これも、経験しないと得られないこと、なのではないでしょうか。
ええ、これも、意志の弱さから来る理由づけのように思います。 せめて発行はせねば、という思いを胸に、今回もはりきってまいります。 今回のお題 - Jubatus でログをクラスタリングしてみる (レベル:中級)サーバには、多種多様なログが、日々蓄積されていきます。 今この瞬間にも、rsyslog などが新たなログを書き込み、 logrotate などが古いログを消し去っています。
多忙なシステム管理者は、すべてのログに目を通す時間を確保する、
などということは、到底できっこありません。 しかし、それらによってあぶり出されるログたちは、 事前に指定した条件にマッチしたものだけです。指定し忘れたものや、 いままでに注目されることのなかったものは、網の目をくぐり抜けてしまいます。 細かい条件など指定しなくても、 いつもとちょっと違う(と思われる)ログを抜き出して提示してくれたら、 非常に助かりますよね。 というわけで今回は、クラスタリングを利用して、 いつもとちょっと違うログを収集したいと思います。 …最初にカミングアウトしておきますと、とりあえずやってみた、というレベルです。 実際のサーバに取り入れるには、幾多の高い壁を乗り越える必要があります。 どうして異常検知ではなくクラスタリングなのか? などといったピュアな質問は心の奥底にしまい、 生暖かい目で見守っていただけますよう、何卒よろしくお願い申し上げます。 Jubatus とは?
今回は、「Jubatus」でクラスタリングを行おうと思います。 Jubatus は、 「分散したデータ」を「常に素早く」「深く分析」することを狙った分散基盤技術です。 (下記ページよりコピペしました。) 大変ざっくり言ってしまうと、機械学習を、 簡単かつ幅広く使えるようにするためのソフトです。 Jubatus : オンライン機械学習向け分散処理フレームワーク http://jubat.us/ja/
泣く子も黙る Preferred Networks と、
NTTソフトウェアイノベーションセンタが共同開発した、
オープンソースのプロダクトです。
Jubatus では、「Zookeeper」
を使用して分散処理を実現しています。 で、今回は、そのちょろっと動かす方をやってみたいと思います。 Jubatus のインストール手順
インストール手順は、下記のクイックスタートに書かれています。 クイックスタート - Jubatus http://jubat.us/ja/quickstart.html
ちなみに、Ubuntu 15.04 でも、同様の手順でインストールできました。 $ sudo sh -c \ "echo deb http://download.jubat.us/apt/ubuntu/trusty binary/ \ > /etc/apt/sources.list.d/jubatus.list" $ sudo apt-get update $ sudo apt-get install jubatus ... 警告: 以下の警告: 以下のパッケージは認証されていません! jubatus 検証なしにこれらのパッケージをインストールしますか? [y/N] ← yと答える ...
また、上記の他に、クライアントのインストールも必要です。 $ sudo apt-get install python-pip $ sudo pip install jubatus Jubatus を使ってみましょう
Jubatus は、推薦も分類も異常検知もできます。が、ここでは諸般の事情により、
クラスタリングを行っていきます。
まず、実際に機械学習の処理を行うサーバを起動します。 $ . /opt/jubatus/profile $ jubaclustering --configpath \ /opt/jubatus/share/jubatus/example/config/clustering/kmeans.json 最初に「/opt/jubatus/profile」を読み込んでいますが、 「~/.bashrc」などで読み込むようにしておけば、実行は不要です。
それから、jubaclustering の実行時に、
設定ファイル「kmeans.json」を引数に指定しています。 ...前略... "parameter" : { "k" : 3, ...後略...
次に、クライアントを起動するのですが、クライアントは自分で作る必要があります。 ですので、Python でこんなのを書いてみました。 #!/usr/bin/env python # -*- coding: utf-8 -*- import sys import re import socket import jubatus from jubatus.common import Datum def line2datum(l, pat): d = pat.split(l) if len(d) <= 1: return None datum = Datum() # ※1 datum.add_binary('addr', socket.inet_aton(d[1])) # ※2 datum.add_string('method', d[2]) # ※3 datum.add_number('status', int(d[3])) # ※4 return datum if __name__ == '__main__': if len(sys.argv) != 3: print >> sys.stderr, "Usage: %s learnfile testfile" % (sys.argv[0]) sys.exit(1) jclient = jubatus.Clustering('localhost', 9199, 'apache_log') pat = re.compile('^(\d+\.\d+\.\d+\.\d+).*\]\s+\"(\S+)[^\"]+\"\s+(\d+)\s+"') # learn with open(sys.argv[1], 'r') as f: l = f.readline().rstrip() while len(l) > 0: datum = line2datum(l, pat) l = f.readline().rstrip() if datum is not None: jclient.push([datum]) # ※5 # get centers centers = jclient.get_k_center() # ※6 print '# centers' for center in centers: print center.num_values # test print '\n# test' with open(sys.argv[2], 'r') as f: l = f.readline().rstrip() while len(l) > 0: datum = line2datum(l, pat) l = f.readline().rstrip() if datum is not None: r = jclient.get_nearest_center(datum) # ※7 print datum, "\nresult:", r.num_values 上記では、第1引数で指定したアクセスログを読み込んで学習し、 第2引数のアクセスログを読み込んでクラスタリングの結果を表示します。
Jubatus では、「Datum」というデータ形式を使います(※1)。 第1引数のアクセスログで学習を行ったら、 それぞれのクラスタの中心を取得して(※6)、 標準出力に出力しています。 そして、第2引数のアクセスログそれぞれに対し、 もっとも近いクラスタの中心を求めて(※7)、 標準出力に出力しています。
上記スクリプトを適当なファイル名で保存し、 2つのアクセスログを引数に指定して実行します。 $ chmod +x clustering_alog.py $ ./clustering_alog.py 学習用アクセスログ 確認用アクセスログ すると、こんな結果が得られました。 # centers [('status', 200.01931762695312)] [('status', 404.0213317871094)] [('status', 303.39306640625)] # test datum{string_values: [['method', 'GET']], num_values: [['status', 200.0]],... result: [('status', 200.01931762695312)] datum{string_values: [['method', 'GET']], num_values: [['status', 200.0]],... result: [('status', 200.01931762695312)] datum{string_values: [['method', 'POST']], num_values: [['status', 404.0]],... result: [('status', 404.0213317871094)] datum{string_values: [['method', 'HEAD']], num_values: [['status', 304.0]],... result: [('status', 303.39306640625)] datum{string_values: [['method', 'CONNECT']], num_values: [['status', 405.0]],... result: [('status', 404.0213317871094)] datum{string_values: [['method', 'OPTIONS']], num_values: [['status', 200.0]],... result: [('status', 200.01931762695312)] ...
「# centers」の後の3行が、それぞれのクラスタの中心です。 メソッドが「GET」でステータスが「200」の場合、1つ目のクラスタに、 メソッドが「POST」でステータスが「404」の場合、2つ目のクラスタに、 メソッドが「HEAD」でステータスが「304」の場合、3つ目のクラスタに、 メソッドが「CONNECT」でステータスが「405」の場合、2つ目のクラスタに…と、 それっぽくクラスタリングされていることがわかります。 それっぽいと言うと聞こえがいいですが、 IPアドレスやメソッドも属性として渡しているのに、結局ステータスしか見ていない、 という残念な結果が得られてしまった次第です。 無理やり結論づけると、2つ目のクラスタに属するログをチェックした方がいいよ、 ということになりますでしょうか…。 おわりに以上、Jubatus を使って Apache ログのクラスタリングをやってみたが、 微妙な結果しか得られなかった、をお送りいたしました。
ちなみに、異常検知(anomaly)もやってみましたが、いろいろ試行錯誤を繰り返しても、
それっぽい結果を出すことができませんでした。
なお、Jubatus の利点のひとつに、オンライン処理が挙げられます。 宿題の答えもうお忘れかと存じますが、前回の宿題は、 UFW を無効にしたとき、NAPT の設定も無効にしましょう。 でした。 とりあえず下記をさらっとご覧いただき、思い出してくださいませ。 Vol.269 - UFW と NAPT を両立させる http://www.usupi.org/sysad/269.html
UFW を無効にしたり停止したりすると、
「/lib/ufw/ufw-init-function」の「ufw_stop」が呼ばれます。
じゃあ、ここで、NAPT の設定を削除する命令を追加すればいいですね。 ...前略... stop) # typically required if [ -n "$(iptables -t nat -nL | grep '^MASQUERADE.*192\.168\.1\.0')" ]; then iptables -t nat -D POSTROUTING -s 192.168.1.0/24 -o eth0 -j MASQUERADE fi ;; ...後略...
「# typically required」より後の3行(この色のif文のところ)が、追加する部分です。 $ sudo chmod +x /etc/ufw/after.init これで、「ufw disable」や「stop ufw」すると、 NAPT の設定がちゃんと削除されるようになります。 ただ、NAPT の設定の追加も削除も、1つの設定ファイルに集約したいですよね。 というわけで、前回変更した after.rules をもとの状態に戻し、 after.init に以下の設定を追加してみましょう。 ...前略... start) # typically required if [ -z "$(iptables -t nat -nL | grep '^MASQUERADE.*192\.168\.1\.0')" ]; then iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth0 -j MASQUERADE fi ;; ...後略... stop の際と同様、「# typically required」より後の3行(この色の部分)を追加します。 これで、変更したファイルは、after.init だけになりました。 さらに、start と stop の同じような設定を集約したり、 もう少し汎用性のある記述にしたりなど、改善点はいくつか思いつきますが、 あとは自由課題とさせていただきたいと存じます。 今回の宿題今回の宿題は、 他のログでもクラスタリングをしてみましょう。 です。
なにかよさそうなログを探してきて、リベンジしたいと思います。 あとがき先日、春の情報処理技術者試験がありましたが、うっかり申し込んでいたため、 受けに行ってまいりました。 今回は、勉強することが主な目的であり、その成果として受かったらいいなあ、 という程度に考えていました。
ですが、お金を払った以上は受かりたいと思い、入門書と、
試験対策用の書籍を購入し、大まかな計画を立てました。 …が、がんばったのはそこまででした。(いやがんばっていませんけど。) 結局、忙しかったり、忙しいことを言い訳にしたりして、 直前に過去問を解くことすらせず、本番を迎えてしまいました。 結果は、お察しの通り、推して知るべし、でございました。 何のために勉強するのかが曖昧だったため、どこかで、受かることが目標にすり替わり、 このままでは無理だと悟り、挑戦することを諦めたのではないかと思います。 我ながら、残念な性格だと思います。 今年買った書籍は来年も使えますので、 ぶれない目的や目標を定めた上で来年に挑みたいと思います。 まあ、これも、経験しないと得られないこと、なのでしょうかね…。
今回も、ここまで読んでいただき、誠にありがとうございました。
「いますぐ実践! Linux システム管理」はこちらです。
その他、作者に関するページは、概ね以下にございます。 |
▼ トップ ▼ プロフィール ▼ リンク
▼ 作ってみました
▼ せんでん
▼ 最近読んだ本
▼ 気に入ってる本 |