[技術ブログvol.26] Muninで80と443を監視するのは一筋縄ではいかない

はじめに

Muninをお使いの皆様、これからお使いの皆様、こんにちは。
Muninって、手軽に入れられて、でも色々なグラフを取ってくれて非常に助かりますよね。
導入が手軽すぎて、技術的に面白くない!なんて方も中にはいらっしゃるのではないでしょうか。
かく言う私も、ある機会に初めてMuninを導入することとなり、そんな風に思いながら構築した経験があるのですが、その時クライアントからある提案がありました。

「80と443ポート、両方を監視してくれ」

ある程度仕組みを理解していた私は、「ハッ、plugin-conf.dに"env.ports 80 443"とでもかけばいいんでしょ?」と軽く考え、そしてGoogle先生も大方それに同意でした。

しかし...

非情なことに、これでは両方の値は取れません。グラフを見れば明らかです。

ちーん...    ちーん...

ここでは、何故取れないかについてを詳しくお話したいと思います。

と、その前に

理解を深めて頂くため、まずはMuninの概要とインストール方法について軽く触れましょう。
不要な方は、本題にジャンプ

Muninとは

Munin Wikipediaでの説明

フギン (古ノルド語: Huginn, 英: Hugin) とムニン (古ノルド語: Muninn, 英: Munin) は、北欧神話に登場する神オーディンに付き添う一対のワタリガラス。フギンは「思考」を、ムニンは「記憶」を意味する。フギンはアイスランド語の hugsun (考え)に対応する。

オーディンに付き添うカラスだそうです。
そっちかよ!と突っ込みが入りそうですが、決してふざけてはおらず、名前の由来を知ることは重要なことだと私は考えます。
Muninを既にお使いの方は、なるほど!と思ったことでしょう。

ここで触れるMuninとは、もちろんこちらの方です。

munin.png

Muninは自機及び他機のリソース情報を定期的にモニタリングし、蓄積した情報を基にグラフを生成、WEBコンテンツとして組み込みまでしてくれる便利ツールです。
NagiosやZabbixを導入するより、かなり楽に導入できます。

Muninのインストール方法

では、インストール方法を紹介します。
一般的な使われ方としてはクライアント-サーバモデルで動かしますが、ここではミニマムに自機のモニタリングのみ設定します。
※WEBサーバとしてApache+mod_ssl環境が構築済みであることを前提としています

Epelレポジトリをインストール
yum install epel-release
yumコマンドでmuninをインストール
yum install munin --enablerepo=epel
※munin,munin-node,rrdtoolやperlモジュールが同時にもりっと入ります

以上!

Muninのセットアップ

インストールすると、主に以下が設置されます

  • グラフ閲覧用WEBコンテンツ(/var/www/html/munin)
  • 設定ファイル(/etc/httpd/conf.d/munin.conf , /etc/munin/*)
  • 監視やグラフ生成間隔の設定ファイル(/etc/cron.d/munin)
  • デフォルトで入るプラグイン達(/usr/share/munin/plugins/*)

この状態でApacheを再起動すると正常に起動しますが、基本認証のユーザ設定をしないままだとアクセスできないため設定します。

/etc/init.d/httpd restart
htpasswd -c /etc/munin/munin-htpasswd munin

バーチャルホストを設定している場合は、Aliasを設定するか、/var/www/html/muninディレクトリを移動させる等で調整する必要があるので注意。

デフォルトでかなり多岐に渡るグラフを取っていますが、今回は必要無いためApache関連のプラグイン(各監視プログラムのこと)のみ設定します。

rm -f /etc/munin/plugins/*
ln -s /usr/share/munin/plugins/apache_accesses /etc/munin/plugins/apache_accesses
ln -s /usr/share/munin/plugins/apache_processes /etc/munin/plugins/apache_processes
ln -s /usr/share/munin/plugins/apache_volume /etc/munin/plugins/apache_volume
※デフォルトで用意されているプラグインと/etc/munin/plugins配下にリンクを張るだけで、
有効/無効を切り替えることができます

/etc/init.d/munin-node restart

これらデフォルトで用意されているapache_*シリーズのプラグインは、Apacheのmod_statusの値を取得するよう設計されているため、mod_statusを有効する必要があります。

vi /etc/httpd/conf/httpd.conf
------------------------------------
server-statusで検索しながら...

ExtendedStatus Off ←Onに変更

...

↓コメントアウトを外す
#<Location /server-status>
# SetHandler server-status
# Order deny,allow
# Deny from all
# Allow from 127.0.0.1
Allow from "クライアントPCのIPアドレス" ←追記
#</Location>
------------------------------------

/etc/init.d/httpd restart

あとは、グラフが描画されるまで待ち、ブラウザからMuninのグラフ閲覧ページにアクセスすればOKです。

ここから本題!

冒頭で触れました、80番と443番を両方監視する件についてお話ししていきます。

Muninには、プラグインで使用する変数を明示的に設定する領域として、/etc/munin/plugin-conf.dというディレクトリがあり、以下のように設定することで変数が適用されます。

vi /etc/munin/plugin-conf.d/apache
------------------------------------
[apache*]
env.ports 80 443
------------------------------------

/etc/init.d/munin-node restart

[apache*]と書いて、先ほどリンクを張ったapacheうんたらのプラグインに使う変数であることを宣言し、env.portsには80と443を入れますよと指定しています。

Google先生に師事した場合、大抵は同様の設定を行って運用している方が多いようですが、冒頭の通りこれだけでは無意味です。

なぜ、無意味なのか

例として、apache_accessesをターゲットにしてお話していきます。
ソースを見てみましょう。
autoconfやconfigに関するところは無視し、以下の部分のあたりが実際に監視で使われている領域です。

...
my $URL = exists $ENV{'url'} ? $ENV{'url'} : "http://127.0.0.1:%d/server-status?auto";
my @PORTS = exists $ENV{'ports'} ? split(' ', $ENV{'ports'}) : (80);

...中略

my $ua = LWP::UserAgent->new(timeout => 30,
agent => sprintf("munin/%s (libwww-perl/%s)", $Munin::Common::Defaults::MUNIN_VERSION, $LWP::VERSION));

foreach my $port (@PORTS) {
my $url = sprintf $URL, $port;
my $response = $ua->request(HTTP::Request->new('GET',$url));
if ($response->content =~ /^Total Accesses:s+(.+)$/im) {
print "accesses$port.value $1n";
} else {
print "accesses$port.value Un";
}
}

かいつまんで言うと、以下のURLを見に行く動作をするわけですね。

  • http://127.0.0.1:80/server-status?auto
  • http://127.0.0.1:443/server-status?auto

curlなり、ブラウザなりで実際アクセスしてみればわかりますが、443の方は"Bad Request"等が出たのではないでしょうか。
プロトコルの仕様上、このエラーは避けられません。
そして、これが原因で

munin-run apache_accesses
------------------------------------
accesses80.value 1000
accesses443.value U
------------------------------------

となるわけです。
これじゃグラフ生成するにも値が取れないんで、意味がないですよね。

ではどうするか
my $URL = exists $ENV{'url'} ? $ENV{'url'} : "http://127.0.0.1:%d/server-status?auto";

先ほどのソース中のこの一行を見て、plugin-conf.dに"env.url https~~"と書けば良いのではないか!
と思った方がいらっしゃるかもしれませんが、https://127.0.0.1:80にアクセスすれば、それが適わないことだとわかると思います。

要は、80番で値を取りに行くときはhttpにアクセスし、443番で値を取りに行く時はhttpsにアクセスすれば良いわけです。

私が真っ先に浮かんだのは、プラグインのソースを書き換えて、条件式でhttpとhttpsに振る方法でした。
これで勝てると思い込み、慣れないPHPに苦戦しながら完成させました!

やはり非情

実は、これもダメです。できたつもりでしたが、大きな罠がありました。
論より証拠。わかりやすく、ブラウザで見てみましょう。
二つの窓でそれぞれにアクセスし、交互に更新していくのです。

  • http://"対象サーバのIPアドレス"/server-status?auto
  • https://"対象サーバのIPアドレス"/server-status?auto

おわかりいただけただろうか

先の通り、munin-nodeはmod_statusの値を見に行きます。
バージョンによって異なりますが、ブラウザにはいくつかの文字列と数字が表示されます。
更新しながら交互に見た結果、ここで見られる値はhttpもhttpsも同じ値だということがおわかりいただけたと思います。

そう、どれだけもがこうと、結果見に行くページが同じなのだから、同時に監視する意味なんて無かったのです!
あー時間を無駄にした!なんと非情な!さすが神の付き添い!

さりとて

でも、男にはやらなくちゃならない時がある。
ここまで費やした時間を無駄にもしたくないし、それでも監視しろと指示がある場合もあるでしょう。
なにも私は、無理だ無理だと発信するためにこの記事を書いたわけではないのです。
結論を言うと、80と443を同時に監視する方法はあります。
同時監視は、あります!

しかし、この件については、またその内書く事にしましょう...。

技術ブログ中の人
Next Denet's HIIIINT!...多重化
来月あたりに書くので、乞うご期待。

返信を残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA