ZabbixでAWS ALBの監視をする
ZabbixでAWS ALBの監視をする:
AWS ALBは
Cloud Watchからの情報はAPIを経由して取得する必要があります。
なので今回は
1. external scriptsに
2. zabbix server側でzabbix trapperを使ってzabbix senderで送られた情報をキャッチする
3. そのitemでアラートを出すようにする
zabbix trapper等の情報は以下が詳しいです。
https://www.zabbix.com/documentation/3.0/manual/config/items/itemtypes/trapper
基本pythonで以下の感じで実装をしました。
aws_monitoring.sh (アクセスキーはインスタンスプロファイル/credential等使用していれば不必要です)
定期実行するには
- cronとして仕込む
- zabbix itemの
今回は
https://www.zabbix.com/documentation/3.4/manual/config/items/itemtypes/external
https://www.zabbix.com/documentation/3.4/manual/appendix/command_execution
この辺りを応用するとcloud watchの情報を使ってzabbixで監視ができる。
cloud watchのAPIは有料なので長い期間を連続して取得しないようにする。
https://aws.amazon.com/jp/cloudwatch/pricing/
前提
- zabbix3.4
- ALBに紐づいているTargetGroupのヘルスチェックが通っているかを確認したい
構成
AWS ALBはHealthyHostCount
という情報をCloud watchに保存しています。Cloud Watchからの情報はAPIを経由して取得する必要があります。
なので今回は
1. external scriptsに
APIを打ってzabbix senderでcloud watchの情報を送るスクリプト
を配置する2. zabbix server側でzabbix trapperを使ってzabbix senderで送られた情報をキャッチする
3. その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を実行。
#!/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_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)
結論
この辺りを応用するとcloud watchの情報を使ってzabbixで監視ができる。cloud watchのAPIは有料なので長い期間を連続して取得しないようにする。
https://aws.amazon.com/jp/cloudwatch/pricing/
コメント
コメントを投稿