12月 21, 2015

移動するサーバのzabbixエージェントを登録する(Zabbix Advent Calendar 2015)

Zabbix Advent Calendar 2015の21日目です。

zabbix便利ですね。
監視と通知と表示と対応がこれ一つでできるので、 何かと重宝しています。
悩みをツイートすると、的確なアドバイスが返ってくるのもすごいです。
本当はフォーラムあたりに投稿して、情報を集積するべきなんでしょうけど、すいません。

さて、わたしの環境では 自宅サーバでzabbix-serverを起動し、他の自宅サーバやEC2、VPSのagentから情報を集めています。
EC2だと固定IPを登録していないなら起動する度にIPアドレスが変わりますし、スポットインスタンスなどを使えば起動していない時間帯もあります。
このようなサーバもzabbixで管理したいと思い試行錯誤してみたらうまく行ったのでご紹介。

通常、同一ネットワークに管理対象サーバが居れば、ディスカバリ機能を使ってagentを見つけてくれますが、さすがにグローバルIPアドレス宛で、範囲が決まっているとは言えEC2などでは広大な範囲が指定されているので難しいものがあります。
ですので、agent側から起動時にserverへIPアドレスの変更を通知します。
わたしの場合は、サーバが落ちていることも検知したかったので、インスタンス終了時には敢えてサーバの登録解除はせず、あらかじめ登録しておいたサーバのIPアドレスを変更する手法を採っています。
数の決まっていないサーバを登録・解除する場合は、以下の方法のIP変更命令を、サーバの登録にして、インスタンス終了時に登録解除の命令を送れば大丈夫かと思います。

zabbixには、JSONRPCで用意されているAPIを叩くと、様々な情報を取得したり、更新したりできます。
この機能を利用します。このスクリプトは、zabbixサーバに設置します。
ユーザー名、パスワード、zabbix設置アドレスをそれぞれの環境に合わせて書き換えてください。
あと、jqコマンドを使いますので入れておいてください。
#!/bin/bash

# json2zabbix
json_auth='{"jsonrpc":"2.0","method":"user.login","params":{"user":"ユーザー名","password":"パスワード"},"id":1}'
rpc_url='http://zabbix設置アドレス/api_jsonrpc.php'

ZABBIX_TOKEN=`curl -s -XGET -H "Content-Type:application/json-rpc" -d $json_auth $rpc_url | jq -r '.result'`
echo "####### TOKEN = $ZABBIX_TOKEN"

if [ $1 ]; then
  json='{"jsonrpc": "2.0","method":"hostinterface.get","params":{"filter":{"dns":"##DNS##"}},"id":2,"auth":"##TOKEN##"}'
  json=`echo $json | jq '.' -c | sed -e s/##DNS##/$1/ -e s/##TOKEN##/$ZABBIX_TOKEN/ `
  echo $json
  interfaceid=`curl -s -XGET -H "Content-Type:application/json-rpc" -d $json $rpc_url | jq -r '.result[0].interfaceid'`

  json='{"jsonrpc": "2.0","method":"hostinterface.update","params":{"interfaceid":"##INTERFACEID##","ip":"##IP##"},"id":3,"auth":"##TOKEN##"}'
  json=`echo $json | jq '.' -c | sed -e s/##INTERFACEID##/$interfaceid/ -e s/##IP##/$2/ -e s/##TOKEN##/$ZABBIX_TOKEN/ `
  echo $json
  curl -s -XGET -H "Content-Type:application/json-rpc" -d $json $rpc_url
else
  echo "JSON to ZABBIX Request"
  echo "Usage: json2zabbix.sh ip dns"
fi
jsonrpcのメソッドについてはこちらを参照してください。バージョン2.4へのリンクですが、ロゴの下でバージョンが切り替えられます。
このスクリプトではuser.loginメソッドでログイントークンを取得し、以後のメソッド呼び出しに使っています。
IPアドレスを変更する対象サーバを見つけるために、DNS情報を利用しています。
hostinterface.getにて、指定のDNSを持つサーバのインターフェースIDを取得し、そのインターフェースのIPアドレスをhostinterface.updateメソッドで更新しています。

EC2側では、agentの起動スクリプト内で
sudo -u サーバにSSH接続できるユーザ名 ssh ユーザ名@サーバアドレス -p SSHポート "json2zabbix.sh ${instance_name} ${ec2_public_ipv4}"
を呼び出します。
ここで使っている
${instance_name} と ${ec2_public_ipv4} は、別途
#!/bin/sh

# get instance data
url_prefix=http://169.254.169.254/latest
ec2_instance_id=`/usr/bin/curl ${url_prefix}/meta-data/instance-id/ --stderr /dev/null`
ec2_region=`/usr/bin/curl ${url_prefix}/meta-data/public-hostname --stderr /dev/null | awk -F . '{print $2}'`
ec2_public_ipv4=`/usr/bin/curl ${url_prefix}/meta-data/public-ipv4 --stderr /dev/null`
ec2_user_id=`/usr/bin/curl ${url_prefix}/dynamic/instance-identity/document --stderr /dev/null | awk -F : '/accountId/ {n=split($2,a,"\"");print a[2]}'`
instance_name=`/usr/bin/curl -q ${url_prefix}/user-data --stderr /dev/null`
local_ipv4=`/usr/bin/curl ${url_prefix}/meta-data/local-ipv4 --stderr /dev/null`
というようなスクリプトを用意して読み込ませておくと良いでしょう。
分けてあると、色々と使い回しができて便利です。
このスクリプトでは、EC2の高度な詳細にあるユーザーデータにドメイン名を指定します。
jsonrpcで操作できる項目は多種に渡るため、一度どんなメソッドが用意されているか見ておくだけでも楽しいです。基本的にはWebUIから設定できる物は全部できるっぽいですね。
何か自動化したくなったときに、いろいろと役立つかもしれません。

0 件のコメント:

コメントを投稿