Ubuntu Weekly Recipe

第359回 Muninでサーバーのリソースを可視化しよう

この記事を読むのに必要な時間:およそ 7.5 分

Native SSH Transport

Webサービスを運用するにあたって,すべてのサーバーをグローバルに晒すということはまずありません。下記の図のように,インターネットから直接アクセスできるのはフロントエンドとなるWebサーバーやリバースプロキシ,ロードバランサーなどのみで,アプリケーションサーバーやデータベースサーバーはローカルな空間に置いて裏で繋ぐ,という構成が一般的でしょう。このような構成の場合,muninサーバーがローカルな空間のmunin-nodeに直接到達できないため,監視することができません。そんなときに役立つのが,Muninのバージョン2系から実装されたNative SSH Transport機能です。これはSSHを利用してフロントエンドのサーバーを踏み台とし,バックエンドのサーバーに接続するための機能です。

図2 SSHを利用してフロントエンドのサーバーを踏み台とし,バックエンドのサーバーに接続する

図2 SSHを利用してフロントエンドのサーバーを踏み台とし,バックエンドのサーバーに接続する

まず,muninサーバーからプロキシとなるmunin-nodeサーバーへ,muninユーザーがパスワードなしでSSH接続できるようにする必要があります。muninサーバー上でmuninユーザーのSSH鍵ペアを生成し,公開鍵をメモしてください。

muninユーザーのSSH鍵ペアの作成

$ sudo -u munin ssh-keygen
$ sudo cat /var/lib/munin/.ssh/id_rsa.pub

次にmunin-nodeサーバー上で,muninユーザーがログインできるよう設定します。デフォルトでmuninユーザーのログインシェルは/bin/falseになっていますので,これをbashに変更します。ホームディレクトリになる/var/lib/muninを作り,そこにSSH公開鍵を設置してください。

munin-nodeサーバー上での,muninユーザーの設定

$ sudo chsh -s /bin/bash munin
$ sudo install -d -m 755 -o munin -g munin /var/lib/munin
$ sudo -u munin -i
$ install -d -m 700 .ssh
$ echo (公開鍵の中身) > authorized_keys
$ chmod 600 authorized_keys

muninサーバーから以下のコマンドを実行して,munin-nodeサーバーにSSH接続ができれば準備は完了です注6⁠。

注6)
初回接続時はホスト鍵の確認と受け入れがあるため,必ず一度は手動でSSH接続しておいてください(SSHのStrictHostKeyCheckingについての解説は省略します⁠⁠。

muninサーバーからmunin-nodeサーバーへSSH接続する

$ sudo -u munin ssh 153.120.xxx.xxx

あとはmuninサーバーの/etc/munin/munin.confに,以下のようにデータベースサーバーを監視対象として登録するだけです。これでまずmunin-nodeサーバーへSSH接続し,そこでncコマンドを起動し,データベースサーバーへ接続することが可能になりました注7⁠。

注7)
SSHの多段接続でProxyCommandを指定するのとだいたい同じです。

SSH Native Transportを利用した監視設定例

[Ubuntu;database.example.com]
    address ssh://(踏み台サーバーのIPアドレス)/bin/nc (対象のローカルIPアドレス) 4949
    use_node_name yes

プラグインを自作する

Muninのプラグインは,Muninの望むフォーマットに従って文字列を出力するだけ注8です。そしてプラグインを自作すれば,数値化できるものならなんでもMuninでグラフ化することが可能です。最近はメールやTwitterにデータを送れる体重計がありますので,体重や体脂肪率を記録して,閾値を越えたらアラートを出すなんてこともできそうです注9⁠。スマートフォンの歩数計アプリを使って,毎日の歩いた歩数を記録してみるのも良いでしょう。

注8)
乱暴に言ってしまえば,⁠プラグイン名.value」に続いて数値を出力するだけです。How to write Munin pluginsが参考になります。また最終的な出力さえ正しければ,内部は好きな言語で実装して構いません。筆者の印象ですが,世間ではシェルスクリプトや(Munin本体と同じ)Perlが使われることが多いようです。
注9)
そういうリッチな機能を持っているヘルスメーターには,標準でグラフ化サービスがメーカーから提供されている,という意見もあるかもしれません。しかし体重というセンシティブな個人情報を第三者に預けるというリスクを考えると,自前でのホスティングも検討の余地があるのではないでしょうか。

私事ですが,筆者は昨年秋,北海道に移住しました。はじめての北海道の冬,やはり気になるのはその寒さです。そこでUSB温度計を使い,室温を記録してみることにしました注10⁠。

注10)
室温を計測するため,ここからはクラウドのサーバーではなく,自室に設置したCubox-i4上のUbuntu 14.04を使って構築しています。消費電力を考えARMマシンを利用していますが,一般的なPCでも設定内容は同じですのでご安心ください。

コマンドラインから温度を取得するプログラムはGitHubで公開されています。しかしこのプログラムは,出力時の時刻がGMTでハードコーディングされているうえ,フォーマットも日本式ではありません。この問題を修正した日本向けのforkがありますので,今回はこのリポジトリを利用しました注11⁠。

注11)
日時はMuninが勝手に記録するため,temperコマンドの出力する日時はプラグイン内で切り捨てています。ですのでこの問題は無視しても構いません。

READMEに従い,コンパイルとインストールを行います。単純なプログラムですので,特にハマる部分はないでしょう。USB温度計から温度を読み取るにはroot権限が必要なのですが,それでは都合が悪いため,udevのルールを変更してmuninユーザーから読み取れるようにします。/etc/udev/rules.d/60-temper.rulesというファイルを作成し,リストの内容を記述してください注12⁠。温度計を挿抜しなおせば,muninユーザーから読み取れるようになっています注13⁠。

注12)
サンプルがソースコードに同梱されていますので,それのGROUPの部分を書き換えてください。
注13)
ここではmuninグループに権限を与えてしまいましたが,サンプル通りにtemperグループを作成し,muninユーザーをグループに追加する方がスマートかもしれません。

Muninプラグインは,リストの内容を/etc/munin/plugins/temperとして作成しました。シンボリックリンクでなくシェルスクリプトそのものを/etc以下に配置してしまっていますが,ここでしか使わない自作プラグインなので良しとしておきます。シェルスクリプトですので,実行権限を付けておくのを忘れないようにしましょう。あとはmunin-nodeを再起動し,munin-runやtelnet経由でtemperプラグインを叩き,⁠temper.value 17.023663」のような出力が得られれば成功です。5分待ってから,Web画面でグラフが描画されていることを確認しましょう。

muninユーザーが温度計にアクセスできるよう,udevのルールを設定する

# TEMPer1 USB thermometer
ATTR{idVendor}=="1130", ATTR{idProduct}=="660c", OWNER="root", GROUP="munin", MODE="0660"
ATTR{idVendor}=="0c45", ATTR{idProduct}=="7401", OWNER="root", GROUP="munin", MODE="0660"

コンパイルしたtemperコマンドで温度を取得できるか確認する

$ sudo -u munin /usr/local/bin/temper
2015-01-12 13:04:35,18.180950

Munin用temperプラグイン

#!/bin/sh

if [ "$1" = "autoconf" ]; then
    if [ -x /usr/local/bin/temper ]; then
        echo yes
        exit 0
    else
        echo no
        exit 1
    fi
fi

if [ "$1" = "config" ]; then
    echo 'graph_title Room Temperature'
    echo 'graph_vlabel Temp'
    echo 'graph_category Temper'
    echo 'temper.label Temp'
    echo 'temper.warning 20'
    echo 'temper.critical 26'
    echo 'temper.info Room Temperature'
    exit 0
fi

echo -n "temper.value "
/usr/local/bin/temper | cut -d',' -f2

図3 室温を記録した結果

図3 室温を記録した結果

著者プロフィール

水野源(みずのはじめ)

Ubuntu Japanese Teamメンバー。理想のフリーデスクトップ環境を求めて東へ西へ……のはずが,気がついたら北の大地で就職していたインフラ寄りのエンジニア。最近レンズ沼にハマる。