前提
- zabbix3.4
- ALBに紐づいているTargetGroupのヘルスチェックが通っているかを確認したい
構成
AWS ALBはHealthyHostCount
という情報をCloud watchに保存しています。
Cloud Watchからの情報はAPIを経由して取得する必要があります。
なので今回は
- external scriptsに
APIを打ってzabbix senderでcloud watchの情報を送るスクリプト
を配置する - zabbix server側でzabbix trapperを使ってzabbix senderで送られた情報をキャッチする
- そのitemでアラートを出すようにする
zabbix trapper等の情報は以下が詳しいです。
https://www.zabbix.com/documentation/3.0/manual/config/items/itemtypes/trapper
zabbix senderでcloud watchの情報を送る
基本pythonで以下の感じで実装をしました。
- シェルスクリプトでpythonを叩く
- zabbixで設定されているHost情報から target groupの情報を抜く(ZabbixのMacroとかにTarget情報をいれてもOK)
- cloud watchから情報を抜く(今回はメトリクス情報もAPIから毎回引っこ抜いています。)
-
alb.metrics_name
という形に生成 - subprocessでzabbix senderを実行。
aws_monitoring.py
#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys, subprocess, datetime
from boto3.session import Session
def _exponential_backoff(func, trial_count=5):
last_raised = None
for x in xrange(trial_count):
try:
results = func()
return results
except Exception as e:
print('[{0}/{1}] Exponential Backoff Failed'.format(x + 1, trial_count))
last_raised = e
time.sleep(2 ** x)
raise last_raised
def get_client(akey, sakey, region, SERVICE='ec2'):
client = Session(
aws_access_key_id = akey,
aws_secret_access_key = sakey,
region_name = region
).client(SERVICE)
return client
def send_data(hostname, key, value):
cmd =['zabbix_sender', '-z','127.0.0.1', '-s', str(hostname), '-k', str(key), '-o', str(value), '-vv']
result = subprocess.call( cmd, shell=False )
def get_cw_columnlist(client, TARGET_GROUP):
metricslist = _exponential_backoff(lambda: client.list_metrics(
Namespace = 'AWS/ApplicationELB',
Dimensions = [{
'Name' : 'TargetGroup',
'Value' : TARGET_GROUP,
}],
)
)
columnlist = []
for metrics in metricslist['Metrics']:
columnlist.append(metrics['MetricName'])
columnlist_unique = list(set(columnlist))
return columnlist_unique
def send_items(cw_client, alb_client, ELB_NAME):
alb_info = _exponential_backoff(lambda: alb_client.describe_target_groups(Names=[ELB_NAME]))
TARGET_GROUP = alb_info['TargetGroups'][0]['TargetGroupArn'].rsplit(':',1)[1]
for column in get_cw_columnlist(cw_client, TARGET_GROUP):
unit = _select_unit(column)
cw_values = _exponential_backoff(lambda: cw_client.get_metric_statistics(
Namespace = 'AWS/ApplicationELB',
MetricName = column,
Dimensions = [{
'Name' : 'TargetGroup',
'Value' : TARGET_GROUP,
}],
StartTime = get_nowtime_utc() - datetime.timedelta(minutes=9),
EndTime = get_nowtime_utc(),
Period = 300,
Statistics = [unit],
)
)['Datapoints']
key = 'alb.' + column
value = 0
if cw_values != []:
value = sorted(cw_values,key=lambda x:x['Timestamp'],reverse=True)[0][unit]
print(key, value)
send_data(ELB_NAME, key, value)
def _select_unit(column):
unitlist = {
'HTTPCode_Backend_2XX':'Sum',
'HTTPCode_Backend_4XX':'Sum',
'HTTPCode_Backend_5XX':'Sum',
'RequestCount':'Sum',
'HealthyHostCount':'Maximum',
'UnhealthyHostCount':'Maximum',
'TargetResponseTime': 'Average',
'RequestCountPerTarget': 'Sum'
}
if column not in unitlist:
return 'Average'
else:
return unitlist[column]
if __name__ == '__main__':
main()
def main():
AKEY = sys.argv[1]
SAKEY = sys.argv[2]
HOSTNAME = sys.argv[3]
REGION = 'ap-northeast-1'
ELB_NAME = HOSTNAME
cw_client = get_client(AKEY, SAKEY, REGION, SERVICE='cloudwatch')
alb_client = get_client(AKEY, SAKEY, REGION, SERVICE='elbv2')
send_items(cw_client, alb_client, ELB_NAME)
aws_monitoring.sh (アクセスキーはインスタンスプロファイル/credential等使用していれば不必要です)
AWS_KEY=hoge
AWS_SAKEY=fuga
python aws_monitoring.py $AWS_KEY $AWS_SAKEY $1
senderするスクリプトを定期実行する
定期実行するには
- cronとして仕込む
- zabbix itemの
External check
で定期実行させる。
今回はExternal check
を使って実装します(以下が詳しいです)
https://www.zabbix.com/documentation/3.4/manual/config/items/itemtypes/external
https://www.zabbix.com/documentation/3.4/manual/appendix/command_execution
-
zabbix_server.cfg
のExternalScripts
に上記のスクリプトを配置します - zabbix itemを設定します
- type: External check
- key: aws_monitoring.sh[{HOST.HOST} (ここの引数は適宜変えてください)
- Update interval: 300 (監視間隔なので適宜変えてください)
zabbix trapperを配置する
- zabbix itemを設定します (HealthyHostCountの場合)
- type: Zabbix Trapper
- key: alb.HealthyHostCount
- Type of information: Numeric(float)
配置すれば終了。あとはLatest Dataでデータが反映されているか確認しましょう。
結論
この辺りを応用するとcloud watchの情報を使ってzabbixで監視ができる。
cloud watchのAPIは有料なので長い期間を連続して取得しないようにする。
https://aws.amazon.com/jp/cloudwatch/pricing/