Edited at

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

More than 3 years have passed since last update.

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.おわりに

基本的な考え方は上記の通りです。

なお、例外処理は色々あると思うのでそこは適宜追加してください。

また、今回は一連の流れをどかーっと書きましたが、認証処理などは共通化できると思うので、

そこは適宜作り替えてもらえればと思います。

※こうやってるよ、というのがあれば教えてください!!!

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