LoginSignup
46
49

More than 5 years have passed since last update.

オートスケールするインスタンスをzabbix監視対象として自動登録(削除)する

Last updated at Posted at 2014-12-02

AWSのAuto-Scalingって、とってもクラウドらしくて聞こえもよく便利なんですが、
本気で導入しようとすると、結構細かい考慮が必要だったりします。

そのひとつが、監視対象をどうやってコントロールするか? です。

本記事では、zabbixを使って監視を行う構成を例に、その構成方法を解説したいと思います。

1.そもそもAuto-Scalingとは?

ざっくりですが、Auto-Scaingのおさらい。

Auto-Scalingは、大きく3つのコンポーネントから構成されています。

コンポーネント 設定内容(超ざっくり)        
Launch-configuration 起動するAMI-IDやインスタンスタイプを指定
Auto-Scaling-group 起動するAZ指定、max、min台数の指定
Auto-Scaling-policy スケール時に何台ずつ拡張・縮退するかの指定

この3つのコンポーネントを定義しておき、CloudwatchでAuto-Scaling-groupの負荷状態を監視します。
Cloudwathは、定義した敷居値を超えると"アラーム"が発生するので、これをトリガーにAuto-Scaling-actionを発動し、
定義した内容の通りにインスタンスを増減させる仕組みです。

例えば、こんな具合です。

CPU使用率90超が2分間続いたらアラームを発生させ、インスタンスを1台ずつ増やす。
CPU使用率10%以下が10分間続いたらアラームを発生させ、1台ずつインスタンスを削除する。

ここで大切なのは、
Auto-Scalingで起動してくるインスタンスは、ど新規インスタンスであるということと、
Auto-Scalingで削除されるインスタンスは、stopではなく、terminateされるということです。

つまり、予め準備しておいたインスタンスを起動・停止するわけではないので、
IPアドレスやホスト名は都度変わってしまうことになります(AWSの仕様)。

2.監視対象へ自動登録・削除するには?

ではどうするか?
スケールアウト時には自動で監視対象に登録する処理と、
スケールイン時は、自動で監視対象から削除する処理が必要になってきます。

zabbixはAPIが公開されているので、上記処理をスクリプトで書いておき、
インスタンス起動時(削除時)に自動的に実行するように仕込んでおけばOKです。

3.ホスト登録・削除スクリプト

zabbixには色々なAPIが存在していますが、ここでは純粋なzabbix-APIを利用して登録します。
zabbix-APIは、JSONを引数にしてメソッドやパラメーターを指定してhttpリクエストを投げる方式で処理を行っていきます。
イチからJSONをパースする処理を書くのは面倒なので、今回はpythonを使用してスクリプトを書いています。

...さて、やっと本題です。
zabbixのホストに登録するには以下の値が必要になります。

auth-id : 認証情報です
hostgroup-id : どのホストグループに登録するか?
template-id : どんな監視項目(Template)を割り当てるか?

なので、まずはこれらの値を取得してから登録処理を行います。

create_host.py
#coding=utf-8
import json
import urllib2
import socket

# based url and required header
url = "http://xxx.xxx.xxx.xxx/zabbix/api_jsonrpc.php"
header = {"Content-Type":"application/json"}


############### まずは認証し、認証idを取得します(以降の処理で必要) ###############

data = json.dumps(
{
   "jsonrpc": "2.0",
   "method": "user.login",
   "params": {
   "user": "Admin",        # initial-param
   "password": "zabbix"    # initial-param
},
"id": 0
})

# create request object
request = urllib2.Request(url,data)
for key in header:
   request.add_header(key,header[key])

# auth and get authid
result = urllib2.urlopen(request)
response = json.loads(result.read())
result.close()
authid = response['result']


############### host登録に必要な値①:gropu-idを取得します ###############

data = json.dumps(
{
   "jsonrpc": "2.0",
   "method": "hostgroup.get",
   "params": {
      "output": "extend",
      "filter": {
         "name":[ "XXXXXXXXXXX" ]
      }
   },
    "auth": authid,
    "id": 1
})

# create request object
request = urllib2.Request(url,data)
for key in header:
   request.add_header(key,header[key])

# get hostgroup-id
result = urllib2.urlopen(request)
response = json.loads(result.read())
result.close()
for gid in response['result']:
   # set hostgrup-id 
   targetGroupid = gid['groupid']



############### host登録に必要な値②:template-idを取得します ###############

data = json.dumps(
{
   "jsonrpc": "2.0",
   "method": "template.get",
   "params": {
      "output": "extend",
      "filter": {
         "host":[ "XXXXXXXXXXX" ]
      }
   },
    "auth": authid,
    "id": 1
})

# create request object
request = urllib2.Request(url,data)
for key in header:
   request.add_header(key,header[key])

# get template-id
result = urllib2.urlopen(request)
response = json.loads(result.read())
result.close()
for gid in response['result']:
   # set template-id
   targetTemplateId = gid['templateid']



###############  取得した値を基にhost登録 ###############

data = json.dumps(
{
   "jsonrpc": "2.0",
   "method": "host.create",
   "params": {
      "host": "XXXXXXXXXXX",
      "interfaces": [{
         "type": 1,
         "main": 1,
         "useip": 1,
         "ip": "xxx.xxx.xxx.xxx",
         "dns": "",
         "port": "999"}],
      "groups": [{
         "groupid": targetGroupid
      }],
      "templates":[{
         "templateid": targetTemplateId
      }]
   },
    "auth": authid,
    "id": 1
})

# create request object
request = urllib2.Request(url,data)
for key in header:
   request.add_header(key,header[key])

# create host
result = urllib2.urlopen(request)
response = json.loads(result.read())
result.close()
for hid in response['result']['hostids']:
   print "create host successful. host-id is " + hid

また、削除時には以下の値が必要になります。
登録時と同じように、まずはhost-idを取得し、取得したhost-idをキーに削除処理を行います。

host-id : 削除対象のホストキー

ソースコードは省略しますが、
登録時と同じように、認証 → host-id取得 → deleteという流れになります。

4.自動起動・削除の設定(Linux)

最後に、作ったスクリプトをサービスとして登録し、
インスタンスの起動時・シャットダウン時に自動実行するように設定してあげます。
これは普通にLinuxのService登録をしてあげるだけす。

etc/init.d配下にserviceコマンド用のスクリプトを配置し、chkconfig --add xxxxでサービス登録します。
サービス登録用のスクリプトはこんな感じです。
このスクリプトから、先ほどのホスト登録スクリプトや削除スクリプトを呼んでいます。

service用コマンド
#!/bin/sh

# chkconfig: 2345 99 06
# description: regist or delete zabbix-managed-host-list.

servicename='manage-zabbix-host'
lock_file="/var/lock/subsys/${servicename}"

start() {
    python /path/01_regist_host.py
    touch ${lock_file}
    echo "manage-zabbix-host-list start:[OK]"
    return 0
}
stop() {
    python /path/02_delete_host.py
    rm -f ${lock_file}
    echo "manage-zabbix-host-list stop:[OK]"
    return 0
}


case "$1" in
  start)
    start
    ;;
  stop)
    stop
    ;; 
  *) break ;;
esac

5.おわりに

基本的な考え方は上記の通りです。
なお、例外処理は色々あると思うのでそこは適宜追加してください。

また、今回は一連の流れをどかーっと書きましたが、認証処理などは共通化できると思うので、
そこは適宜作り替えてもらえればと思います。
※こうやってるよ、というのがあれば教えてください!!!

後日、これの動作確認くらいの情報は追記したいと考えています。。。

46
49
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
46
49