冗談はさておき、久々に Munin を調べたのですが、みんなプラグインを書いて満足してるようなので、体力勝負で割りとガチで解説してみます。
Muninとはいえ人の子なので、運用面などについてもソースコードから紐解いてみました。
ちゃんとMuninの動作しってる人、どれだけ居るんだろ?
事前準備
ここでは、CentOS6のAMIにepelリポジトリをインストールし、そこからmuninをインストールします。
まず、CentOS6系のAMIを適宜用意します。
この際、謝罪(SELinux)、武装解除(iptables, ip6tables)、及び更新(yum update)を済ませておいてください。
EPELリポジトリをインストールします。CentOS6系の場合、el6のrpmをインストールします。
EPEL – FedoraProject
尚、以下のコマンドを実行すると、明示的に指定(--enablerepo=epel
)されない限り、epelリポジトリを参照しなくなります。
# mv /etc/yum.repos.d/epel.repo /etc/yum.repos.d/epel.repo.orig # cat /etc/yum.repos.d/epel.repo.orig | sed -e "s/enabled=1/enabled=0/" | tee /etc/yum.repos.d/epel.repo
今回はソースコードを軽く読む事が目的なので、とりあえず本体をインストールします。
もしWebUIを観たい場合は、事前にApacheをインストール・設定しておきます。
# yum --enablerepo=epel install munin munin-node -y
Muninの起動と処理のフロー
詳細は後ほど解説しました、Munin全体は以下の図のように、cronによりキックされ、munin-cronにより順番にスクリプトが実行されます。
また、エージェントとしてmunin-nodeを監視対象へインストールし、デフォルトで4949/tcpをLISTENします。
Munin設定ファイル
munin.confは、以下のファイル、及びサブディレクトリを使用します。
# less /etc/munin/munin.conf (snip) # (Exactly one) directory to include all files from. includedir /etc/munin/conf.d
次に、Configファイルには以下のようにホストを定義します。
Groupsの定義については、munin-updateにて紹介します。
[localhost] address 127.0.0.1 use_node_name yes
CRONによる起動
munin-cronは、以下のcronファイルより5分毎にコールされます。
5分より短くする事も可能ですが、RRD Toolsが5分毎に描画するよう設定されている為、特に意味を成しません。
# ls -lah /etc/cron.d | grep munin -rw-r--r-- 1 root root 113 2014-10-26 15:22 munin # cat /etc/cron.d/munin */5 * * * * munin test -x /usr/bin/munin-cron && /usr/bin/munin-cron
munin-cron
munin-cronの実体はShellScriptであり、/usr/bin以下に配置されています。
# ls -lah /usr/bin | grep munin -rwxr-xr-x 1 root root 4.2K 2014-10-26 15:22 munin-check -rwxr-xr-x 1 root root 650 2014-10-26 15:21 munin-cron -rwxr-xr-x 1 root root 3.2K 2014-10-26 15:21 munindoc # cat munin-cron | grep -v ^# /usr/share/munin/munin-update $@ || exit 1 /***-> Configのロードと新規ノード・プラグインのチェック、及びRRDへの反映 ***/ /usr/share/munin/munin-limits $@ /*** -> munin-htmlの為の値チェック ***/ nice /usr/share/munin/munin-html $@ || exit 1 /*** -> HTML生成 ***/ nice /usr/share/munin/munin-graph --cron $@ || exit 1 /*** -> RRDからのグラフ生成 ***/
このスクリプトのポイントは2点です。
- 負荷の高いmunin-html、munin-graphについては、明示的にプロセスの優先順位を下げる為、niceコマンドが用いられる。
- 各スクリプトが異常終了した場合でも、munin-cronは正常終了してしまう為、「|| exit 1」により明示的に異常終了及び戻り値を定義している。
また、munin-cronを手でコールした際に引数を引き渡せるようにもなっています。
munin-update
munin-updateの実体はPerlScriptであり、Configファイルのパースと初期化、及びmunin-nodeから値の取得を行います。
# less /usr/share/munin/munin-update use Munin::Master::Update; use Munin::Master::Config; (snip) sub main { exit_if_run_by_super_user(); configure(); (snip) sub configure { $config->parse_config_from_file($f); }
上記のようにPerlModule及びメソッドがコールされていますが、これらは全て以下のディレクトリに格納されています。
/usr/share/perl5/vendor_perl/Munin/
Configファイルのパース部分のコメントを読むと、以下のように定義ができるようです。
また、ここではValidateを行っておらず、Configファイルをロードする際に各スクリプトでValidateを行っているようです。
sub _split_config_line { # Group;address # Group;Group;address # Group;Host:address # Group;Host:if_eth0.in.value # Group;Host:snmp_foo_if_input.snmp_foo_if_input_0.value # Now left with (1:1 with cases above) # address # address # Host:address # Host:if_eth0.in.value # Host:snmp_foo_if_input.snmp_foo_if_input_0.value }
munin-limit
munin-htmlの為の値チェックのようです。munin-graphには関係しません。
スクリプトのコメントには、以下のようにあります。
# less /usr/share/munin/munin-limits munin-limits - A program to check for any off-limit values
munin-html
munin-htmlは、出力先ディレクトリに表示用のHTMLを生成します。実体は同じくPerlScriptです。
シンプルかつ小さなコードですが、生成するページが多い為多重ループが多く、先のniceコマンドからも全体的に重たいスクリプトである事が伺えます。
munin-graph
munin-graphは、出力先ディレクトリに表示用のグラフ画像を生成します。実体は同じくPerlScriptです。
実装としては小さくシンプルで、munin-updateが生成したRRDファイルを、RRD Toolをコールして描画します。
RRD Toolのパラメータの定義はmunin-updateが担っており、munin-node経由でプラグインへ初回アクセスした際、及び描画する値(カラム)が増えた際に更新されます。
よって、munin-graphは純粋にRRD Toolをコールし、グラフ画像を所定のディレクトリに出力するのみです。
muninのロックファイル
muninは5分毎に定期的にコールされますが、値のポーリング及び描画等で実行時間が5分を超える場合があります。
このため、/var/run/munin以下にロックファイルが出力されます。
但し、何かの手違いでmuninを殺してしまった場合(他殺)、ロックファイルが残りデッドロックとなります。
この際、/var/run/munin以下のファイルを削除する事で復活します。
muninの実行権限
muninは全体的にmunin専用ユーザで動作しています。
epelリポジトリからインストールした場合、以下のように設定されていました。
# cat /etc/group | grep munin munin:x:499: # cat /etc/passwd | grep munin munin:x:498:499:Munin user:/var/lib/munin:/sbin/nologin
また、munin-updateに以下のような定義があり、rootで実行する事は許されていません。
sub main { exit_if_run_by_super_user(); }
この関数が実行された場合、以下のコメントが表示され異常終了します。
This program will easily break if you run it as root as you are trying now. Please run it as user 'nobody'. The correct 'su' command on many systems is 'su - munin --shell=/bin/bash' Aborting.
また、仮にrootで実行できた場合、RRDファイルなどのパーミッションが変わってしまい、muninユーザから上書きする事ができなくなります。
(過去にやっちゃいました。テヘペロ☆)
Munin-node
Munin-nodeとは、監視対象へインストールするエージェントとなります。
実装は同じくPerlScriptですが、4949/tcpをオープンする為、注意が必要です。
尚、ポート及び簡易的なACLを、Configファイルで定義可能です。
プロトコル及び実装
MuninとMunin-nodeは、暗号化されていない独自のプロトコルを用いて、複数のプラグインを1セッションでconfig, fetch通信します。
よって、telnet及びncコマンドで手で操作する事が可能です。
以下、munin-nodeにtelnetでアクセスし、cpuプラグインのconfig及びfetchを行った例です。
# telnet localhost 4949 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. # munin node at localhost.localdomain # Unknown command. Try cap, list, nodes, config, fetch, version or quit list cpu df df_inode entropy forks fw_conntrack fw_forwarded_local fw_packets if_err_eth0 if_eth0 interrupts irqstats load memory netstat open_files open_inodes postfix_mailqueue postfix_mailvolume proc_pri processes swap threads uptime users vmstat config cpu graph_title CPU usage graph_order system user nice idle iowait irq softirq graph_args --base 1000 -r --lower-limit 0 --upper-limit 100 graph_vlabel % graph_scale no graph_info This graph shows how CPU time is spent. graph_category system graph_period second system.label system system.draw AREA system.min 0 system.type DERIVE system.info CPU time spent by the kernel in system activities user.label user user.draw STACK user.min 0 user.type DERIVE user.info CPU time spent by normal programs and daemons nice.label nice nice.draw STACK nice.min 0 nice.type DERIVE nice.info CPU time spent by nice(1)d programs idle.label idle idle.draw STACK idle.min 0 idle.type DERIVE idle.info Idle CPU time iowait.label iowait iowait.draw STACK iowait.min 0 iowait.type DERIVE iowait.info CPU time spent waiting for I/O operations to finish when there is nothing else to do. irq.label irq irq.draw STACK irq.min 0 irq.type DERIVE irq.info CPU time spent handling interrupts softirq.label softirq softirq.draw STACK softirq.min 0 softirq.type DERIVE softirq.info CPU time spent handling "batched" interrupts steal.label steal steal.draw STACK steal.min 0 steal.type DERIVE steal.info The time that a virtual CPU had runnable tasks, but the virtual CPU itself was not running guest.label guest guest.draw STACK guest.min 0 guest.type DERIVE guest.info The time spent running a virtual CPU for guest operating systems under the control of the Linux kernel. . fetch cpu user.value 4118 nice.value 1598 system.value 5319 idle.value 510449 iowait.value 2031 irq.value 0 softirq.value 2 steal.value 1660 guest.value 0 . quit Connection closed by foreign host.
プラグインの実装
munin-nodeは、4949/tcpでmuninからのアクセスを待った上で、コマンドに応じ、各プラグインをコールし標準出力をmuninに戻します。
よって、プラグインはソケット通信を意識する必要はありません。
標準入出力を扱うことができ、先のプロトコルに準ずるアウトプットをするのであれば、特に言語を問いません。
実際、自分の場合ShellScriptやPHP Scriptでプラグインを実装する事が多いです。
プラグインの実装方法については、こちらのエントリに詳しく書かれていますので、参照してください。
muninプラグインを作成 – SEEDS BLOG
昔(2007年頃)は情報も少なく、Muninも流行り始めだったので、自分で試行錯誤した覚えがあります。
プラグインのデバッグ
プラグインのデバッグには、プラグインを単体で実行するmuninコマンドが用意されています。
ここではmunin-runコマンドを用いて、cpuプラグインをデバッグしてみます。
# munin-run cpu autoconf yes # munin-run cpu config graph_title CPU usage graph_order system user nice idle iowait irq softirq graph_args --base 1000 -r --lower-limit 0 --upper-limit 100 graph_vlabel % graph_scale no graph_info This graph shows how CPU time is spent. graph_category system graph_period second system.label system system.draw AREA system.min 0 system.type DERIVE system.info CPU time spent by the kernel in system activities user.label user user.draw STACK user.min 0 user.type DERIVE user.info CPU time spent by normal programs and daemons nice.label nice nice.draw STACK nice.min 0 nice.type DERIVE nice.info CPU time spent by nice(1)d programs idle.label idle idle.draw STACK idle.min 0 idle.type DERIVE idle.info Idle CPU time iowait.label iowait iowait.draw STACK iowait.min 0 iowait.type DERIVE iowait.info CPU time spent waiting for I/O operations to finish when there is nothing else to do. irq.label irq irq.draw STACK irq.min 0 irq.type DERIVE irq.info CPU time spent handling interrupts softirq.label softirq softirq.draw STACK softirq.min 0 softirq.type DERIVE softirq.info CPU time spent handling "batched" interrupts steal.label steal steal.draw STACK steal.min 0 steal.type DERIVE steal.info The time that a virtual CPU had runnable tasks, but the virtual CPU itself was not running guest.label guest guest.draw STACK guest.min 0 guest.type DERIVE guest.info The time spent running a virtual CPU for guest operating systems under the control of the Linux kernel. # munin-run cpu user.value 4423 nice.value 2568 system.value 5571 idle.value 550230 iowait.value 2155 irq.value 0 softirq.value 2 steal.value 1795 guest.value 0
おわりに
Muninと言えば@zembutsuさんですよね。
かくなる僕も、@zembutsuさんだと思います。
そして、恐らく日本でMuninエバンジェリストと言えば、@zembutsuさんです。
なので、ミスターMuninと言えば@zembutuさんだと思います。
…とはいえ、僕も一時期より使う頻度は落ちましたが(そもそも皆んな監視してくれてるのであまり困ってない。あと冗長化されてて困ってない。)、MRTGのように設定が面倒だったり、HinemosやZABBIXのように大それたソリューションを入れるのであれば、やっぱMuninかなぁ、と思いますはい。
あ、通知エージェントざびたんは別ですよ?(一応、初代のパッチコミッターしてました。。。)
元記事はこちらです。
「Munin徹底入門〜ねぇMunin、ソース頂戴♡〜 – みからぼ。」