1
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

ZabbixでAWS ALBの監視をする

Posted at

前提

  • 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で以下の感じで実装をしました。

  1. シェルスクリプトでpythonを叩く
  2. zabbixで設定されているHost情報から target groupの情報を抜く(ZabbixのMacroとかにTarget情報をいれてもOK)
  3. cloud watchから情報を抜く(今回はメトリクス情報もAPIから毎回引っこ抜いています。)
  4. alb.metrics_nameという形に生成
  5. 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

  1. zabbix_server.cfgExternalScriptsに上記のスクリプトを配置します
  2. zabbix itemを設定します
  • type: External check
  • key: aws_monitoring.sh[{HOST.HOST} (ここの引数は適宜変えてください)
  • Update interval: 300 (監視間隔なので適宜変えてください)

zabbix trapperを配置する

  1. 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/

1
3
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
1
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?