Mackerelを使ったAlibaba Cloud監視ソリューション

システムを運用する場合には第三者の監視サービスを利用してシステムをコントロールする方法がよく使われます。メリットとしてはハイブリッド環境やカスタム監視が可能ですし、災害などの突発状況でも分かれた地域から常に監視できるなどがあります。本記事では、サードパーティ監視サービスMackerelを使ってAlibaba Cloudをモニタリングする方法をご紹介します。

課題

CloudMonitor

Alibaba CloudではCloudMonitorという監視機能があります。操作が簡単だし、リソースのメトリックの収集、インターネットサービスの可用性の検出、メトリックに関するアラーム設定など便利なツールも利用できます。しかし、CloudMonitorは基本的にAlibaba Cloudのプロダクトのメトリックしか監視できない課題があります。例えばAlibaba Cloudとオンプレミスのハイブリッドシステム環境やユーザーのカスタムデータの監視などの場合にはCloudMonitorでは対応が難しいです。

Mackerel

Mackerelははてなが開発したサーバ管理・監視ツールです。運用中のクラウドもしくはオンプレミスのサーバにエージェントを入れることで簡単にサーバ管理を始められ、統合管理および監視が便利にできます。しかし、サーバを監視するにはMackerelのエイジェントをインストールする必要があります。Alibaba Cloudでシステムを構築した場合、ECSだけではなくRDS、OSS、SLBなど色んなプロダクトの監視が必要であり、エイジェントのインストールができなく、それらを一括で監視することが難しくなります。

監視ソリューション

上記の紹介通り、CloudMonitorとMackerelはそれぞれのメリットとデメリットがあります。Alibaba Cloudを監視するため、ECSはMackerel、他のプロダクトはCloudMonitorを使う方法もありますが、こう言った監視を2つに分ける状況は運用現場で色んな問題が出るから望ましくない方法です。

ところで、Mackerelにはカスタムメトリック監視の機能があり、カスタムメトリックを定期的にエージェントから投稿できます。これを利用することでCloudMonitorとMackerelを連携した監視ソリューションができます。具体的な内容は次の2つに分けて説明します。

  1. CloudMonitor SDKを使ってAlibaba Cloudの監視データを読み取る
  2. 読み取ったデータを監視用ECSでMackerelに転送する

1. CloudMonitor SDKを使ってAlibaba Cloudの監視データを読み取る

Alibaba Cloudのプロダクトのメトリックは常にCloudMonitorサーバに蓄積されています。ここで、CloudMonitor SDKを使ってCloudMonitorサーバからデータを読み取って見ます。ちなみに、本記事はpythonでプログラムを実現するので、事前にpythonとpipのインストルをしてください。

1. まず、aliyuncliの環境を作る

$ pip install aliyuncli
$ aliyuncli configure

ここでaccess keyの設定が必要です。accsess keyの作成はコンソールで行います。

2. 必要なpython sdkをインストールする

$ pip install aliyun-python-sdk-core
$ pip install aliyun-python-sdk-cms

これで必要なSDKの設定が完了しました。

3. python sdkを使って監視データ読み取る

下記は監視データ読み取るためのテストコードです。

from aliyunsdkcore import client
from aliyunsdkcms.request.v20170301 import QueryMetricListRequest
import time

#client登録
clt = client.AcsClient('your_accesskey','accesskey_passowrd','cn-hangzhou')
#objectを作る
request = QueryMetricListRequest.QueryMetricListRequest()
#インスタンス選択、JSON形式で複数選択可能
request.set_Dimensions("{'instanceId':'your_instanceID'}") 
#outbut形式 text,json,table
request.set_accept_format('json')
#監視モード
request.set_Project('acs_rds') # acs_ecs, acs_rds, acs_slbなど
#監視データ
request.set_Metric('DiskUsage') #CPUUtilization ,CpuUsage,PacketTXなど

#時間選択
start_time = "2017-06-21 11:40:00"
end_time = "2017-06-21 12:50:00"
timestamp_start = int(time.mktime(time.strptime(start_time, "%Y-%m-%d %H:%M:%S"))) * 1000
timestamp_end = int(time.mktime(time.strptime(end_time, "%Y-%m-%d %H:%M:%S"))) * 1000
request.set_StartTime(timestamp_start)
request.set_EndTime(timestamp_end)

#監視周期
request.set_Period('300') #ECS,SLBは60の、RDSは300の倍数

ここで、RDSの監視ログを読んて検証結果を確認しましょう。

#object action
result = clt.do_action(request)
print result
{"Period":"300","Datapoints":[{"timestamp":1498016700000,"Maximum":23.5,"userId":"5450581093456520","Minimum":23.5,"instanceId":"your_instanceID","Average":23.5,"type":"DiskUsage"},{"timestamp":1498017000000,"Maximum":23.5,"userId":"5450581093456520","Minimum":23.5,"instanceId":"your_instanceID","Average":23.5,"type":"DiskUsage"},{"timestamp":1498017300000,"Maximum":23.5,"userId":"5450581093456520","Minimum":23.5,"instanceId":"your_instanceID","Average":23.5,"type":"DiskUsage"}],"RequestId":"0DAF457B-1627-48FE-A0ED-7194350C558F","Success":true,"Code":"200"}

様々な利用環境に応じて、下のリンクに必要な情報をまとめました。

  1. CloudMonitor SDKのメトリック関連紹介
  2. python SDKのサンプルコード

後、読み取ったデータを利用するにはデータのポストプロセッシングが必要です。その部分はMackerelの説明のサンプルコードをご参照ください。

2.データを監視用ECSでMackerelに転送する

1. Mackerelサイトにログインし、「スタートガイド」の通りに監視用ECSにエイジェントを設置します。

2. エージェントの設定ファイルを開き

$ vi /etc/mackerel-agent/mackerel-agent.conf

下記の内容を追加します。

[plugin.metrics.vmstat]
command = "python /path/to/vmstat-metrics.py"

これは指定のコマンドを定期的に実行し、エイジェントからカスタムデータをMackerelに送る内容です。

3. サンプルコードを作成します。

$ vi /path/to/vmstat-metrics.py

ファイルにコードを書き込みます。

import os
import sys

#パッケージが見つからない場合、手動でpathを使いします
#sys.path.append("/your_path_to_packages")

from aliyunsdkcore import client
from aliyunsdkcms.request.v20170301 import QueryMetricListRequest
import time
import datetime
import json  
from random import randint
from collections import defaultdict

def multi_dimension_dict(dimension, callable_obj=int):
    nodes = defaultdict(callable_obj)
    for i in range(dimension-1):
        p = nodes.copy()
        nodes = defaultdict(lambda : defaultdict(p.default_factory))
    return nodes

def cloudmonitor_ecs():
    clt = client.AcsClient('LTAIW9Li9PyBsd9S','HXH0rjLEAQEis3UlDwP0rnwCuW5oJn','cn-hangzhou') #cn-hangzhou, ap-northeast
    request = QueryMetricListRequest.QueryMetricListRequest()
    request.set_Dimensions("{'instanceId':'i-6wegs3tcjgo98oy9wqsh'}") 
    request.set_accept_format('json')
    request.set_Project('acs_ecs') # acs_ecs, acs_rds, acs_slb
    request.set_Metric('CPUUtilization') #CPUUtilization ,CpuUsage,PacketTX
    date_time = (datetime.datetime.now() - datetime.timedelta(minutes = 10)).strftime("%Y-%m-%d %H:%M:%S")#1m37.5s 
    timestamp = int(time.mktime(time.strptime(date_time, "%Y-%m-%d %H:%M:%S"))) * 1000
    request.set_StartTime(timestamp)
    result = clt.do_action(request)
    results = json.loads(json.dumps(json.loads(result)["Datapoints"]))[-1]
    res_time = (results["timestamp"] + 3600000)/1000
    print('\t'.join(['CMtest.metrics.ecs_cpu', str(results["Average"]), str(res_time)]))

def cloudmonitor_rds():
    clt = client.AcsClient('LTAIW9Li9PyBsd9S','HXH0rjLEAQEis3UlDwP0rnwCuW5oJn','cn-hangzhou') #cn-hangzhou, ap-northeast
    request = QueryMetricListRequest.QueryMetricListRequest()
    request.set_Dimensions("{'instanceId':'rm-e9bibkvcn2ok889a3'}") 
    request.set_accept_format('json')
    request.set_Project('acs_rds') # acs_ecs, acs_rds, acs_slb
    request.set_Metric('DiskUsage') #CPUUtilization ,CpuUsage,PacketTX
    date_time = (datetime.datetime.now() - datetime.timedelta(minutes = 10) - datetime.timedelta(seconds = 0)).strftime("%Y-%m-%d %H:%M:%S")#1m37.5s 
    timestamp = int(time.mktime(time.strptime(date_time, "%Y-%m-%d %H:%M:%S"))) * 1000
    request.set_StartTime(timestamp)
    result = clt.do_action(request)
    results = json.loads(json.dumps(json.loads(result)["Datapoints"]))[-1]
    res_time = (results["timestamp"] + 3600000)/1000
    print('\t'.join(['CMtest.metrics.rds_disk', str(results["Average"]), str(res_time)]))
    
def cloudmonitor_slb():
    clt = client.AcsClient('LTAIW9Li9PyBsd9S','HXH0rjLEAQEis3UlDwP0rnwCuW5oJn','cn-hangzhou') #cn-hangzhou, ap-northeast
    request = QueryMetricListRequest.QueryMetricListRequest()
    request.set_Dimensions("{'instanceId':'lb-e9bexje9dwny5ywo0gn4f'}") 
    request.set_accept_format('json')
    request.set_Project('acs_slb') # acs_ecs, acs_rds, acs_slb
    request.set_Metric('TrafficRXNew') #CPUUtilization ,CpuUsage,PacketTX
    date_time = (datetime.datetime.now() - datetime.timedelta(minutes = 10) - datetime.timedelta(seconds = 0)).strftime("%Y-%m-%d %H:%M:%S")#1m37.5s 
    timestamp = int(time.mktime(time.strptime(date_time, "%Y-%m-%d %H:%M:%S"))) * 1000
    request.set_StartTime(timestamp)
    result = clt.do_action(request)
    results = json.loads(json.dumps(json.loads(result)["Datapoints"]))[-1]
    res_time = (results["timestamp"] + 3600000)/1000
    print('\t'.join(['CMtest.metrics.slb_traffic', str(results["Average"]), str(res_time)]))

if(os.environ.get('MACKEREL_AGENT_PLUGIN_META') == '1'):
    meta = multi_dimension_dict(2)
    metrics = [{'name':'ecs_cpu','label':'ECS(cpu)'},{'name':'rds_disk','label':'RDS(cpu)'},{'name':'slb_traffic','label':'ECS(cpu)'}]
    meta['graphs']['CMtest.metrics'] = {'label': 'metrics', 'unit': 'integer', 'metrics': metrics}
    print(json.dumps(meta))
    sys.exit(0)

cloudmonitor_ecs()
cloudmonitor_rds()
cloudmonitor_slb()

4. エイジェントを再起動すると、Mackerelコンソールから監視結果を確認できます。

$ systemctl restart mackerel-agent

下のグラフからECS、RDS、SLBのデータがうまく監視できるのを確認できます。

まとめ

本記事ではCloudMonitorとMackerelを連携したAlibaba Cloudの監視ソリューションを紹介しました。メリットとして

  1. ハイブリッドシステム環境
  2. カスタムメトリクスを監視できる
  3. 離れた地域で監視することで可用性が高い

などが挙げれます。紹介した方法を活かして、皆さんの本業でぜひ試して見なさい。

参考

  1. CloudMonitor製品紹介
  2. ホストのカスタムメトリックを投稿する
この記事をシェアする