b.l0g.jp     About     Archive     Feed

Nagiosのプラグイン作成や設定ファイル操作にpynagが超便利!

Nagiosの設定ファイルをパースする簡単な方法ないかなと思って調べてたら、pynagという超便利なパッケージ発見。日本語の情報ほとんどないけど、Fedoraの標準パッケージになっているってことは割と一般的なんだろうか。

  • Nagiosのプラグインを簡単に作りたい
  • Nagiosの設定ファイルをパースして値を取りたい
  • Nagiosの設定をコマンドラインやプログラムから取得・変更したい

って時に重宝する。pynagという名の通り、pythonで書かれている。公式ページのそのまんま訳に近いけど、使い方ご紹介。

インストール

Fedoraの最近のバージョンには標準で含まれており、CentOSやRHELならepelを使えるようにしておけばyumでインストールできる。

  
$ sudo yum install http://ftp-srv2.kddilabs.jp/Linux/distributions/fedora/epel/6/x86_64/epel-release-6-8.noarch.rpm
  
$ sudo yum install pynag
  

pipが使えるならpipでもインストールできる。

  
$ sudo pip install pynag
  

設定ファイルのパース

pynagパッケージのModelモジュールを使えば、 /etc/nagios など代表的なパスから nagios.cfg を探し出して読み込んでくれる。含まれるホストとそのホストに関連づいたContact groupを表示する例。

  
from pynag import Model

# Get all hosts
  
all_hosts = Model.Host.objects.all
  
for i in all_hosts:
      
print i.host_name, i.contact_groups
  

設定書き換え

同じようにして、設定を保存することもできる。ホスト名がexamplehostのホストのContact groupを「mycontactgroup」にする例。

  
from pynag import Model

services = Model.Service.objects.filter(host_name='examplehost')
  
for i in services:
    
i.contactgroups = "mycontactgroup"
    
i.save()
  

ステータスの取得

監視結果が保存されているstatus.datファイルのパースもしてくれるので、ホストやサービスのステータス取得もできる。

ホストグループ名とサービス名を引数に与えてやると、ホストグループに所属するホスト全てに関するサービスのステータスを返すスクリプト。

  
import sys
  
from pynag import Model
  
from pynag.Parsers import status

argvs = sys.argv
  
argc = len(argvs)
  
status = status()

if (argc != 3):
          
print
          
print("Usage: ./%s hostgroup service" % argvs[0])
          
print
          
sys.exit()

hostgroups = Model.Hostgroup.objects.filter(hostgroup_name=argvs[1])
  
for hostgroup in hostgroups:
          
print("Hostgroup: %s" % hostgroup.hostgroup_name)
          
print("Member:")
          
for host in hostgroup.members.split(','):
                  
print("%s %s" % (host, status.get_servicestatus(host, argvs[2])['current_state']))
  

status.datのパースにはやや時間がかかるので、監視対象サーバの台数が多いと使用に耐えない。そういう場合は、高速にステータスを取得できるMK Livestatusと組み合わせることもできる。インストール方法は割愛するのでWebページを参照するべし。MK Livestatusを使って、上のスクリプトと同じようにホストグループとサービス名を引数に与えてホストのステータスを取得する例。


import sys
  
from pynag import Model
  
from pynag.Parsers import mk_livestatus

argvs = sys.argv
  
argc = len(argvs)
  
livestatus = mk_livestatus()

if (argc != 3):
          
print
          
print("Usage: ./%s hostgroup service" % argvs[0])
          
print
          
sys.exit()

hostgroups = Model.Hostgroup.objects.filter(hostgroup_name=argvs[1])
  
for hostgroup in hostgroups:
          
print("Hostgroup: %s" % hostgroup.hostgroup_name)
          
print("Member:")
          
for host in hostgroup.members.split(','):
                  
print(host)
                  
print(livestatus.get_service(host,argvs[2])['host_services_with_info'])
  

コマンドラインから使う

Pythonのスクリプト内だけでなく、pynagコマンドとしてシェルから直接使うこともできる。where句で対象を絞ることが可能。

全ホストオブジェクトを表示する例。

  
$ pynag list where object_type=host
  
object_type shortname filename
  
——————————————————————————-
  
host server01 /etc/nagios/Default_collector/hosts.cfg
  
host server02 /etc/nagios/Default_collector/hosts.cfg
  
(中略)
  
———-123 objects matches search condition———————————-
  

MySQL_Connect_cというサービスのチェックコマンドを表示する例。

  
$ pynag list effective_command_line where service_description=MySQL_Connect_c
  
effective_command_line
  
——————————————————————————-
  
/usr/lib64/nagios/plugins/check_mysql_health -hostname -user nagios -password nagios -mode connection-time -database test -critical 1
  
———-1 objects matches search condition————————————
  

もちろんコマンドラインから設定の変更も可能。ホスト名server01をserver02に変更する例。

  
$ pynag update set host_name=server02 where host_name=server01 and object_type=host
  

where句にはlikeのような部分一致が使えないようだ。複雑なクエリを発行したいときは、pythonスクリプトとして作った方がいいかもしれない。コマンドラインでの使い方はWikiにもう少し詳しく書いてある。

Nagiosプラグイン作成時に使う

個人的に一番ツボなのがこの機能。自作のプラグインに、Nagiosのプラグインを書く際のガイドラインに準じた引数の処理などを簡単に加えることができる。

/proc/loadavgの中身から、ロードアベレージを引いてくる簡単な例。

  
#!/usr/bin/python
  
import os,sys

## プラグインのオプションを生成
  
np = Plugin()

## コマンドライン引数を追加
  
np.add_arg("l","load-file", "Enter a load average file", required=None)

## プラグインをアクティベート
  
np.activate()

## load-fileオプションが指定されたらそのファイルからLAを読み込む
  
## デバッグと、add_argメソッドのサンプルとして
  
if np['load-file']:
      
load_file = np['load-file']
  
else:
      
load_file = "/proc/loadavg"

## ちょっとしたエラーチェック
  
if not os.path.isfile(load_file):
      
np.nagios_exit(np.UNKNOWN, "Missing Load average file %s" % load_file)

## チェックに使う値を取得
  
current_load = os.popen("cat %s" % load_file).readline().split()[0]

## パフォーマンスデータを付加
  
np.add_perfdata("1min", current_load)

## チェック実行
  
np.check_range(current_load)
  

上のスクリプトをcheck_cpu.pyとして保存しておく。5行目のPlugin()で、プラグインとして必要なオプションが用意されるので、以下のようにスクリプトに引数を指定しないで実行しただけで、簡易ヘルプが表示される。

  
$ ./check_load.py
  
usage: check_load.py [options]

check_load.py: error: You must provide a WARNING and/or CRITICAL value
  

さらに、-hオプションをつけると、詳細なヘルプが表示される。

  
$ ./check_load.py -h
  
usage: check_load.py [options]

options:
    
-h, -help show this help message and exit
    
-l LOAD-FILE, -load-file=LOAD-FILE
                          
Enter a load average file
    
-v VERBOSE, -verbose=VERBOSE
                          
Verbosity Level
    
-H HOST, -host=HOST Target Host
    
-t TIMEOUT, -timeout=TIMEOUT
                          
Connection Timeout
    
-c CRITICAL, -critical=CRITICAL
                          
Critical Threshhold
    
-w WARNING, -warning=WARNING
                          
Warn Threshhold
  

ここで、スクリプト内の8行目、add_argメソッドで追加したオプションが、ヘルプの中に「-l LOAD-FILE, -load-file=LOAD-FILE」として表示されている。また、-Hでの監視対象ホスト指定や-c,-wによる閾値の指定オプションがはじめから用意されていることがわかる。自作スクリプトを書くたびにオプションのパースから書いていた事を考えれば、なんという簡単さ!

もちろん、ヘルプでみたとおりのオプションを与えてやれば、プラグインとして使用可能。

  
$ uptime
   
13:16:19 up 396 days, 22:32, 3 users, load average: 0.60, 1.08, 1.04

$ ./check_load.py -w 1 127.0.0.1
  
OK: 0.60 is inside warning=1 and critical=None | '1min'=0.60;;;;
  

元々やりたかったのは「同一ホストグループ内のある台数のチェック失敗まではWARNING、その台数以上のチェック失敗でCRITICALアラートを上げたい」ということだったのだが、以下のような短いプラグインスクリプトで実現できた。

  
#!/usr/bin/python

import sys
  
from pynag import Model
  
from pynag.Parsers import status
  
from pynag.Plugins import simple as Plugin

np = Plugin()
  
status = status()

np.add_arg("g", "hostgroup", "Hostgroup name", required=1)
  
np.add_arg("s", "service", "Service name", required=1)

np.activate()

errornum = 0
  
hostgroups = Model.Hostgroup.objects.filter(hostgroup_name=np['hostgroup'])
  
for hostgroup in hostgroups:
          
for host in hostgroup.members.split(','):
                  
if status.get_servicestatus(host, np['service'])['current_state'] != "0":
                          
errornum = errornum + 1
  
np.add_perfdata("WARN/CRIT", errornum)

np.check_range(errornum)
  

2台のチェックに失敗している時の例。

  
# 2より多いとwarn、3より多いとcrit
  
$ python check_wipeout.py -hostgroup=common_dbs -service=ifSpeed_eth0_w -w 2 -c 3
  
OK: 2 is inside warning=2 and critical=3 | 'WARN/CRIT'=2;;;;

$ echo $?
  


# 1より多いとwarn、3より多いとcrit
  
$ python check_wipeout.py -hostgroup=common_dbs -service=ifSpeed_eth0_w -w 1 -c 3
  
WARNING: 2 is outside warning range: 1 | 'WARN/CRIT'=2;;;;

$ echo $?
  
1

# 1より多いとcrit
  
$ python check_wipeout.py -hostgroup=common_dbs -service=ifSpeed_eth0_w -c 1
  
CRITICAL: 2 is outside critical range: 1 | 'WARN/CRIT'=2;;;;
  
$ echo $?
  
2
  

というわけで、pynagがあるとNagiosプラグインを書くのが超簡単になる! pynag万歳!

ドキュメントはGithub上のWikiを見るとよい。Wikiからだと分からない部分も多いが、ソース自体はそれほど複雑ではないので読んでみればわかるのでは。

Nagiosの設定ファイル生成ツールnconfが使いやすいのであーる

Nagiosの設定ファイルを編集するツールには、NagiosQLなどいくつかあるが、あれこれ触ってみた感じnconfがよさげだった。JQueryなどを適宜使って動きは軽快だし、メニューの構成などもストレートで直感的に使えるところがNagiosQLよりも気にいった。

監視の設定はできる限り自動生成するくらいが大規模なシステムでは最近の主流かもしれないが、そこまでの大きさのシステムではない時でも、設定ファイルを手で編集するのはいただけない。Nagiosを使うならとりあえずnconfも一緒に入れて設定すべし。

最新版が2011年で開発が活発でないのは気になるが、基本的な機能は網羅されており不自由は感じないので、しばらく使っている。ってことで、CentOS6.4にNagiosとnconfをインストールして、監視を始めるまでの手順。

Nagiosのインストール

epelリポジトリにNagiosが含まれているので、epelをインストールしてからNagiosと、監視に使うプラグインをインストール。

  
$ sudo yum install http://ftp-srv2.kddilabs.jp/Linux/distributions/fedora/epel/6/x86_64/epel-release-6-8.noarch.rpm
  
$ sudo yum install nagios nagios-plugins
  

Nagiosと一緒に、PHPやPerl、Apacheなども一緒にインストールされる。

  
$ sudo /etc/init.d/nagios start
  
$ sudo /etc/init.d/httpd start
  

NagiosとApacheを起動したら、 http://(サーバのIP)/nagios をブラウザで開いて、ユーザ名 nagiosadmin、パスワード nagiosadmin でログインするとNagios管理画面が開ければNagiosの準備は一旦終わり。

Nagios Core

MySQLのインストール

nconfの特徴として、設定をMySQLに入れておいて、そこからNagiosの設定ファイルを生成することが挙げられる。そのためにMySQLをインストール。nconfはPHPで書かれており、PHPからMySQLへ接続するためのphp-mysqlも一緒にインストール。

  
$ sudo yum install mysql-server php-mysql
  

mysql, mysql-libsなどもインストールされる。

この辺参照して、/etc/my.cnf の [mysqld] セクションに最低限の設定をしてから、MySQLを起動。

  
$ sudo /etc/init.d/mysqld start
  

nconf用データベースと、MySQLへ接続するためのアカウントも作成。以下の例では、データベース名がnconf、ユーザ名がnconf、パスワードはnconfpasswordとしているが、任意のものにできるので適宜変更すべし。

  
$ mysql -uroot
  
mysql> create database nconf;
  
Query OK, 1 row affected (0.00 sec)

mysql> grant SELECT, INSERT, UPDATE, DELETE, CREATE, ALTER, DROP on nconf.* to 'nconf'@'localhost' identified by 'nconfpassword';
  
Query OK, 0 rows affected (0.00 sec)
  

nconfのインストール

nconfのサイトのDownloadからnconf-1.3.0-0.tgzをダウンロードして適当なディレクトリに配置。CentOSのApacheのDocumentRootに展開する。

  
cd /var/www/html
  
sudo tar zxvf /fuga/hoge/nconf-1.3.0-0.tgz
  
chown -R apache. nconf
  

インストールに必要な設定は、GUIで行える。http://(サーバのIP)/nconf/ をブラウザで開く。

nconf01

ここで画面がforbiddenになる場合、SELinuxが有効になっている可能性がある(/var/log/audit/audit.logにその旨出力されているはずなので確認すべし)。そんな時は頑張って動くように設定するか、そっと/etc/sysconfig/selinuxのSELINUX=enabledをdisabledに書き換えてOSを再起動する。

必須のパッケージが全てインストールされていれば、最初の画面でOKが並ぶので、Nextをクリック。

nconf02

前項でMySQLに作成したデータベース名とアカウントを入力してNextを押すとチェックが走るので、OKが並んだらNext。

nconf03

nconfの接続に認証を必要とするかどうかの設定。後でも変更できるので一旦そのまま(AUTH_ENABLEDがFALSE)でNext。

nconf04

全て完了したらFinishをクリック。

nconf05

インストールしたディレクトリ内のファイル、ディレクトリを削除しろというメッセージが出るので、リネームする(別に使わないと思うが一応)。

  
$ cd /var/www/html/nconf
  
$ sudo mv INSTALL INSTALL.org
  
$ sudo mv INSTALL.php INSTALL.php.org
  
$ sudo mv UPDATE UPDATE.org
  
$ sudo mv UPDATE.php UPDATE.php.org
  

ここまででnconfの設定画面にはアクセスできるようになる。

nconf07

nconfの設定・Nagiosの追加設定

前述の通りnconfはMySQLに設定を書いていて、それをNagiosの設定ファイルとして書き出し、Nagiosを再起動して設定を反映させるところまでnconfでやることができる。そのための追加設定がここから。

/var/www/html/nconf/config/nconf.php (nconfのメイン設定ファイル)を以下の通り書き換え。

23行目。Nagios本体のパスを指定する。

  
\# 変更前
  
define('NAGIOS_BIN', '/var/www/html/nconf/bin/nagios');
  
\# 変更後
  
define('NAGIOS_BIN', '/usr/sbin/nagios');
  

75行目。Nagiosのメイン設定ファイル(nagios.cfg)の構文チェックを無効化。手元の環境では、有効にしてしまうと、正しいはずの設定ファイルのチェックがどうしてもエラーになってしまったのでやむなく。

  
\# 変更前
  
define('CHECK\_STATIC\_SYNTAX', 1);
  
\# 変更後
  
define('CHECK\_STATIC\_SYNTAX', 0);
  

80行目。この配列に入っているユーザが、通知先などに自動で追加されてしまうので削除。

  
\# 変更前
  
$SUPERADMIN_GROUPS = array ("+admins");
  
\# 変更後
  
$SUPERADMIN_GROUPS = array ("");
  

/var/www/html/nconf/config/deployment.ini (nconfの自動デプロイ設定ファイル)を以下の通り書き換え。

「;; LOCAL deployment ;;」の下、6行目から29行目までの以下のセクションの行頭のセミコロンを外して有効化。

  
;[extract config]
  
;[copy collector config]
  
;[copy global config]
  
;[copy nagios.cfg]
  

また、nconfが生成するNagios設定ファイルのアーカイブを指定する、8行目を以下のとおり変更。

  
\# 変更前
  
source_file = "/var/www/nconf/output/NagiosConfig.tgz"
  
\# 変更後
  
source_file = "/var/www/html/nconf/output/NagiosConfig.tgz"
  

Apacheの起動ユーザapacheがNagiosを再起動できるようにsudoersを編集。

  
$ sudo visudo
  

以下の1行を末尾に追加。

  
apache ALL=(ALL)NOPASSWD: /etc/rc.d/init.d/nagios reload
  

nconfが生成した設定ファイルをNagiosの設定ファイルディレクトリ(/etc/nagios)に配置できるように細々した設定。

  
$ cd /etc/nagios
  
$ sudo mkdir Default_collector global
  
$ sudo chown apache. Default_collector global nagios.cfg
  

nconfからnagios.cfgを編集・配置することもできるので、一応nconfのディレクトリ以下にnagios.cfgを置いておく。

  
$ sudo cp /etc/nagios/nagios.cfg /var/www/html/nconf/static_cfg/
  

nconfが配置するファイルを設定ファイルとして使用するように、コピーした先の/var/www/html/nconf/static_cfg/nagios.cfgを編集。

  
\# cfg\_fileとcfg\_dirを全てコメントアウトして以下の2行を追加。

cfg_dir=/etc/nagios/global
  
cfg\_dir=/etc/nagios/Default\_collector
  

これで設定はおしまい。ApacheとNagiosを再起動して一息つく。

  
$ sudo /etc/init.d/httpd stop
  
$ sudo /etc/init.d/nagios restart
  
$ sudo /etc/init.d/httpd start
  

動作確認

http://(サーバのIP)/nagios/ を開いて、左側のCurrent Status → Servicesをクリックすると、Nagios側では以下のようにデフォルトでlocalhostの監視のみが設定されている。

nagios02

一方、 http://(サーバのIP)/nconf/ を開いて、左側のBasic Items → Hostsをクリックすると、nconf側ではlocalhost以外にサンプルとしてhplj2605dnなど合わせて4台分の設定が入っていることが分かる。

nconf08

ここで、nconfの左側のメニューからBasic Items → Generate Nagios configをクリックすると、設定ファイルが生成される。以下の画面で「Deploy」をクリックする。

nconf09

以下の画面のように、全てOKになれば、設定ファイルのデプロイとNagiosの再起動が終わっているはず。

nconf10

ここで、Nagiosの画面を開くと、以下のようにnconfに入っていた設定が有効になって、ホストが増えていれば成功。

nagios03

後は、nconfからあれこれ設定を入れて監視を始めるべし。

IPv6環境でnet-snmpを使う

IPv6環境でSNMPで情報を引っ張ってきたいのだが、net-snmpをインストールしてsnmpdを起動したが、getできない。

監視サーバをnagios01、監視対象ホストをclient01とした時の例。

  
client01$ sudo yum install net-snmp net-snmp-utils
  
client01$ sudo /etc/init.d/snmpd start
  
  
nagios01$ snmpwalk -v 1 -c public client01 UCD-SNMP-MIB::laLoad.1
  
No log handling enabled - turning on stderr logging
  
getaddrinfo: client01 Name or service not known
  
snmpwalk: Unknown host (client01)
  

snmpwalkなどでIPv6のサーバへ問い合わせる場合は、ホスト名の前に「udp6」を明示的に指定する必要があるようだ。しかし、

  
nagios01$ snmpwalk -v 1 -c public udp6:client01 UCD-SNMP-MIB::laLoad.1
  
Timeout: No Response from udp6:client01
  

タイムアウトになってしまう。ちなみに、net-snmpは5.0以降IPv6に対応しているということなので、5.0以降がインストールされていれば、snmpwalkコマンドもIPv6を扱えるはず。

クライアント側を見てみる。

  
client01$ netstat -lanp
  
Active Internet connections (servers and established)
  
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
  
(中略)
  
udp 0 0 0.0.0.0:161 0.0.0.0:* 12403/snmpd
  

0.0.0.0:161ってことは、IPv4だけで、IPv6でリッスンしていない。

設定ファイルを見てみる。

  
client01$ cat /etc/snmp/snmpd.conf
  
(以下抜粋)
  
com2sec notConfigUser localhost public
  
com2sec notConfigUser nagios01 public
  
group notConfigGroup v1 nogConfigUser
  
access notConfigGroup "" any noauth exact systemview none none
  
syslocation Unknown (edit /etc/snmp/snmpd.conf)
  
syscontact Root <root@localhost> (configure /etc/snmp/snmp.local.conf)
  
view all included .1 80
  
dontLogTCPWrappersConnects yes
  

どうやら、デフォルトの設定では、IPv4しかリッスンしない設定らしい。以下のように、明示的にv6でも使えるように追記。

  
\# 以下の4行を追記(下の2行は実際の設定に応じて変更)
  
agentaddress udp:161
  
agentaddress udp6:161

com2sec6 notConfigUser localhost public
  
com2sec6 notConfigUser nagios01 public
  

snmpd を再起動すると、v6でもリッスンするようになった。

  
client01$ sudo /etc/init.d/snmpd restart
  
client01$ netstat -lanp
  
Active Internet connections (servers and established)
  
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
  
(中略)
  
udp 0 0 0.0.0.0:161 0.0.0.0:* 12442/snmpd
  
udp 0 0 :::161 :::* 12442/snmpd
  

これで値を取れるようになった。

  
nagios01$ snmpwalk -v 1 -c public udp6:client01 UCD-SNMP-MIB::laLoad.1
  
UCD-SNMP-MIB::laLoad.1 = STRING: 0.03
  

まとめ

IPv6環境でnet-snmpを使うときは

  • net-snmp 5.0以降を使う
  • snmpd.confで、agentaddress udp6:161とcom2sec6を設定する
  • snmpwalkなどで値を取る時はアドレスの前にudp6:をつける