Nagios+Gangliaでシステムの異常を検知する

Nagios で問題を通知する

以前書いたGangliaの記事と併せて Ganglia + Nagios という構成でシステムのモニタリング、及び、問題の通知を行うためのシステムを構築する手順。

はじめに

先日の Gangliaでシステムモニタリング という記事にも書きましたが、弊社では Ganglia + Nagios という構成でシステムのモニタリングを行っています。

この構成を採るに至った元ネタは IBM developerWorks の以下記事です。

Ganglia の導入方法に関しては Gangliaでシステムモニタリング に書いた通りですが、今回は Nagios の導入、及び、Ganglia との連携方法に関してまとめてみます。

※写真 : 写真素材ぱくたそ

環境

環境は以下になります。

OS CentOS 6.7
Nagios 3.5.1-1
Ganglia 3.7.2-2

Nagiosインストール(サーバ側)

epelリポジトリの追加

epelリポジトリからインストールするため、登録されていない場合登録します。

# yum install epel-release

パッケージ・インストール

以下パッケージをインストールします。
  • nagios
  • nagios-plugins-all
# yum install nagios nagios-plugins-all

apache 関連設定

Nagios で状態を確認する場合に利用する Webアプリケーションに関わる設定を行います。

管理パスワードの設定

yum でインストールすると /etc/httpd/conf.d/nagios.conf がインストールされ apache 起動時に読み込まれます。
この設定では /etc/nagios/passwd を利用してBasic認証を行うようになっているので、このパスワードを設定します。

# htpasswd /etc/nagios/passwd nagiosadmin

実行するとパスワードを問い合わせてくる ( 2回 ) ので入力してください。

httpd 設定

必要に応じてapache関連の設定を行ってください。

# vi /etc/httpd/conf.d/nagios.conf

deny, allow 設定等を必要に応じて変更して下さい。

以下はGangliaサーバの場合と同様、LAN上の端末からも閲覧できるようにした例 (抜粋)

  ... 
  Allow from ::1
  Allow from 192.168.1.0/24
  ...

sendEmailインストール

Nagiosはデフォルトでは障害を検知した際にメール(/bin/mail)にて通知を行いますが、SMTP-Authに対応したメールを送信するために、sendEmailをインストールします。
以下を参考にしました。

Nagios Exchange - Notifications using ISP SMTP server with Authentication:

※必要ない場合は飛ばしてください。

  1. sendEmailを取得します。
    http://caspian.dotconf.net/menu/Software/SendEmail/ から sendEmail のアーカイブを取得します。
    # wget http://caspian.dotconf.net/menu/Software/SendEmail/sendEmail-v1.56.tar.gz
    
  2. 取得したアーカイブを展開し、/usr/local/bin 以下に sendEmail コマンドをコピーします。
    # tar xvzf sendEmail-v1.56.tar.gz
    # cp sendEmail-v1.56/sendEmail /usr/local/bin/
    
  3. sendEmail の実行確認
    /usr/local/bin/sendEmail を実行します。コマンドが正しく実行され、ヘルプが表示される事を確認します。
    # /usr/local/bin/sendEmail
    
  4. resource.cfg編集
    /etc/nagios/private/resource.cfg を編集します。

    ※resource.cfg に関しては /etc/nagios/nagios.cfg 中 resource_file= で定義されているので、ここで指定されているファイルを編集します。

    # /etc/nagios/private/resource.cfg
    

    以下内容で編集します (抜粋)

    $USER5$=xxx@agilegroup.co.jp # 送信メールアドレス
    $USER6$=XXXXXXXX             # 送信メールアドレスのパスワード
    $USER7$=mail.hoge.com:587    #メールサーバ名:ポート番号 
    
  5. sendEmail 用ログファイル作成
    # touch /var/log/sendEmail
    # chown nagios:nagios /var/log/sendEmail
    
  6. commands.cfg 編集
    commands.cfg を編集します。
    # vi /etc/nagios/objects/commands.cfg
    

    以下内容で編集します (抜粋)。notify-host-by-email、及び、notify-service-by-email コマンドを sendEmail を利用するように変更しています。

    define command{
            command_name    notify-host-by-email
            command_line    /usr/bin/printf "%b" "***** Nagios *****\n\nNotification Type: $NOTIFICATIONTYPE$\nHost: $HOSTNAME$\nState: $HOSTSTATE$\nAddress: $HOSTADDRESS$\nInfo: $HOSTOUTPUT$\n\nDate/Time: $LONGDATETIME$\n" | /usr/local/bin/sendEmail -s $USER7$ -xu $USER5$ -xp $USER6$ -t $CONTACTEMAIL$ -f $USER5$ -l /var/log/sendEmail -u "** $NOTIFICATIONTYPE$ Host Alert: $HOSTNAME$ is $HOSTSTATE$ **" -m "***** Nagios *****\n\nNotification Type: $NOTIFICATIONTYPE$\nHost: $HOSTNAME$\nState: $HOSTSTATE$\nAddress: $HOSTADDRESS$\nInfo: $HOSTOUTPUT$\n\nDate/Time: $LONGDATETIME$\n"
            }
    		
    # 'notify-service-by-email' command definition
    define command{
            command_name    notify-service-by-email
            command_line    /usr/bin/printf "%b" "***** Nagios *****\n\nNotification Type: $NOTIFICATIONTYPE$\n\nService: $SERVICEDESC$\nHost: $HOSTALIAS$\nAddress: $HOSTADDRESS$\nState: $SERVICESTATE$\n\nDate/Time: $LONGDATETIME$\n\nAdditional Info:\n\n$SERVICEOUTPUT$\n" | /usr/local/bin/sendEmail -s $USER7$ -xu $USER5$ -xp $USER6$ -t $CONTACTEMAIL$ -f $USER5$ -l /var/log/sendEmail -u "** $NOTIFICATIONTYPE$ Service Alert: $HOSTALIAS$/$SERVICEDESC$ is $SERVICESTATE$ **" -m "***** Nagios *****\n\nNotification Type: $NOTIFICATIONTYPE$\n\nService: $SERVICEDESC$\nHost: $HOSTALIAS$\nAddress: $HOSTADDRESS$\nState: $SERVICESTATE$\n\nDate/Time: $LONGDATETIME$\n\nAdditional Info:\n\n$SERVICEOUTPUT$"
            }
    

Nagios設定

Nagios の設定ファイルは以下のように分かれています。これらファイルを編集して設定を行っていきます。

ファイル
/etc/nagios/nagios.cfgメインの設定ファイル
/etc/nagios/objects/commands.cfgコマンドの定義
チェックコマンドや上述の通知用コマンドの定義に利用
/etc/nagios/objects/contancts.cfg通知先の定義
/etc/nagios/objects/timeperiods.cfg通知時間帯の定義
/etc/nagios/objects/templates.cfg設定のテンプレート

オブジェクト

Nagios では幾つかの定義可能なオブジェクトがあり、これらオブジェクトを定義して監視のための設定を行っていきます。
このオブジェクトの中でも特に重要なのは以下のものです。

  • host
    監視対象です。任意のサーバやネットワーク機器等が該当します。
  • service
    監視するサービスです。SSH や HTTP等になります。
  • contact
    通知先です。
  • command
    チェックのためのコマンドです。

ここでは、上記、及び、hostgroup に関して触れながら設定方法を説明します。

nagios.cfg

nagios.cfg では command.cfg, contacts.cfg 等のオブジェクト設定ファイルを利用するよう設定がなされています。

# You can specify individual object config files as shown below:
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

上記のように nagios では監視対象の種類によって設定ファイルを適宜分割し、これらを nagios.cfg で利用するように指定する形をとります。

cfg_dir というディレクティブも存在し、設定ファイルを格納するディレクトリを指定する事も可能です。この場合、指定したディレクトリ下にある拡張子.cfg のファイルが設定ファイルとして扱われます。
弊社の場合、監視対象のドメイン毎にディレクトリを切って、ここに設定ファイルを置く形にしています。ここでもその方式での設定方法に関して書きます。

監視対象に関する設定を格納するディレクトリの作成

LAN内のサーバ、及び、AWS上のサーバを監視するものとし、以下ディレクトリを作成します。

# mkdir /etc/nagios/agile_local
# mkdir /etc/nagios/aws

nagios.cfgに 上記ディレクトリ設定を追加します。

# vi /etc/nagios/nagios.cfg

以下を追記します。

cfg_dir=/etc/nagios/agile_local
cfg_dir=/etc/nagios/aws

command.cfg 編集

command.cfg を必要に応じて編集します。
command.cfg には既によく利用されるコマンドが定義されています。監視したいサービスチェック用のコマンドが定義済みの場合、これらを利用しましょう。対象サービスのチェックコマンドが定義されていない場合には、定義を追加します。

※Nagios ではプラグインをインストールしたからといって、これがすぐに利用できるわけではなく、command.cfg でプラグインに対応する定義を行う必要があります。実際のホスト/ホストグループに対して監視の設定を行う場合には command.cfg で定義された内容で check_command 定義を記述する事になります。

# vi /etc/nagios/objects/commands.cfg

以下例。
ここでは幾つかのコマンド定義の例を示しています。
必要となるコマンドはプラグインのマニュアル等に従って適宜追加して下さい。

# 'check_smb' command definition
define command{
        command_name    check_smb
        command_line    $USER1$/check_disk_smb -H $HOSTADDRESS$ -s $ARG1$ -u user -p 'passwd' -w $ARG2$ -c $ARG3$
        }

# 'check_ldap' command definition
define command{
        command_name    check_ldap
        command_line    $USER1$/check_ldap -H $HOSTADDRESS$ -b $ARG1$ -w $ARG2$ -c $ARG3$
        }

# 'check_mysql' command definition
define command{
        command_name    check_mysql
        command_line    $USER1$/check_mysql -H $HOSTADDRESS$ -u root -p passwd
        }

# 'check_clamd' command definition
define command{
        command_name    check_clamd
        command_line    $USER1$/check_nrpe -H $HOSTADDRESS$ -c check_clamd
        }

contacts.cfg 編集

contacts.cfg を編集します。

# vi /etc/nagios/objects/contacts.cfg

以下のように編集します (抜粋)。

    alias           Nagios Admin            ; Full name of user
    email          xxx@agilegroup.co.jp      ; <<***** CHANGE THIS TO YOUR EMAIL ADDRESS ******

ドメイン毎の設定

LAN、及び、aws 用にディレクトリを切りましたが、ここに監視のための設定ファイルを作成します。
以下ファイルを作成するものとします。

基本的な方針は "はじめに" にリンクした developerWorks の記事に従っています。

ここでの方法に従った場合、設定ファイルとオブジェクトの関係は以下のような感じになります。

nagios config files
ファイル設定内容
nodes.cfg監視対象のノード、及び、ノードグループの定義
host-services.cfg監視するサービスとホストの関連設定を定義

nodes.cfg

nodes.cfg を作成します。以下は aws の場合の一例です。

#===== ホストグループ定義 =====
# サーバ群
define hostgroup {
 hostgroup_name aws_ec2-servers
 alias AWS EC2 Servers
}

#===== ホスト定義 =====
# EC2サーバ定義(ベース)
define host {
 name   aws_ec2-server
 use    linux-server
 hostgroups aws_ec2-servers
 # TEMPLATE!
 register 0
}

#----- 実際のノード定義(上記ベース定義を継承) -----
#-- Agile Web Server --
define host {
 use aws_ec2-server
 host_name agilegroup.co.jp
 alias Agilegroup Web Server
 address agilegroup.co.jp
}
...

ポイントは以下

  • 実際の監視対象(ノード)を定義する場合に、定義済みの設定を継承している事
    共通部分は親の定義で行い、ホスト固有の設定箇所を少なくする事ができる。
    nagios node 設定継承
  • ホストグループ設定を行っている事
    ホストグループに対して監視設定を行う事で管理コストが軽減できる。

上記設定例ではホストグループとして aws_ec2-servers しか設定していませんが、例えばwebサーバとdbサーバでは監視内容は異なってきます。こういった場合、webサーバ用とdbサーバ用のホストグループを設定する事になるでしょう。

host-services.cfg

host-services.cfg では nodes.cfg で設定したホスト/ホストグループに割り当てる監視内容を定義します。
以下設定例を示します。

# 監視サービスと任意のホスト/ホストグループの関連設定
#-- SSH --
define service{
        use                             generic-service
        hostgroup_name                  aws_ec2-servers
        service_description             SSH
        check_command                   check_ssh!--port=NNN
        }
#-- Ping --
define service{
        use                             generic-service
        hostgroup_name                  aws_ec2-servers
        service_description             PING
        check_command                   check_ping!100.0,20%!500.0,60%
        }

上記設定ではSSH、及び、PINGの監視を設定しています。これら何れもホストグループに対しての設定になっています。

※check_command がcheckのためのコマンドです。command.cfg で定義済みのコマンドを指定します。!以降の文字列がオプション($ARG1$~)に置換されます ( 二つめの!以降は $ARG2$ に )。

ホストグループを定義するまでもないという場合、上記 hostgroup_name 部分を以下のようにする事も可能です。

        host_name                  host1

また、hostgroup_name、及び、host_name いずれの場合も以下のように複数の対象を指定可能です。

        hostgroup_name             group1, group2, group3
あるいは
        host_name                  host1, host2, host3

LANの場合の例

LANの場合の設定例も示します。

nodes.cfg

#===== ホストグループ定義 =====
# サーバ群
define hostgroup {
 hostgroup_name agile_local-servers
 alias Agile Local Servers
}
# サーバ以外のネットワーク機器
define hostgroup
 hostgroup_name agile_local-network
 alias Agile Local Network Infrastructure
}

#===== ホスト定義 =====
# Linuxサーバ定義(ベース)
define host {
 name   agile_local-server
 use    linux-server
 hostgroups agile_local-servers
 # TEMPLATE!
 register 0
}
# ネットワーク機器定義(ベース)
define host {
 name agile_local-network
 use    generic-switch
 hostgroups agile_local-network
 # TEMPLATE!
 register 0
}

#----- 実際のノード定義(上記ベース定義を継承) -----
#-- Router --
define host {
 use agile_local-network
 host_name agile-router
 alias router
 address 192.168.xx.xx
}
#-- Printer --
define host {
 use agile_local-network
 host_name agile-printer
 address 192.168.xx.xx
}
#-- Kvm Host Server --
define host {
 use agile_local-server
 host_name kvm.agilegroup.local
 alias kvm (KVM Host Server)
 address 192.168.xx.xx
}
....

host-services.cfg

# 監視サービスと任意のホスト/ホストグループの関連設定
#-- SSH --
define service{
        use                             generic-service
        hostgroup_name                  agile_local-servers
        service_description             SSH
        check_command                   check_ssh
        }
#-- Ping --
define service{
        use                             generic-service
        hostgroup_name                  agile_local-servers, agile_local-network
        service_description             PING
        check_command                   check_ping!100.0,20%!500.0,60%
        }
#-- Clamd --
define service{
        use                             generic-service
        hostgroup_name                  agile_local-servers
        service_description             CLAMD
        check_command                   check_clamd
        }
...

ルータ、プリンタ系のアプライアンスは Pingチェック(基本的な死活監視)のみ行う設定例になっています。

Gangliaとの連携設定

Ganglia との連携を設定します。

Ganglia と Nagios: 第 2 回 Nagios でエンタープライズ・クラスターを監視する の方法そのままです。

gangliaプラグインの入手・インストール

Ganglia パッケージを取得して入手するか ( Ganglia のパッケージ中を解凍した場合 ./contrib/check_ganglia.py スクリプトが含まれる )、Github から入手して下さい。

check_ganglia.py スクリプトを Nagiosのプラグインディレクトリにコピーします。

# cp check_ganglia.py /usr/lib64/nagios/plugins

ganglia-services.cfg

nodes.cfg 等と同様に Ganglia のメトリックを利用したチェック定義のためのファイルを作成します。ファイル名は ganglia-services.cfg とします。

# vi /etc/nagios/agile_local/ganglia-services.cfg

以下のような内容で編集します。

以下はGangliaの load_one、disk_free メトリックを利用する設定になっています。これら以外のメトリックを利用する場合、適宜サービス設定を追加して下さい。

# Gangliaで収集した情報を元にNagiosが監視を行うための設定
define servicegroup {
  servicegroup_name ganglia-metrics
  alias Ganglia Metrics
}
# Gangliaで収集した情報を用いたチェックを行うコマンド
define command {
  command_name check_ganglia
  command_line $USER1$/check_ganglia.py -h $HOSTNAME$ -m $ARG1$ -w $ARG2$ -c $ARG3$
}
# ganglia-serviceの定義ベース (個々の監視(service)定義はこの定義を継承する)
# 対象は agile_local-servers で定義されたホスト全て
define service {
  name ganglia-service
  use generic-service
  hostgroup_name agile_local-servers
  service_groups ganglia-metrics
  notifications_enabled 0
  register 0
}
# Gangliaのload_one監視用
# 5以上 : Warning、8 : Critical
define service {
  use ganglia-service
  service_description load_one
  check_command check_ganglia!load_one!5!8
}
# Gangliaのdisk_free監視用
# 3G未満 : Warning、1G未満 : Critical
define service {
  use ganglia-service
  service_description disk_free
  check_command check_ganglia!disk_free!3!1
}

check_ganglia.py コマンドの編集

check_ganglia.py コマンドはしきい値が高くなり過ぎた場合にしかアラートを出しません。disk_free の場合と同様に、しきい値が低くなり過ぎた時にもアラートを出すには、コードに手を加える必要があります。check_ganglia.pyの終わりを以下のように変更します。(抜粋)

 if critical > warning:
    if value >= critical:
      print "CHECKGANGLIA CRITICAL: %s is %.2f" % (metric, value)
      sys.exit(2)
    elif value >= warning:
      print "CHECKGANGLIA WARNING: %s is %.2f" % (metric, value)
      sys.exit(1)
    else:
      print "CHECKGANGLIA OK: %s is %.2f" % (metric, value)
      sys.exit(0)
  else:
    if critical >= value:
      print "CHECKGANGLIA CRITICAL: %s is %.2f" % (metric, value)
      sys.exit(2)
    elif warning >= value:
      print "CHECKGANGLIA WARNING: %s is %.2f" % (metric, value)
      sys.exit(1)
    else:
      print "CHECKGANGLIA OK: %s is %.2f" % (metric, value)
      sys.exit(0)

Nagios 起動

変更を適用するためにNagiosを(再)起動します。

再起動の前にここまでに設定した内容に問題がないかチェックします。

# nagios -v /etc/nagios/nagios.cfg

設定に問題がある場合、エラー内容が表示されます。問題なければNagiosを(再)起動します。

# /etc/rc.d/init.d/nagios restart

自動起動設定は必要に応じてどうぞ

# chkconfig nagios on

サービスが起動したら http://<サーバ名>/nagios/ にWebブラウザでアクセスする事で Nagios の管理作業を行う事ができます。
基本認証を設定している場合、先に設定した id / password で認証を通して下さい。

以下は Nagios の管理画面から Service Detail を実行した場合の例

Nagios Service Detail

通知

Nagios がきちんとセットアップされれば、問題があった場合に通知が行われます。

以下通知メールの例です。

ディスク残量がしきい値を下回ったために送信されたアラートメールになります。

***** Nagios *****

Notification Type: PROBLEM

Service: disk_free
Host: host1 (System Monitor(Nagios,Ganglia))
Address: 192.168.xx.xx
State: WARNING

Date/Time: Tue Jan 31 12:34:56 JST 2016

Additional Info:

CHECKGANGLIA WARNING: disk_free is 2.96

通常はメールによる通知になるでしょうが、任意のスクリプトを実行させる事も出来るようです。デバイス連携してパトランプ(USB接続のやつとか)を鳴らすといった事も可能だと思います。

Nagios(NRPE)インストール(監視対象側)

監視対象もLinuxサーバ( Centos6系 )の想定です。

実は 上の監視設定では、一部のサービス監視に NRPE を利用していました。

NRPE は Nagios Remote Plugin Executor の略で、その名の通り、監視対象でプラグインをリモート実行し、その結果を Nagios サーバに返すもので、これによってリモートサーバのメトリックをモニタする事が可能になります。
今回の設定では Gangliaと連携する事で監視対象の基本的なメトリックも取得できる状態になっているため、必ずしも必要ではありませんが、Gangliaでは非標準のメトリックを検知したい場合や、特殊なサービスの状態を通知したいと言った場合、NRPEを利用する事で検知可能になる場合があります。

※上記監視設定では clamd (アンチウィルス) の状態監視に nrpe を利用する設定を記述

ここでは監視対象にNRPEを導入する場合の手順についても簡単に示します。

パッケージのインストール

以下をインストールします。

  • nagios-nrpe
  • nagios-plugins-nrpe
  • nagios-plugins-all

nrpe.cfgの編集

/etc/nagios/nrpe.cfgを編集します

# vi /etc/nagios/nrpe.cfg

以下内容で編集します (抜粋)。

allowed_hosts=127.0.0.1, 192.168.xx.xx  # nagios サーバのアドレスを追記
		
dont_blame_nrpe=1
		
command[check_clamd]=/usr/lib64/nagios/plugins/check_clamd -H localhost -w 20 -c 60

command[コマンド名]= 実行するコマンドを定義します。

コマンド名の部分は Nagiosのcommand.cfg で定義した clamd チェック用コマンドの以下太字部分 ( check_nrpe プラグインの -c オプションの値 ) と合致させるようにします。

        command_name    check_clamd
        command_line    $USER1$/check_nrpe -H $HOSTADDRESS$ -c check_clamd

NRPEの起動

設定を変更したらNRPEを(再)起動します。

※xinetd 配下で実行させる方法もあります。参考 : Standalone NRPE vs Under XINETD

# /etc/rc.d/init.d/nrpe start

自動起動設定は必要に応じてどうぞ

# chkconfig nrpe on

ファイアウォール設定

nrpe は デフォルトで 5666番ポートを利用するので、通信が行えるように設定を行ってください
以下は一例

# vi /etc/sysconfig/iptables
以下ルールを追記。ルール追加後は iptables 再起動
-A INPUT -m state --state NEW -m tcp -p tcp --dport 5666 -j ACCEPT

NRPEの動作

NRPEプラグインの実行は以下のような感じで行われます (多分)。

  1. Nagios でNRPEプラグインが実行される。今回の例では
    check_nrpe -H $HOSTADDRESS$ -c check_clamd
    
    $HOSTADDRESS$ 部分にはNagiosが監視対象(リモート)のアドレスを設定する。
    -c オプションはNRPEのコマンド名。
    リモートに対してNRPEリクエストが発行されると思えばよい。
  2. リモートのNRPEがコマンド実行のリクエストを受ける。
    NRPEは-c で指定されたコマンド名でコマンドが登録されていればこれを実行する。
    今回の例では nrpe.cfg で
    command[check_clamd]=/usr/lib64/nagios/plugins/check_clamd -H localhost -w 20 -c 60
    
    として定義されている。
  3. リモートがコマンドの実行結果をNagios側に返す。
  4. NagiosはNRPEプラグインの実行結果に従いサービスの状態を検知(把握)する。

NRPEプラグインを単独で実行する。

NRPEが正しく動作するかどうかは Nagios サーバ側からプラグインを直接実行する事でも確認できます。

# /usr/lib64/nagios/plugins/check_nrpe -H 192.168.xx.xx -c check_clamd
CLAMD OK - 0.000 second response time on localhost port 3310 [PONG]|time=0.000357s;20.000000;60.000000;0.000000;10.000000

NRPEプラグインの実行で問題がある場合には、直接実行する事で問題解決の糸口が掴める可能性は高いと思われます。

※例えばリモートで定義したコマンドと異なる場合、NRPE: Command 'hogehoge' not defined とエラーが出力される。

まとめ

Nagios + Ganglia で

  • システムのモニタリング
  • 問題の検知
  • アラート/エラーの通知

を行うためのシステム構築方法に関して記載しました。
参考文書に挙げた developersWorks の記事 には更に Nagios を拡張する方法等も記載されているので、興味がある方はお読みください。