Mackerel のような SaaS のリソース監視サービスが流行ってそうな中、あえていまさら Munin を触ってみました。
ところで Munin のドキュメント、公式っぽいものが下記の 2 箇所にあるっぽいんですけど、どういうことなの?
Attention: All content still relevant for Munin 2.x will be moved from here to Munin Guide. Pages that are in transit or have already moved, will get an info box on top (like here), be set to "Read only" and later will be archived or purged.
移行中? らしいです。とりあえず後者の方が新しいっぽいです。
用語とか
- Munin マスター
- 監視する側
- Munin ノードから定期的にメトリクスを取得して RRD に保存
- 閾値をチェックして必要なら通知する
- 閲覧用の Web 画面
- Munin ノード
- 監視される側
- エージェントとして
munin-node
が動く
- Munin プラグイン
- Munin ノードでメトリクスを取得するスクリプト
- SNMP だと別のホストの SNMP エージェントからメトリクスを取得することもある
とりあえず使ってみる
Vagrantfile
とりあえず使ってみるために、次のような Vagrant 環境を使います。
Vagrant.configure(2) do |config| config.vm.box = "bento/centos-7.1" config.vm.define "web" do |config| config.vm.hostname = "web" config.vm.network "private_network", ip: "192.168.33.10", virtualbox__intnet: "munin" end config.vm.define "munin" do |config| config.vm.hostname = "munin" config.vm.network "forwarded_port", guest: 80, host: 1234 config.vm.network "private_network", ip: "192.168.33.11", virtualbox__intnet: "munin" end config.vm.provision "shell", inline: <<-SHELL sudo yum -y install vim-enhanced mailx nc SHELL config.vm.provider :virtualbox do |v| v.linked_clone = true end end
Munin ノード
監視される側です。munin-node
を epel からインストールします。
sudo yum -y install epel-release sudo yum -y install munin-node
設定ファイルを編集します。
sudo vim /etc/munin/munin-node.conf
下記を追記して監視する側(Munin マスター)からのアクセスを許可します。
cidr_allow 192.168.33.11/32
munin-node
を開始します。
sudo systemctl enable munin-node sudo systemctl start munin-node sudo systemctl status munin-node
試しにロードアベレージを取得してみます。munin-run
コマンドでローカルの munin-node
から情報を取得できます。
munin-run load
次のようにロードアベレージの値が表示されます。
load.value 0.30
TCP の 4949 ポートでもアクセスできるはずなので試してみます。
echo "fetch load" | nc localhost 4949
次のようにロードアベレージの値が表示されます。
# munin node at localhost.localdomain load.value 0.30 .
Munin マスター
監視する側です。munin
と Web 画面のために Apache もインストールします。
Apache を先にインストールしないと cgi がログの書き込みでパーミッションエラーになったので、同時にインストールしないほうが良いです。
sudo yum -y install epel-release sudo yum -y install httpd sudo yum -y install munin
マスターでも munin-node
を開始します。munin-node
は監視対象のホストで実行するものですが、マスターそのもののリソース監視も行いたいのと、後述する SNMP 監視も試すので、munin-node
をマスターでも実行します。
sudo systemctl enable munin-node sudo systemctl start munin-node sudo systemctl status munin-node
Apache を開始します。
sudo systemctl enable httpd sudo systemctl start httpd sudo systemctl status httpd
Basic認証の ID/PW を設定します。
sudo htpasswd -bc /etc/munin/munin-htpasswd munin pass
設定ファイルを作成します。
sudo vim /etc/munin/conf.d/example.conf
このディレクトリに置いた設定ファイルは自動的に読み込まれます(/etc/munin/munin.conf
で includedir /etc/munin/conf.d
のように指定されています)。
次のように監視対象のノードを追記します。
[example;web.example.com] address 192.168.33.10 use_node_name yes
TCP 経由で監視対象ノードから監視項目の値が取れることを確認します。 もし、値が取れなければ何かが間違っています。
echo "fetch load" | nc 192.168.33.10 4949
手動で munin-cron
を実行します。
sudo -u munin munin-cron
ブラウザで http://localhost:1234/munin/ を開くと Basic 認証が聞かれるので munin:pass
を入力すると Munin の画面が表示されます。
通知
監視項目に閾値を設定して、閾値を超えらたメールで通知されるように設定してみます。
Munin マスターで監視の設定を変更します。
sudo vim /etc/munin/conf.d/example.conf
次のように変更します。
contact.ore-no-mail.command mail -s "Munin ${var:group}::${var:host}" -r munin@example.com ore@example.com contact.ore-no-mail.always_send critical [example;web.example.com] address 192.168.33.10 use_node_name yes cpu.user.critical 50 contacts ore-no-mail
Munin ノードでCPU使用率を高めてみます。
while :; do :; done
しばらく待つと次のような通知が飛んできます
example :: web.example.com :: CPU usage CRITICALs: user is 100.00 (outside range [:50]).
Munin マスターの Web 画面でも Critical として表示されます。
監視の設定をざっくり説明します。
contact.ore-no-mail.command mail -s "Munin ${var:group}::${var:host}" -r munin@example.com ore@example.com
ore-no-mail
という名前で通知先を設定しますmail
から先は通知時に実行するコマンドです${var:host}
のような変数名が使用可能です
contact.ore-no-mail.always_send critical
- 常に通知する障害レベルを指定します
- この例では
critical
のみが常に通知されます - 前回と状態が変わっていなくても通知するという意味です
- つまり閾値を超えている間、通知され続けます
- デフォルトは未設定です
- ググると出てくる日本語の説明は間違っているものが多い気がします
[example;web.example.com] : cpu.user.critical 50
- このノードの
cpu
プラグインのuser
フィールドのcritical
の閾値を 50 にします
[example;web.example.com] : contacts ore-no-mail
- このノードの通知先として
ore-no-mail
を設定します - デフォルトは
contact
で設定されている通知先全部です
SNMP で監視
Munin ノードに net-snmp
をインストールします。
sudo yum -y install net-snmp net-snmp-utils
それっぽく設定します。
sudo tee <<'EOS' /etc/snmp/snmpd.conf com2sec s_default default oreore group g_all_ro v1 s_default group g_all_ro v2c s_default view v_all included .1 access g_all_ro "" any noauth exact v_all none none load 12 14 14 EOS
snmpd
を起動します。
sudo systemctl enable snmpd.service sudo systemctl start snmpd.service
Munin マスターに net-snmp-utils
を入れます。
sudo yum -y install net-snmp-utils
マスターからノードの snmpd にアクセスできることを確認します。
snmpwalk -v1 -c oreore 192.168.33.10 la
/etc/munin/plugin-conf.d/zzz-snmp
に SNMP のコミュニティ名などを設定します。
このディレクトリのファイルは自動で全部読まれるのでファイル名はなんでもいいです。
sudo tee <<'EOS' /etc/munin/plugin-conf.d/zzz-snmp [snmp_192.168.33.10_*] env.community oreore env.version 1 EOS
この後 Munin マスターの /etc/munin/plugins/
にプラグインのシンボリックリンクを作るのですが、munin-node-configure
を使うと設定可能な項目を一覧表示できます。
munin-node-configure --snmp 192.168.33.10 --snmpcommunity oreore
Plugin | Used | Suggestions ------ | ---- | ----------- snmp__cpuload | no | yes (+192.168.33.10) snmp__df | no | yes (+192.168.33.10) snmp__df_ram | no | yes (+192.168.33.10) snmp__fc_if_ | no | no :
--shell
オプションを付けると /etc/munin/plugins/
へシンボリックリンクを作成するためのコマンドが表示されます。
munin-node-configure --snmp 192.168.33.10 --snmpcommunity oreore --shell
ln -s '/usr/share/munin/plugins/snmp__cpuload' '/etc/munin/plugins/snmp_192.168.33.10_cpuload' ln -s '/usr/share/munin/plugins/snmp__df' '/etc/munin/plugins/snmp_192.168.33.10_df' ln -s '/usr/share/munin/plugins/snmp__df_ram' '/etc/munin/plugins/snmp_192.168.33.10_df_ram' :
これを bash
にパイプすればシンボリックリンクが作成されます。
munin-node-configure --snmp 192.168.33.10 --snmpcommunity oreore --shell | sudo bash -x
munin.conf
を編集します。
sudo vim /etc/munin/conf.d/example.conf
次のように追記します。マスターから見てローカルの munin-node
が SNMP で監視対象のノードから情報を取得するので address
は 127.0.0.1
です。セクションの 192.168.33.10
が SNMP で接続する先です。
[example;192.168.33.10] address 127.0.0.1
マスターの munin-node
を再起動します。
sudo systemctl restart munin-node
munin-cron
を手動で実行します。
sudo -u munin munin-cron
ブラウザで見てみると snmp で取得した項目が増えています。
この手順だと 192.168.33.10
という名前の名前で Munin の画面上で表示されますが、次のように設定すると任意の名前にできます。
/etc/munin/plugin-conf.d/zzz-snmp
[snmp_192.168.33.10_*] env.community oreore env.version 1 host_name web-by-snmp
/etc/munin/conf.d/example.conf
[example;web-by-snmp] address 127.0.0.1
SNMP の監視で通知を設定するときは、プラグイン名の .
を _
に読み替えて記述します。例えば、ロードアベレージなら次のように指定します。
[example;web-by-snmp] address 127.0.0.1 snmp_192_168_33_10_load.load.critical 3 contacts ore-no-mail
snmp_192_168_33_10_load
という名前は、Munin の Web 画面でそのグラフを表示したときの URL に、load
の方は、その画面の下の方にあるテーブルの Internal name
です。
Native SSH Transport
Munin マスターからノードへの接続を SSH にすることができます。
Munin マスターから Munin ノードへ munin
アカウントでログインすることになるのですが、パッケージインストール時のデフォだと munin
アカウントのログインシェルが /sbin/nologin
になっていて SSH でのログインが不可能です。
なので、Munin ノードの munin
アカウントのログインシェルを chsh
で適当なシェルに変更します。
sudo chsh -s /bin/bash munin
Munin ノードで公開鍵を配置するディレクトリを作成してそれっぽくパーミッションやオーナーを設定します。
sudo mkdir /var/lib/munin/.ssh sudo touch /var/lib/munin/.ssh/authorized_keys sudo chmod 700 /var/lib/munin/.ssh sudo chmod 600 /var/lib/munin/.ssh/authorized_keys sudo chown -R munin. /var/lib/munin/.ssh
Munin マスターで鍵ペアを作成して公開鍵を Munin ノードに転送します。
sudo -u munin -H ssh-keygen sudo cat /var/lib/munin/.ssh/id_rsa.pub | ssh vagrant@192.168.33.10 sudo -u munin tee /var/lib/munin/.ssh/authorized_keys
Munin マスターからノードにログインできることを確認します。
sudo -u munin -H ssh 192.168.33.10 uname -n
Munin マスターでノードへの接続設定を変更します。
sudo vim /etc/munin/conf.d/example.conf
次のように変更します。
[example;web.example.com] address ssh://192.168.33.10 /bin/nc 127.0.0.1 4949 use_node_name yes
Munin マスターで munin-cron
を手動で実行します。
sudo -u munin munin-cron
Munin ノードでログを確認してみます。
tail /var/log/munin-node/munin-node.log
ローカルホストからの接続になっています。
2015/04/23-21:39:06 CONNECT TCP Peer: "[127.0.0.1]:49566" Local: "[127.0.0.1]:4949"
.
うーん? SSH しかポートが空いてないとか、中継サーバを経由しないとアクセスできないとかの場合に使うものなのでしょうか。
監視間隔を変更
デフォだと監視間隔は 5 分なので 1 分に縮めてみます。
Munin マスターの設定を変更します。
sudo vim /etc/munin/munin.conf
次のように追記します。
update_rate 60
cron の設定も変更します
sudo vim /etc/cron.d/munin
元は 5 分ごとになっているので、1 分ごとに変更します
*/1 * * * * munin test -x /usr/bin/munin-cron && /usr/bin/munin-cron
crond をリロードして設定を反映します。
sudo systemctl reload crond.service
これで 1 分ごとに監視されるようになりました。
と、言いたいところですが、1回でも munin-cron
を実行したことがあると変更しても意図したとおりにはならなさそうです。
どうしても変更したければ rrd ファイルの変換が必要なようです。
update_rate
は man しても出てこないので使えないのかなと思ったのですが、このような事情によりアンドキュメントなのかもしれません(適当)。
監視項目の削除
/etc/munin/plugins
にあるシンボリックリンクが、そのホストの監視項目(プラグイン)です。
なので /etc/munin/plugins
にあるシンボリックリンクを削除すると、その項目は監視されなくなります。
プラグインの実体は /usr/share/munin/plugins/
にあります。
例えば Postfix の監視を削除してみます。
sudo rm /etc/munin/plugins/postfix_mail* sudo systemctl restart munin-node
これで、Postfix に関する監視は行われなくなります。
もしくは /etc/munin/munin-node.conf
で ignore_file
で無視するプラグインを指定できます。
sudo vim /etc/munin/munin-node.conf
次のように正規表現で指定します。
ignore_file ^postfix_
ファイル名がアンスコで終わるプラグインは、リンク名が引数として使用されます。
例えば /usr/share/munin/plugins/if_
が /etc/munin/plugins/if_enp0s3
という名前のシンボリックリンクになっていますが、この場合 enp0s3
がプラグインの引数として用いられます。
また、SNMP 関連のプラグインは、プラグイン名にアンスコが 2 つ含まれており、その部分に SNMP エージェントのホスト名や IP アドレスが入ります。
例えば、/usr/share/munin/plugins/snmp__cpuload
が snmp_192.168.33.10_cpuload
のようにリンクされます。
プラグインの作成
自分でプラグインを作ってみます。Munin ノードで次のようにスクリプトを作成します。
sudo vim /usr/local/bin/ore.sh
#!/bin/bash if [ "$1" = "autoconf" ]; then echo yes exit 0 fi if [ "$1" = "config" ]; then echo 'graph_title ore no title' echo 'graph_args --base 1000 -l 0' echo 'graph_vlabel ore' echo 'graph_scale no' echo 'graph_category oreore' echo 'are.label are' echo 'are.min 0' echo 'are.draw AREA' echo 'are.type GAUGE' exit 0 fi echo "are.value 25"
プラグインのディレクトリにシンボリックリンク作成します。
sudo chmod +x /usr/local/bin/ore.sh sudo ln -s /usr/local/bin/ore.sh /etc/munin/plugins/ore
munin-run
でプラグインを実行してみます。
munin-run ore
次のように値が得られます。
are.value 25
ノードの munin-node
を再起動します。
sudo systemctl restart munin-node.service
しばらく待ってから Munin マスターをブラウザで表示すると項目が増えています。
テンプレートを変更
Bootstrap ベースのテンプレートに差し替えます。Munin マスターで munin-monitoring/contrib
をダウンロードします。
mkdir /tmp/munin-contrib wget https://github.com/munin-monitoring/contrib/archive/master.tar.gz -O - | tar xzf - -C /tmp/munin-contrib --strip-components=1
テンプレートと静的ファイルを Munin のディレクトリに上書きします。
sudo rsync -av /tmp/munin-contrib/templates/munstrap/templates/ /etc/munin/templates/ sudo rsync -av /tmp/munin-contrib/templates/munstrap/static/ /etc/munin/static/
既に作成されているファイルを削除して munin-cron
を手動実行します。
sudo rm -rf /var/www/html/munin/* sudo -u munin munin-cron
Munin マスターをブラウザで表示すると見た目が Bootstrap 風になっています。
CGI
デフォでは munin-cron
の実行時に HTML やグラフ画像が作成されています。
ll /var/www/html/munin/example/web.example.com
監視対象が増えてくるととても重いので、CGI でオンデマンドに HTML やグラフ画像が作成されるように変更します。
まず、Munin マスターに munin-cgi
をインストールします。
sudo yum -y install munin-cgi
Apache を再起動します。
sudo systemctl restart httpd
Munin の設定を変更します。
sudo vim /etc/munin/munin.conf
下記の箇所を変更します。cron ではなく cgi でグラフや html を作る、という意味です。
graph_strategy cgi html_strategy cgi
生成されている HTML ファイルを削除して munin-cron
を手動で実行します。
sudo rm -fr /var/www/html/munin/* sudo -u munin munin-cron
生成されたファイルを確認してみると static しかないことがわかります。
ll /var/www/html/munin/
ブラウザで http://localhost/
を開くと(http://localhost/munin/
ではなく)、Munin の画面が表示されます。
雑感
お手軽に使えるのが良いですね。
- インストールが簡単
- epel から yum で入れられる
- Cacti も yum で入れれるけど MySQL とかも必要だし
- 監視サーバの設定が簡単
- 監視サーバには設定ファイルを置くだけ
- 逆に GUI での設定は無いけど困らない
- Cacti だと GUI なのでかなり辛い(CLI もあるけど使いにくい)
- 監視対象のサーバの設定も簡単
- munin-node をインストールしてプラグインへのシンボリックリンクを作成するだけ
- Cacti でも snmpd をインストール&設定するだけなので簡単といえば簡単
- カスタム監視項目が簡単
- 簡単なスクリプト1個で項目を追加できる
- Cacti だと監視項目の追加がとてもつらい
- SNMP にも対応
- 既存のサーバやネットワーク機器の監視にも導入しやすい
- 閾値によるアラートをデフォで対応
- Cacti でもプラグインでできるけどとても面倒です
ただ、Cacti と比べると閲覧画面の機能がかなり劣っているようにも感じました。
例えば Cacti だと次のようなことが出来たのですが、静的に出力するのが基本な Munin ではそういうのができなさそうです。
- 表示するグラフの一覧を設定としてあらかじめ作成しておけたり
- ホスト名の部分一致で条件指定してグラフをずらーっと並べたり
- さらに任意の時間幅を指定してグラフをずらーっと並べたり
もうちょい突っ込んだ説明
munin.conf
munin.conf
は下記の3種類のセクションを記述します。
- 1つのグローバルセクション
- ゼロ以上のグループのセクション
- 1つ以上のホストのセクション
設定ファイルの構成は例えば次のようになります。
# グローバルセクション [localhost] # localhost グループの localhost ホストのセクション [foo.example.com] # example.com グループの foo.example.com ホストのセクション [example.com;bar.example.com] # example.com グループの bar.example.com ホストのセクション # ↑と同じだがグループを明示的に指定している [groupname;] # groupname グループのセクション # このグループすべてに適用される設定を記述できる [groupname;baz.example.com] # groupname グループの baz.example.com ホストのセクション
グループのセクションやホストのセクションには、次の3種類のディレクティブが記述できます。
- ノードのディレクティブ
- プラグインのディレクティブ
- フィールドのディレクティブ
ノードのディレクティブは、これまでの例で書いてきた address
とか use_node_name
とかです。
プラグインのディレクティブは PLUGIN.DIRECTIVE <VALUE>
の形式で記述します。例えば cpu.contacts ore-no-mail
のように特定のプラグインで通知の宛先を指定することができます。
フィールドのディレクティブは PLUGIN.FIELD.DIRECTIVE <VALUE>
の形式で記述します。例えば cpu.user.critical 50
のように特定のプラグインの特定のフィールドの閾値を指定できます。
詳細は下記。
munin-node.conf
munin-node.conf
は munin-node
(Munin のエージェント) の設定ファイルです。
アクセス制御とか無視するプラグインとかを設定できます。
詳細は下記。
plugin-conf.d
/etc/munin/plugin-conf.d
にはプラグインの設定ファイルを設置します。
ここにはパッケージからインストールされたファイルが幾つか配置されています。それらのファイルを編集するとアップデートで上書きされてしまうかもしれないため、その代わりに zzz-myconf
のようなファイルで設定を上書きします(ファイルはアルファベット順で読まれる)。
設定ファイルは[plugin-name]
の形式でプラグインごとにセクションを記述します。プラグイン名の先頭または終端はワイルドカード *
にすることができます(両方や中間は不可)。
上の例で行ったように、特定のホストの SNMP のコミュニティ名などを一括で設定したい場合は下記のようにワイルドカードで指定します。
[snmp_192.168.33.10_*] env.community oreore env.version 1
設定可能な項目は下記のガイドを参照してください。
env.var <variable content>
でプラグインの環境変数を設定できます。どのようなものが設定できるかはプラグインによって異なります。詳細はプラグインのドキュメントで確認できます。
munindoc snmp__cpuload
Please see 'perldoc Munin::Plugin::SNMP' for further configuration information. とのことなので、
perldoc Munin::Plugin::SNMP
snmp 関連のプラグインの共通の情報が表示されました。
munin-cron
munin-cron
は下記の 4 つのスクリプトを実行します。
/usr/share/munin/munin-update
- メトリクス値を取得して保存
/usr/share/munin/munin-limits
- 閾値をチェック
/usr/share/munin/munin-html
- html を生成
html_strategy
がcgi
なら何もしません
/usr/share/munin/munin-graph --cron
- グラフを生成
graph_strategy
がcgi
なら何もしません
munin-node が返すホスト名
1つの munin-node
は複数のホストの情報を提供することができます。例えば↑で設定したような構成だと、Munin マスターで実行されている munin-node
は localhost.localdomain
と web-by-snmp
の2つのホストの情報を提供しています。
$ echo nodes | nc localhost 4949 | tail -n +2 localhost.localdomain web-by-snmp .
この名前はプラグインに config
を付けて実行すると host_name
で得られます。
$ munin-run snmp_192.168.33.10_cpuload config | grep host_name
host_name 192.168.33.10
しかし snmp ではない普通のプラグインだと host_name
が含まれません。
$ munin-run cpu config | grep host_name
この場合は munin-node
そのものの名前になるのですが、その値は /etc/munin/munin-node.conf
で指定されています。
host_name localhost.localdomain
もし未設定なら自動的にローカルホストの名前が解釈されます。
Munin マスターが munin-node から取得するデータのホスト名
Munin マスターの設定ファイルで次のように設定したとします。
[localhost] address 127.0.0.1 use_node_name yes [example;web.example.com] address 192.168.33.10 use_node_name yes [example;web-by-snmp] address 127.0.0.1
角括弧 [...]
で指定しているものは、Munin の Web 画面で表示されるグループ名やホスト名です。
address
で指定しているものは、Munin マスターが接続する munin-node
のアドレスです。
munin-node
は複数のホストの情報を提供するので、Munin マスターが Munin ノードに接続した後、どのホストの情報が欲しいのかを指定する必要があります。
デフォルトでは角括弧 [...]
で指定しているホスト名(セミコロン ;
の右側)ですが、use_node_name yes
の場合は munin-node
への接続時に munin-node
が名乗った名前をそのまま使います。
なので、
[localhost] address 127.0.0.1 use_node_name yes
127.0.0.1
の munin-node
に接続して、munin-node
が名乗ったホスト名のデータを取得します。
取得したデータは localhost
グループの localhost
のものとして記録されます。
[example;web.example.com] address 192.168.33.10 use_node_name yes
192.168.33.10
の munin-node
に接続して、munin-node
が名乗ったホスト名のデータを取得します。
取得したデータは example
グループの web.example.com
のものとして記録されます。
[example;web-by-snmp] address 127.0.0.1
127.0.0.1
の munin-node
に接続して、web-by-snmp
のデータを取得します。
取得したデータは example
グループの web-by-snmp
のものとして記録されます。
参考になるリンク
- http://munin-monitoring.org/
- Munin の公式サイト
- http://munin.readthedocs.org/en/latest/
- Munin Guide
- http://gallery.munin-monitoring.org/
- プラグインのギャラリー