ラベル monitor の投稿を表示しています。 すべての投稿を表示
ラベル monitor の投稿を表示しています。 すべての投稿を表示

2012年8月26日日曜日

nagiosで分散監視


目的
nagiosで分散監視を実施する。



簡易構成図
        nagios              ← 中央サーバ(親)
          |      
nagios  nagios  nagios …    ← 集約サーバ群(子)



監視項目、役割
● 中央サーバ(親)
集約サーバ(子)からの通知を受け付ける受動監視に徹する。
親側ではホスト、サービス監視共に能動的に監視をさせないということである。
発報条件として試行回数(Attempt)は1/1にする。


● 集約サーバ(子)
以下を受け持つ。
・能動監視
・受動監視
・TRAP監視(nagiosとの連携方法についてはこちらを参照のこと)

能動監視はnotificationの機能を使い、結果をsend_nscaコマンドで親側へ通知する。

notificationの発動条件(能動、受動、TRAP監視用のテンプレートは別途説明する)。
・ハードエラー時
試行回数を3/3にしておけば、3回目のNG時にnotificationは発動する。
また、復旧時は1/3でnotificationは動作する。

・能動監視時はハードエラーが継続する場合は、
一度アラームがあがったらステータスが変化しない限り通知させない。
検知漏れが怖いなら設定ディフォルトの240分(notification_interval)後に
再通知でもいいだろう。

・受動監視時は試行回数を1/1にしておけば、毎回1回目のNG時にnotificationが発動する。
ステータスが変化しない場合にも発動させる(is_volatileは有効に)。

・HOSTがダウンするとサービス監視は実施されなくなる。
監視が動作しないと慌てないこと。


TRAP監視はnagiosのイベントハンドラ(event_handler)の機能を使い親側へ通知する。
event_handler経由で実行するコマンドは上記と同じくsend_nscaである。
notificationを使わない理由だが、TRAPが複数上がった場合に、
前のアラームが上書きされ、それに気がつかない事態を防ぎたいためである。
TRAP監視のステータスは基本warningとし、warningの状態時に、
再度アラームがTRAPを受けた場合は、ステータスをcriticalとして親側に再通知させる。

イベントハンドラコマンドが実行されるタイミングを確認しておく。
・ソフトエラー状態にある時

・最初にハードエラー状態になった時

・ソフト又はハードエラー状態から復旧する時

ソフトエラーの状態でも実行される点がnotificationと異なる。

サービス名を、TRAP [hoge]、TRAP [piyo]などと分けてもいいのだが、監視対象数は増やしたくない。
nagisoはステータスの管理をデータベースではなくファイルでやっているためである。
TRAPとアラームは一つにし、ステータスのインフォメーションに内容を記載すればいいだろう。



前提
親側、子側に以下のパッケージはインストール済みとする。
・nagios    
・nagios-devel
・nagios-www  
・nagios-plugins
・nagios-nsca ← 分散監視に利用する



親・子nagios共通設定
● /etc/nagios/nagios.cfg
#設定ファイルはconf.d配下に独自に用意する
#cfg_file=/etc/nagios/objects/commands.cfg
#cfg_file=/etc/nagios/objects/contacts.cfg
#cfg_file=/etc/nagios/objects/timeperiods.cfg
#cfg_file=/etc/nagios/objects/templates.cfg
#cfg_file=/etc/nagios/objects/localhost.cfg
cfg_dir=/etc/nagios/conf.d

# ステータスファイルはメモリ上におきIO処理を高速化させる
status_file=/dev/shm/status.dat

# command_fileはディフォルトのままでいいだろうが、変更するなら確認必要
command_file=/var/log/nagios/rw/nagios.cmd


● /etc/nagios/cgi.cfg
# 認証関係の設定
authorized_for_system_information=*
authorized_for_configuration_information=*
authorized_for_system_commands=*
authorized_for_all_services=*
authorized_for_all_hosts=*
authorized_for_all_service_commands=*
authorized_for_all_host_commands=*

# 音声ファイルの設定
host_unreachable_sound=hostdown.wav
host_down_sound=hostdown.wav
service_critical_sound=critical.wav
service_warning_sound=warning.wav
service_unknown_sound=warning.wav
normal_sound=noproblem.wav

# 監視の結果にhtmlタグを出力させる可能性があるためエスケープはしない
escape_html_tags=0


親側nagiosの設定
● /etc/nagios/nagios.cfg
# nagios起動時のサービス確認は親側は不要
execute_service_checks=0

# パッシブホストチェック、パッシブサービスチェックを有効化
# 子側からの通知を受け取るため
accept_passive_service_checks=1
accept_passive_host_checks=1

# 外部コマンドを有効化
# 親、子どちらかだけで外部コマンドを実行できるポリシーにしてもよい
check_external_commands=1


● /etc/nagios/conf.d/base/hosts.cfg
基本となるホストの設定を記載する。
赤色は子側との設定の相違である。
define host {
  name                            nsca-host
  active_checks_enabled           0
  passive_checks_enabled          1
  notifications_enabled           1
  event_handler_enabled           0
  flap_detection_enabled          0
  process_perf_data               0
  retain_status_information       1
  retain_nonstatus_information    1
  check_period                    none
  max_check_attempts              1
  contact_groups                  admins
  notification_options            n
  register                        0
}
check_periodがnoneの理由を補足しておく。
check_freshnessが1ならfreshness_reportが動いてしまう。


● /etc/nagios/conf.d/base/services.cfg
基本となるサービスの設定を記載する
define service{
  name                            nsca-service
  active_checks_enabled           0
  passive_checks_enabled          1
  parallelize_check               1
  obsess_over_service             0
  check_freshness                 0
  notifications_enabled           1
  event_handler_enabled           0
  flap_detection_enabled          0
  process_perf_data               0
  retain_status_information       1
  retain_nonstatus_information    1
  is_volatile                     0
  check_period                    none
  max_check_attempts              1
  contact_groups                  admins
  notification_options            n
  notification_interval           240
  notification_period             24x7
  check_command                   no_report
  register                        0
}


● /etc/nagios/conf.d/service/services.cfg
各種サービスの設定を記載する。
手順の簡略化のため、ホストグループ、ホストの設定ファイルも
ここへあわせて記載する。当然管理のため分けてもよい。
define hostgroup {
  hostgroup_name    frontend_service
  alias             frontend_service
}

define hostgroup {
  hostgroup_name    backend_service
  alias             backend_service
}

define host {
  use           nsca-host
  host_name     host1
  hostgroups    frontend_service
}

define host {
  use           nsca-host
  host_name     host2
  hostgroups    backend_service
}


define service {
  use                    nsca-service
  host_name              host1, host2
  service_description    RESOURCE [load average]
}

define service{
   use                   nsca-service
   host_name             host1, host2
   service_description   PASSIVE [log]
}

define service {
  use                    nsca-service
  host_name              host1, host2
  service_description    TRAP
}


● /etc/nagios/nsca.cfg
子側からの通知を受け付けるデーモンの設定だが、
変更するとしたらポート番号と、nagios.cfgで指定したcommand_fileと
同じ場所を指すようにそこを見直すぐらいだろうか。
server_port=15667

command_file=/var/log/nagios/rw/nagios.cmd



子側nagiosの設定
● /etc/nagios/nagios.cfg
# nagios起動時のサービス確認は子側は必要
execute_service_checks=1

# パッシブホストチェック、パッシブサービスチェックを有効化
# 子側であっても監視対象ノードから受動的に結果を受け取ることがある
accept_passive_service_checks=1
accept_passive_host_checks=1

# 外部コマンドを有効
# 親、子どちらかだけで外部コマンドを実行できるポリシーにしてもよい
check_external_commands=1

# obsess over ホストとサービスは使わない(ディフォルト0)
# obsessを利用した分散環境を作らないため明示的に0としておく
obsess_over_hosts=0
obsess_over_services=0

# ochp(Obsessive Compulsive Host Processor)コマンドは使わない
#ochp_command=somecommand

# ocsp(Obsessive Compulsive Service Processor)コマンドは使わない
#ocsp_command=somecommand



● /etc/nagios/conf.d/base/hosts.cfg
基本となるホストの設定を記載する。
赤色は親側との設定の相違である。
define host {
  name                            active-host
  notifications_enabled           1
  event_handler_enabled           0
  flap_detection_enabled          0
  process_perf_data               0
  retain_status_information       1
  retain_nonstatus_information    1
  check_period                    24x7
  max_check_attempts              3
  normal_check_interval           2
  retry_check_interval            1
  contact_groups                  nscas
  notification_options            d,u,r
  notification_interval           240
  notification_period             24x7
  check_command                   check-host-alive
  register                        0
}


● /etc/nagios/conf.d/base/services.cfg
緑色は子側内の設定との相違点である。
define service {
  name                            active-service
  active_checks_enabled           1
  passive_checks_enabled          1
  parallelize_check               1
  obsess_over_service             0
  check_freshness                 0
  notifications_enabled           1
  event_handler_enabled           0
  flap_detection_enabled          0
  process_perf_data               0
  retain_status_information       1
  retain_nonstatus_information    1
  is_volatile                     0
  check_period                    24x7
  max_check_attempts              3
  normal_check_interval           4
  retry_check_interval            1
  contact_groups                  nscas
  notification_options            u,w,c,r
  notification_interval           240
  notification_period             24x7
  register                        0
}


define service {
  name                            passive-service
  active_checks_enabled           0
  passive_checks_enabled          1
  parallelize_check               1
  obsess_over_service             0
  check_freshness                 0
  notifications_enabled           1
  event_handler_enabled           0
  flap_detection_enabled          0
  process_perf_data               0
  retain_status_information       1
  retain_nonstatus_information    1
  is_volatile                     1
  check_period                    none
  max_check_attempts              1
  normal_check_interval           1
  retry_check_interval            1
  contact_groups                  nscas
  notification_options            u,w,c,r
  notification_interval           240
  notification_period             24x7
  check_command                   check_dummy!0!"OK"
  register                        0
}


define service {
  name                            trap-service
  active_checks_enabled           0
  passive_checks_enabled          1
  parallelize_check               1
  obsess_over_service             0
  check_freshness                 0
  notifications_enabled           1
  event_handler_enabled           1
  flap_detection_enabled          0
  process_perf_data               0
  retain_status_information       1
  retain_nonstatus_information    1
  is_volatile                     1
  check_period                    none
  max_check_attempts              2
  normal_check_interval           1
  retry_check_interval            1
  contact_groups                  nscas
  notification_options            none
  notification_interval           240
  notification_period             24x7
  register                        0
}



● /etc/nagios/conf.d/service/services.cfg
各種サービス固有の設定を記載する
親側での設定と同様に手順の簡略化のため、ホストグループ、ホストの
設定ファイルもここへあわせて記載する。
define hostgroup {
  hostgroup_name    frontend_service
  alias             frontend_service
}

define hostgroup {
  hostgroup_name    backend_service
  alias             backend_service
}


define host {
  use           active-host
  host_name     host1
  address       10.0.0.1
  hostgroups    frontend_service
}

define host {
  use           active-host
  host_name     host2
  address       10.0.0.2
  hostgroups    backend_service
}


define service {
  use                    active-service
  host_name              host1, host2
  service_description    RESOURCE [load average]
  check_command          check_loadaverage!30,30,30!50,50,50
}

define service{
   use                   passive-service
   host_name             host1, host2
   service_description   PASSIVE [log]
   check_command         check_dummy!0!"OK"
}

define service{
   use                   trap-service
   host_name             host1, host2
   service_description   TRAP
   event_handler         notify-service-by-send_nsca_for_trap
   check_command         check_dummy!0!"OK"
}



● /etc/nagios/conf.d/base/contacts.cfg
試行回数をを3/3にしておけば、3回目のNG時にnotificationが発動する。
また、復旧時は1/3でnotificationは動く。
HOSTがダウンするとサービス監視は実施されなくなるため、
監視が動作しないと慌てないこと。
define contact {
  name                             nsca-contact
  service_notification_period      24x7
  host_notification_period         24x7
  service_notification_options     w,u,c,r,f,s
  host_notification_options        d,u,r,f,s
  service_notification_commands    notify-service-by-send_nsca
  host_notification_commands       notify-host-by-send_nsca
  register                         0
}


define contact {
  contact_name    nscaadmin
  use             nsca-contact
  alias           Nsca Admin
}


define contactgroup {
  contactgroup_name    nscas
  alias                Nagios Nacas
  members              nscaadmin
}


● /etc/nagios/conf.d/base/commands.cfg
# for notification
define command {
  command_name    notify-host-by-send_nsca
  command_line    /usr/lib/nagios/plugins/submit_check_result_host $HOSTNAME$ $HOSTSTATEID$ '$HOSTOUTPUT$'
}

define command {
  command_name    notify-service-by-send_nsca
  command_line    /usr/lib/nagios/plugins/submit_check_result_service $HOSTNAME$ '$SERVICEDESC$' $SERVICESTATE$ '$SERVICEOUTPUT$'
}


# for event handler
define command {
  command_name    notify-service-by-send_nsca_for_trap
  command_line    /usr/lib/nagios/plugins/submit_check_result_service_for_trap $HOSTNAME$ '$SERVICEDESC$' $SERVICESTATE$ '$SERVICEOUTPUT$' $SERVICESTATETYPE$
}


【補足】
親側にnagiosではなくOVOを使う場合は、
syslogに結果を吐かせればいいだろう。
define command {
  command_name    notify-host-by-logger
  command_line    /bin/logger -p local6.info "Nagios  `/usr/bin/printf \"%b\" \"[SERVICE NAME] Type: $NOTIFICATIONTYPE$, Host: $HOSTNAME$, State: $HOSTSTATE$, Address: $HOSTADDRESS$, Info: $HOSTOUTPUT$, Date/Time: $LONGDATETIME$\"`"
}

define command {
  command_name    notify-service-by-logger
  command_line    /bin/logger -p local6.info "Nagios  `/usr/bin/printf \"%b\" \"[SERVICE NAME] Type: $NOTIFICATIONTYPE$, Host: $HOSTNAME$, Service: $SERVICEDESC$, State: $SERVICESTATE$, Date/Time: $LONGDATETIME$, Additional Info: $SERVICEOUTPUT$\"`"
}


● /usr/lib/nagios/eventhandlers/submit_check_result_host 
#!/bin/sh
return_code=3

case "$2" in
  UP)
    return_code=0
    ;;
  DOWN)
    return_code=1
    ;;
  UNREACHEBLE)
    return_code=2
    ;;
  UNKNOWN)
    return_code=3
    ;;
esac

#/usr/bin/printf "%s\t%s\t%s\n" "$1" "$2" "$3"  >> /var/tmp/debug_host
/usr/bin/printf "%s\t%s\t%s\n" "$1" "$2" "$3"  | /usr/sbin/send_nsca $親サーバのIPアドレス -c /etc/nagios/send_nsca.cfg

実行権限を与えておくこと。
# chmod 755 /usr/lib/nagios/eventhandlers/submit_check_result_host


● /usr/lib/nagios/eventhandlers/submit_check_result_service
#!/bin/sh
return_code=3

case "$3" in
  OK)
    return_code=0
    ;;
  WARNING)
    return_code=1
    ;;
  CRITICAL)
    return_code=2
    ;;
  UNKNOWN)
    return_code=3
    ;;
esac

#/usr/bin/printf "%s\t%s\t%s\t%s\n" "$1" "$2" "$return_code" "$4" >> /var/tmp/debug_service
/usr/bin/printf "%s\t%s\t%s\t%s\n" "$1" "$2" "$return_code" "$4" | /usr/sbin/send_nsca $親IP -c /etc/nagios/send_nsca.cfg

実行権限を与えておくこと。
# chmod 755 /usr/lib/nagios/eventhandlers/submit_check_result_service


● /usr/lib/nagios/eventhandlers/submit_check_result_service_for_trap
#!/bin/sh
return_code=3

case "$3" in
  OK)
    return_code=0
    ;;
  WARNING)
    return_code=1
    ;;
  CRITICAL)
    return_code=2
    ;;
  UNKNOWN)
    return_code=3
    ;;
esac

if [ $return_code == 0 ];then
  /usr/bin/printf "%s\t%s\t%s\t%s\n" "$1" "$2" 0 "$4" | /usr/sbin/send_nsca $親IP -c /etc/nagios/send_nsca.cfg
else
  case "$5" in
    SOFT)
      /usr/bin/printf "%s\t%s\t%s\t%s\n" "$1" "$2" 1 "$4" | /usr/sbin/send_nsca $親IP -c /etc/nagios/send_nsca.cfg
    ;;
    HARD)
      /usr/bin/printf "%s\t%s\t%s\t%s\n" "$1" "$2" 2 "$4" | /usr/sbin/send_nsca $親IP -c /etc/nagios/send_nsca.cfg
    ;;
  esac

fi

実行権限を与えておくこと。
# chmod 755 /usr/lib/nagios/eventhandlers/submit_check_result_service_for_trap



nagiosのコンフィグ確認
親・子共に実施
# /usr/sbin/nagios -v /etc/nagios/nagios.cfg



nagiosの起動
親・子共に実施する。
# /etc/init.d/nagios start

親だけで実施する。
# /etc/init.d/nsca start


2011年9月20日火曜日

TRAP(トラップ)の受信と監視サーバ(nagios)との連携

目的
監視対象ノードからのトラップを監視サーバのsnmptrapdで受理し、
その内容を同じく監視サーバで稼動しているサーバ(今回はnagiosを利用)へ通知させる。
nagiosの分散監視方法についてはこちらを参照のこと。


概要(トラップ処理の流れ)
1. トラップが飛んでくる

(トラップ例)
host101
UDP: [10.0.0.1]:59360
.1.3.6.1.2.1.1.3.0 87:21:51:52.92
.1.3.6.1.6.3.1.1.4.1.0 .1.3.6.1.6.3.1.1.5.3
.1.3.6.1.2.1.2.2.1.1.10106 10106
.1.3.6.1.2.1.2.2.1.2.10106 "eth0"
.1.3.6.1.2.1.2.2.1.3.10106 ethernet-csmacd
.1.3.6.1.4.1.9.2.2.1.1.20.10106 "down"
.1.3.6.1.6.3.18.1.3.0 10.24.7.14
.1.3.6.1.6.3.18.1.4.0 "public"
.1.3.6.1.6.3.1.1.4.3.0 .1.3.6.1.6.3.1.1.5


2. /usr/sbin/snmptrapdデーモンがトラップを受理


3. snmptrapd.conf内のtraphandleディレクティブで指定したコマンドが実行される
実行されるコマンドはトラップ内容を解析し、その結果を元にsend_nscaを実行して
パッシブなデータの転送処理を担当するNSCA(Nagios Service Check Acceptor)に通知させる。
そしてNSCA経由でNagiosは結果を受け取る。

※snmptrapd.confファイルの場所はsnmptrapdの起動スクリプト/etc/init.d/snmptrapdで指定される。



準備(監視サーバ側)
● インストール
# yum -y install net-snmp

# yum -y install nagios
# yum -y install nagios-nsca


トラップ受信時に一部データベースを使うためである(後ほど説明する)。
# yum -y install mysql mysql-server



● /etc/init.d/snmptrapdファイルの設定
飛んできたtrapを名前変換させないようにする。
# cp /etc/init.d/snmptrapd /etc/init.d/snmptrapd.yyyymmdd
# vi /etc/init.d/snmptrapd
(前)
OPTIONS="-Lsd -p /var/run/snmptrapd.pid"
(後)
OPTIONS="-On -Lsd -p /var/run/snmptrapd.pid"



● snmptrapd.confファイルの設定
飛んできたtrapの認証は不要とする。
traphandle ディレクティブで実行するコマンドを指定する。
# cp /etc/snmp/snmptrapd.conf /etc/snmp/snmptrapd.conf.yyyymmdd
# vi /etc/snmp/snmptrapd.conf
  disableAuthorization yes

  # traphandle default /usr/local/bin/trap.sh ← (a)
  traphandle default /usr/local/bin/trap.rb ← (b)



● traphandleディレクティブで指定したツールの概要
(a)
単純にトラップの内容をログに追記する。
(a)は今回は使わないが、単純にトラップの内容をログに出すだけならこれで十分だろう。
コードは別途下記に記載する。

(b)
(a)と同様にトラップの内容をログに追記していくのだが、
トラップの内容からデータベースを参照してoidの数字をテキストに変換、
また発報させるかさせないのかを判断をさせる処理を加えている。

データベースを用意する目的
1) 数字のoidでは内容が直感的に分からないため、テキストに変換する役割
2) 監視アラームとして発報させる、させないを制御する役割


そして、nagiosへの通知手段としてnagios-nscaをツール内で実行。


● トラップ処理ツールのコード
(a)
# vi /usr/local/bin/trap.sh
#!/bin/sh

echo --------------------------------- >> /var/log/snmptrap/traphandle.log
echo  "`date  '+%Y%m%d%H%M%S'`" >> /var/log/snmptrap/traphandle.log

while read line
do
  echo  "$line" >> /var/log/snmptrap/traphandle.log
done

# chmod 755 /usr/local/bin/trap.sh


(b)
# vi /usr/local/bin/trap.rb
#!/usr/bin/ruby

require 'mysql'

def error(exc)
  f = open('/var/log/snmptrap/traphandle_error.log','a+')
    f.puts '---------------'
    f.puts(Time.now.strftime("%Y%m%d%H%M%S"))
    f.puts(exc)
  f.close
  exit 1
end


def no_alert(host, mib_num)
  f = open('/var/log/snmptrap/traphandle_no_alert.log','a+')
    f.puts '---------------'
    f.puts(Time.now.strftime("%Y%m%d%H%M%S"))
    f.puts("host      :  #{host}")
    f.puts("mib_num   :  #{mib_num}")
  f.close
  exit 0
end


def alert(host, mib_text)
  begin
    command = "/usr/lib/nagios/plugins/submit_check_result #{host} 'TRAP [#{mib_text}]' 1 'check /var/log/snmptrap/traphandle.log'"
    #system command
    puts command

  rescue  => exc
    error(exc)
  end
  exit 0
end


# TRAP RECEIVE
begin
  f = open('/var/log/snmptrap/traphandle.log','a+')
    f.puts '---------------'
    f.puts(Time.now.strftime("%Y%m%d%H%M%S"))

    host = gets.chomp!

    # /etc/hosts ファイルへホスト名の登録が必要
    if host  =~ /.*: (\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\d)/  ||  host  =~ /<UNKNOWN>/
      host = 'other'
    end

    f.puts(host)
    f.puts(gets)
    f.puts(gets)
    oid = gets
    f.puts(oid.chomp!)
    mib_num = oid.scan(/.* (.*)/)

    while line = gets
      f.puts(line)
    end

  f.close

rescue  => exc
  error(exc)
end


# DATABASE
begin
  db = Mysql::new('localhost', 'trapuser', 'password', 'trapdb')

  res = db.query("select id from ignore_table where mib_id = (select id from mib_table where mib_num = '#{mib_num}')")
  id = nil
  res.each { | i | id = i }

  no_alert(host, mib_num) if id != nil

  res = db.query("select host, mib_text from host_table as h, mib_table as m, host_mib_table as hm where h.id = hm.host_id and m.id = hm.mib_id and h.host = '#{host}' and mib_num = '#{mib_num}'")
  mib_text = nil
  res.each { | h, m | mib_text = m }

  mib_text = 'other' if mib_text == nil
  alert(host, mib_text)

rescue  => exc
  error(exc)

ensure
  db.close
end

# chmod 755 /usr/local/bin/trap.rb


# vi /usr/lib/nagios/plugins/submit_check_result
#!/bin/sh

printfcmd="/usr/bin/printf"
NscaBin="/usr/sbin/send_nsca"
NscaCfg="/etc/nagios/send_nsca.cfg"
NagiosHost1=10.0.0.1

$printfcmd "%s\t%s\t%s\t%s\n" "$1" "$2" "$3" "$4" | $NscaBin $NagiosHost1 -p 5667 -c $NscaCfg

# chmod 755 /usr/lib/nagios/plugins/submit_check_result



● 各種プロセスの起動
# /etc/init.d/snmptrapd start
# /etc/init.d/mysqld start

# chkconfig snmptrapd on
# chkconfig mysqld on



● データベースの準備
mysqlの初期設定
# mysql_secure_installation
Set root password? [Y/n]                      ← 空ENTER(rootパスワード設定)
New password:                                 ← rootパスワード応答
Re-enter new password:                        ← rootパスワード応答(確認)
Remove anonymous users? [Y/n]                 ← 空ENTER(匿名ユーザー削除)
Disallow root login remotely? [Y/n]           ← 空ENTER(リモートからのrootログイン禁止)
Remove test database and access to it? [Y/n]  ← 空ENTER(testデータベース削除)
Reload privilege tables now? [Y/n]            ← 空ENTER


ルートユーザでログイン
# mysql -u root -p
Enter password:


ユーザの作成
> GRANT ALL PRIVILEGES ON trapdb.* TO trapuser@localhost IDENTIFIED BY 'password';
> quit


トラップDBを操作するユーザで再ログイン
# mysql -u trapuser -p
Enter password:


データベースの作成
> CREATE DATABASE trapdb;


データベースへ接続
> USE trapdb;


テーブルの作成
ホスト管理テーブル
> CREATE TABLE host_table (
id INT NOT NULL AUTO_INCREMENT,
host VARCHAR(255) NOT NULL UNIQUE,
PRIMARY KEY(id));

> SHOW COLUMNS FROM host_table;
+-------+--------------+------+-----+---------+----------------+
| Field | Type         | Null | Key | Default | Extra          |
+-------+--------------+------+-----+---------+----------------+
| id    | int(11)      | NO   | PRI | NULL    | auto_increment |
| host  | varchar(255) | NO   | UNI | NULL    |                |
+-------+--------------+------+-----+---------+----------------+


mib管理テーブル
> CREATE TABLE mib_table (
id INT NOT NULL AUTO_INCREMENT,
mib_num VARCHAR(255) NOT NULL UNIQUE,
mib_text VARCHAR(255) NOT NULL,
PRIMARY KEY(id));

> SHOW COLUMNS FROM mib_table;
+----------+--------------+------+-----+---------+----------------+
| Field    | Type         | Null | Key | Default | Extra          |
+----------+--------------+------+-----+---------+----------------+
| id       | int(11)      | NO   | PRI | NULL    | auto_increment |
| mib_num  | varchar(255) | NO   | UNI | NULL    |                |
| mib_text | varchar(255) | NO   |     | NULL    |                |
+----------+--------------+------+-----+---------+----------------+


ホストとmib管理テーブル
> CREATE TABLE host_mib_table (
host_id INT NOT NULL,
mib_id INT NOT NULL,
FOREIGN KEY(host_id) REFERENCES host_table(id),
FOREIGN KEY(mib_id) REFERENCES mib_table(id));

> SHOW COLUMNS from host_mib_table;
+---------+---------+------+-----+---------+-------+
| Field   | Type    | Null | Key | Default | Extra |
+---------+---------+------+-----+---------+-------+
| host_id | int(11) | NO   | MUL | NULL    |       |
| mib_id  | int(11) | NO   | MUL | NULL    |       |
+---------+---------+------+-----+---------+-------+


不要トラップ管理テーブル
> CREATE TABLE ignore_table (
id INT NOT NULL AUTO_INCREMENT, 
mib_id INT NOT NULL UNIQUE, 
PRIMARY KEY(id), 
FOREIGN KEY(mib_id) REFERENCES mib_table(id));

> SHOW COLUMNS FROM ignore_table;
+--------+---------+------+-----+---------+----------------+
| Field  | Type    | Null | Key | Default | Extra          |
+--------+---------+------+-----+---------+----------------+
| id     | int(11) | NO   | PRI | NULL    | auto_increment |
| mib_id | int(11) | NO   | MUL | NULL    |                |
+--------+---------+------+-----+---------+----------------+


登録
ホストの登録
> INSERT INTO host_table (host) VALUES('host101');
> INSERT INTO host_table (host) VALUES('host102');
> INSERT INTO host_table (host) VALUES('host103');

> SELECT * FROM host_table;
+----+---------+
| id | host    |
+----+---------+
|  1 | host101 |
|  2 | host102 |
|  3 | host103 |
+----+---------+


MIBの登録
> INSERT INTO mib_table (mib_num, mib_text) VALUES('.1.3.6.1.6.3.1.1.5.3', 'linkDown');
> INSERT INTO mib_table (mib_num, mib_text) VALUES('.1.3.6.1.6.3.1.1.5.4', 'linkUp');

> SELECT * FROM mib_table;
+----+----------------------+-----------------------+
| id | mib_num              | mib_text              |
+----+----------------------+-----------------------+
|  1 | .1.3.6.1.6.3.1.1.5.3 | linkDown              |
|  2 | .1.3.6.1.6.3.1.1.5.4 | linkUp                |
|  3 | .1.3.6.1.6.3.1.1.5.5 | authenticationFailure |
+----+----------------------+-----------------------+


不要トラップの登録
> INSERT INTO ignore_table (mib_id) VALUES(13);

> SELECT * FROM mib_table;
+----+--------+
| id | mib_id |
+----+--------+
|  1 |      3 |
+----+--------+


ホストとMIBの登録
下のようにホストとMIBを結びつけるようにデータベースに登録する。
host101 ⇔ linkDown
host101 ⇔ linkUp
host102 ⇔ linkDown

host_mib_tableをこのようにしたいわけである。
+---------+--------+
| host_id | mib_id |
+---------+--------+
|       1 |      1 |
|       1 |      2 |
|       2 |      1 |
+---------+--------+



アラーム発報
上記のようにホストとMIBを対応させた場合にどのように発報するのかまとめておく。

・ host101
 linkDown              → host101, TRAP [lindDown] として発報する
 linkUp                → host101, TRAP [lindUp] として発報する
 authenticationFailure  発報しない
 未定義TRAP             → host101, TRAP [other] として発報する

・ host102
 linkDown              → host102, TRAP [lindDown] として発報する
 linkUp                → host102, TRAP [other] として発報する
 authenticationFailure → 発報しない
 未定義TRAP             → host102, TRAP [other] として発報する

・ host103
 linkDown              → host101, TRAP [other] として発報する
 linkUp                → host101, TRAP [other] として発報する
 authenticationFailure → 発報しない
 未定義TRAP             → host103, TRAP [other] として発報する

・ 未定義ホスト
 linkDown              → other, TRAP [other] として発報する
 linkUp                → other, TRAP [other] として発報する
 authenticationFailure → 発報しない
 未定義TRAP             → other, TRAP [other] として発報する


idごとにひもづけるのだが手間がかかるのでツールを用意しておく。

# /usr/lib/nagios/plugins/update_db.rb [ホスト名] [mib(oid)] [insert|delete]

# /usr/lib/nagios/plugins/update_db.rb host101 .1.3.6.1.6.3.1.1.5.3 insert
# /usr/lib/nagios/plugins/update_db.rb host101 .1.3.6.1.6.3.1.1.5.4 insert
# /usr/lib/nagios/plugins/update_db.rb host102 .1.3.6.1.6.3.1.1.5.3 insert
削除したい場合は"insert"を"delete"に変える


# vi /usr/lib/nagios/plugins/update_db.rb 
#!/usr/bin/ruby

require 'mysql'

host = ARGV[0]
mib = ARGV[1]
action = ARGV[2]

if ARGV.length !=  3
  puts "argument error : ./update_db.rb [host] [mib number] [insert | delete]"
  exit 1
end

$db = Mysql::new('localhost', 'trapuser', 'password', 'trapdb')


def select(q)
  begin
    id = nil
    query = q
    res = $db.query(query);

    res.each do | i |
      id = i
    end
    return id

  rescue  => exc
    puts exc
  end
end


def insert(host_id, mib_id)
  begin
    query = "insert into host_mib_table (host_id, mib_id) values(#{host_id}, #{mib_id})"
    $db.query(query);
    puts "OK : #{query}"
    exit 0

  rescue  => exc
    puts exc
  end

end


def delete(host_id, mib_id)
  begin
    query = "delete from host_mib_table where host_id = #{host_id} and mib_id = #{mib_id}"
    $db.query(query);
    puts "OK : #{query}"
    exit 0

  rescue  => exc
    puts exc
  end
end


def check_duplicate(host_id, mib_id)
  begin
    query = "select host_id, mib_id from host_mib_table where host_id = #{host_id} and mib_id = #{mib_id}"
    res = $db.query(query);
    flag = nil
    res.each do | i |
      flag = 1
    end

    if flag == 1
      puts("ERROR : Already registered");
      exit 1
    end

  rescue  => exc
    puts exc
  end
end


query = "select id as host_id from host_table where host = '#{host}'"
host_id = select(query)
if host_id == nil
  puts "ERROR : '#{host}' is not registered!!"
  exit 1
end


query = "select id as mib_id from mib_table where mib_num = '#{mib}'"
mib_id = select(query)
if mib_id == nil
  puts "ERROR : '#{mib}' is not registered!!"
  exit 1
end


if action == "insert"
  check_duplicate(host_id, mib_id)
  insert(host_id, mib_id)

elsif action == "delete"
  delete(host_id, mib_id)

else
  puts "ERROR : Action is bad."
  puts "Action is [insert|delete]."
  exit 1
end



● nagiosの準備
設定
トラップを受け付けるサービス設定は以下でよい。
細かい設定に関しては省略する。

define service{
   use                     generic-service
   host_name               host01, host02
   service_description     TRAP [LinkUp]
   check_period            none
   active_checks_enabled   1
   max_check_attempts      1
   is_volatile             1
   check_command           check_dummy!0!"OK"
}

define service{
   use                     generic-service
   host_name               host03
   service_description     TRAP [LinkDown]
   check_period            none
   active_checks_enabled   1
   max_check_attempts      1
   is_volatile             1
   check_command           check_dummy!0!"OK"
}



文法チェック
# nagios -v /etc/nagios/nagios.cfg


起動
# /etc/init.d/nagios restart
# chkconfig nagios on



● nscaの準備
設定
設定ファイルは下だが、基本ディフォルトのままでいいだろう。
/etc/nagios/nsca.cfg

nscaは5667/tcpポートでsend_nscaからの結果を受け取るので、
iptablesなど確認しておいた方がいいだろう。

起動
nacaも立ち上げておく
# /etc/init.d/nsca restart
# chkconfig nsca on



◆ 準備(監視対象ノード側)
監視対象ノードがLinuxサーバであれば、
/etc/snmp/snmpd.confファイルを編集する
下のディレクティブに監視サーバのIPアドレスを入れておけばいいだろう

trapsink 監視サーバのIPアドレス
trap2sink 監視サーバのIPアドレス



◆ 発報試験
1) 監視対象ノードからトラップを飛ばす


2) 監視サーバ側でログを確認する
2-1) trap.rbが処理するログの確認
アラームとして発報させるtrapのログ
/var/log/snmptrap/traphandle.log

trapが飛んできたけれどテーブルに登録していない(アラートをあげない)場合のログ
/var/log/snmptrap/traphandle_no_alert.log

例外発生時のログ
/var/log/snmptrap/traphandle_error.log


2-2) nagiosが処理するログ
/var/log/nagios/nagios.log


監視対象ノードからトラップを飛ばせないのであれば、
監視サーバ側で手動で試験できる。

ツールを実行
# /usr/local/bin/trap.rb
以下をまるごと貼り付け
host101
UDP: [10.0.0.1]:59360
.1.3.6.1.2.1.1.3.0 87:21:51:52.92
.1.3.6.1.6.3.1.1.4.1.0 .1.3.6.1.6.3.1.1.5.3
.1.3.6.1.2.1.2.2.1.1.10106 10106
.1.3.6.1.2.1.2.2.1.2.10106 "eth0"
.1.3.6.1.2.1.2.2.1.3.10106 ethernet-csmacd
.1.3.6.1.4.1.9.2.2.1.1.20.10106 "down"
.1.3.6.1.6.3.18.1.3.0 10.24.7.14
.1.3.6.1.6.3.18.1.4.0 "public"
.1.3.6.1.6.3.1.1.4.3.0 .1.3.6.1.6.3.1.1.5
Ctrl + D で抜ける

"1 data packet(s) sent to host successfully."

と出ればツールは正常に動作している。
それでもnagios側で表示されないようであれば、
nagiosの設定の問題であろう。