unagi.py

P2P風味のシステムモニタ

Last Modified: Wed Oct 26 01:47:00 EDT 2005 (10/26, 14:47 JST)

[English]


概要

unagi.py は緩く結合されたクラスタ環境のためのシステム監視ツールです。 これは複数のユーザがクラスタ上でさまざまなプログラムを走らせるときに、 各マシンの使用状況を報告することによって、ユーザが協力してそのマシン資源を 有効利用できるようにします。このプログラムはクラスタ上のすべてのマシンで走り、 システム情報を共有します。これはまた簡単な HTTP サーバとしての機能も そなえており、ユーザは状況報告をブラウザ上で見ることができます。

注意: unagi.py は公開用のサーバで走ることを意図してつくられては *いません*。 セキュリティ上の理由から、マシンの状態を外部のユーザに見せるべきではありません。

11マシンからなるクラスタの状況報告サンプル (HTML, 220k)

unagi.py の目標は 2つあります:

なぜ SNMP ではダメなのか?

unagi.py の機能は SNMP のそれに似ています。しかし、2つの異なる点があります: ひとつは、SNMP ではマネージャがすべてのデータを集め、決してダウンしてはいけないこと。 私たちの環境ではいつ、どのマシンもシャットダウンあるいは接続解除される可能性があったため、 すべてのマシンにお互いを監視させたかったのです。これによりユーザは (すべてのマシンが一斉に死なない限り) いつでもどれかのマシンに保存されているマシン 情報にアクセスすることができます。もうひとつは、SNMP の設定がひどく複雑なことです。 私たちは堅牢かつ簡単に設定可能なものを求めていました。

サポートしている OS

システム情報を集める方法は OS 依存のため、 unagi.py は 現在のところ Linux でしか走りません。これは以下のような情報を収集します:

変更履歴


ダウンロードと設定

このプログラムを走らせるには Python 2.3 以上 が必要です。 (Python 1.5.2 でも動きますが、古いバージョンの Python には特権を落とすための 関数が欠けているので新しいバージョンのほうがおすすめです。)

プログラムを走らせるには、まずスクリプトファイルを修正していくつかの パラメータを設定する必要があります (これらの値はコマンドラインからも設定できます)。 変更する必要のある箇所は以下のとおりです:

# ネットワーク情報
SIGNATURE = 'なんらかの文字列'
P2P_PORT = P2Pネットワークのための TCPポート番号     # >1024
HTTP_PORT = 状況報告のための HTTPポート番号          # >1024
P2P_SCAN_RANGES = [ 最初のスキャンを行うアドレス範囲 ] # ex. [ "192.168.0.100-199" ]
P2P_ALLOW_RANGES = [ 信頼する peer ホストのアドレス範囲 ]    # ex. [ "192.168." ]
HTTP_ALLOW_RANGES = [ HTTPアクセスを許すアドレス範囲 ]    # ex. [ "192.168.", "127." ]
UNAGI_USER = 'スクリプトを走らせる実効ユーザ名'      # /etc/passwd を修正すること!

SIGNATURE には識別子として、なんらかの文字列を指定します。 ある P2Pネットワークに属するすべてのマシンは同一の識別子をもつ必要があります (識別子が違っている場合、他の peer からは無視されます)。 これの基本的な目的は複数の異なる P2Pネットワークを区別するためですが、 たとえネットワークがひとつしかない場合でもなんらかの文字列を指定する必要があります。 また、P2P_PORT ポート番号と HTTP_PORT ポート番号も 同一ネットワーク上のすべてのマシンで同じにする必要があります。 P2P_SCAN_RANGES, P2P_ALLOW_RANGES, および HTTP_ALLOW_RANGES の各値については、お使いのサブネットの ネットワークアドレスを指定してください。状況報告を外部のネットワークからも 見られるようにしたい場合は HTTP_ALLOW_RANGES に他のマシンの IPアドレスを追加してください。また、P2P_ALLOW_RANGES を変更することで、 サブネットの外のマシンが P2Pネットワークにアクセスすることもできます。 が、世界じゅうのすべてのマシンにお使いの P2P ネットワークを見せないようにしてください! これはセキュリティ上問題となることがあります。 これらのポート番号は、外部のネットワークからは遮断しておくことをおすすめします。 プライベートネットワークで使っている場合は、これについてあまり深く心配する必要はないでしょう。 また、unagi.py は UDP パケットを他の peer との通信に使っているため、 ルータを越えた通信は信頼性がなくなることも覚えておいてください。 また、 P2P_SCAN_RANGES はお使いのネットワーク内のアドレスだけに 厳密に制限するようにしてください。なぜなら unagi.py は最初にこの範囲にある アドレスすべてをスキャンし、ネットワーク上にある他のマシンを探索するためです。 P2P_SCAN_RANGES にはこのプログラムが走っているマシン自体のアドレスも 含まれていなければなりません。

アドレス範囲は Python のリストとして指定されます。 各リストは 1つ以上の範囲を含むことができます。範囲は以下のようにして指定します:

unagi.py doesn't need a root privilege to run. So usually it should run as a harmless user (e.g. "nobody") which has minimum privilege. When you run this program as root, the script changes its process UID and GID if a specific username is given as UNAGI_USER parameter. (However there is a small problem in the older Python -- since Python 1.5.2 or older doesn't have setgroups function, it cannot drop its groups permission, which is not secure. This is why I recommend to use a newer version.) However, it does need a permission to read several files and execute ps command to obtain system information. In particular, it needs a permission to read a syslog output file (usually stored in /var/log/messages) which is probably not world-readable in most Linux distributions. So you will need to grant a permission to the user for reading this file. The safest way is to create a new group named something like "log", and make the syslog file group-readable to this group. Then create a user "unagi" which belongs to this group and run the script on this user. For example,

Add the following entry to /etc/group:

log:x:888:

Add the following entry to /etc/passwd:

unagi:x:10000:888::/:/sbin/nologin

After setting the configuration, make sure this script launched at startup. You can also run the script directly from the shell for testing purpose.

Running on Linux, unagi.py refers to the following files:

Command Line Syntax

unagi.py [-d] [-u update] [-p p2pport] [-n p2pallow] [-h httpport]
         [-a httpallow] [-s scanaddrs] [-S signature] [-H nhistory] [-U username]

unagi.py accepts the following command line options.


仕組み

unagi.py shares system information with other peers by periodically asking every machine its status (default: every 10mins). Each peer has an internal on-memory database which contains the current status of each machine (including the machine itself). unagi.py uses a packet-based message to communicate with other peers. When a peer receives a message from an unknown machine, after confirming its signature it recognizes the sender as a new peer and registers it to the database. Ocasionally (default: every 30mins) each peer broadcasts a list of all known peers to the entire P2P network so that other peers can know newly added machines. When a machine doesn't respond for a while (default: 30mins), it marks the machine as "down". A machine is eventually removed from the database if it doesn't respond for a long time (default: 10days).

When it is started, unagi.py tries to drop a privilege (if a username is given), then to bind two sockets: a UDP socket is used to communicate with other peers. A TCP socket is used to serve HTTP requests. It first scans a certain range of addresses (specified by P2P_SCAN_RANGES) to find other peers by sending an initial query packet to every machine in the specified range until it receives a response from another peer. Since the initial query range includes the machine itself, at lease one machine should respond. After this, it enters an event loop and handles the following protocol.

プロトコル

Communication protocol between peers is simple and stateless. Each message consists of a single UDP packet which contains a text string. Each peer must respond to a message as soon as it receives, or do nothing. Each message must start with its network signature string and it is checked whenever a message is received. There are four types of messages used in the current protocol:

By giving the debug option (-d), you can see which message is sent from one peer to another.


今後の予定


ライセンス

(注: これはいわゆる「MITライセンス」と呼ばれる形式のものです)

Copyright (c) 2004 Yusuke Shinyama <yusuke at cs dot nyu dot edu>

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


Yusuke Shinyama