今回はまずCloudWatchで課金情報項目を引っ張り出して、ZabbixのLow Level Discoveryで拾えるように加工するところまでやってみます。
AWS CLIをインストール
今回は、オンプレミス環境に置いてあるCentOS 6上から監視するイメージです。まずはAWS APIを利用するために、AWSコマンドラインインターフェース ツール(AWS CLI)を導入します。
AWS CLIはPython pip経由でインストールするのが手っ取り早いので、EPELのpython-pip経由で導入。
# yum install python-pip
# python-pip awscli
# aws configure
jqのインストール
AWS CLIの出力は基本的にJSONフォーマットになるので、整形したり編集したりをコマンドラインで出来る jq コマンドを導入します。# yum install jq
ZabbixのLow Level Discoveryが受け付けるJSONフォーマット
Zabbix 2.0 Manual - 3.4. Creating custom LLD rules を見ると分かる…と思うのですが、簡単にまとめてみました。
- 最上位となる要素は辞書(Dictionary)。
- 内容は キー "data"、値はディスカバリした結果を格納した配列(Array)。
- 例)
{ "data": [ディスカバリー結果] } - [ディスカバリ結果]は、それぞれZabbixマクロの変数名と同じキーと、それに対する値を持つ辞書の配列。
- 例)
[{ "{#FS_NAME}":"/", "{#FS_TYPE}":"ufs" }, { "{#FS_NAME}":"/boot", "{#FS_TYPE}":"ufs" }] - 変数名に使えるのは "A-Z , 0-9 , _ , ."のいずれか。
※英小文字は使えないので注意。 - 組み立ててみて、下記のような感じになるとOK
{ "data": [ { "{#FS_NAME}":"/", "{#FS_TYPE}":"ufs" }, { "{#FS_NAME}":"/boot", "{#FS_TYPE}":"ufs" }
] }
AWS CloudWatchの課金情報メトリックのフォーマット
AWS CLI経由で課金情報のメトリック一覧を出力させてみます。
※その月に利用したサービスに応じて、出力されるメトリック(項目)は増減します。
※その月に利用したサービスに応じて、出力されるメトリック(項目)は増減します。
# aws cloudwatch --region us-east-1 list-metrics | jq "." | head -n 30
{
"Metrics": [
{
"MetricName": "EstimatedCharges",
"Dimensions": [
{
"Value": "AmazonEC2",
"Name": "ServiceName"
},
{
"Value": "USD",
"Name": "Currency"
}
],
"Namespace": "AWS/Billing"
},
{
"MetricName": "EstimatedCharges",
"Dimensions": [
{
"Value": "AmazonRoute53",
"Name": "ServiceName"
},
{
"Value": "USD",
"Name": "Currency"
}
],
"Namespace": "AWS/Billing"
},
…
ざっと見た感じ、以下のように変換すると良さそうです。
AWS CLIのJSON | Zabbix LLDのJSON |
.Metrics | .Data |
.Namespace | {#AWS_BILLING_NAMESPACE} |
.MetricName | {#AWS_BILLING_METRIC_NAME} |
(.MetricName + .DimensionsのServiceName) | {#AWS_BILLING_METRIC_DISPLAYNAME} |
(.Dimensions | tostring) | {#AWS_BILLING_METRIC_DIMENSIONS} |
というわけで、jqコマンドで変換するコマンドを組み立ててみる。。。
(試行錯誤すること 2時間ほど…)
できました!
# aws cloudwatch --region us-east-1 list-metrics | jq '.Metrics[] | {
"{#AWS_BILLING_NAMESPACE}": (.Namespace),
"{#AWS_BILLING_METRIC_NAME}": (.MetricName),
"{#AWS_BILLING_METRIC_DISPLAYNAME}": (.MetricName + " - " + ((.Dimensions[] | select(.Name=="ServiceName") | .Value) // "total") ),
"{#AWS_BILLING_METRIC_DIMENSIONS}": (.Dimensions | tostring)
}' | jq -s '{data:(.|sort)}'
ためしてみる!
# aws cloudwatch --region us-east-1 list-metrics | jq '.Metrics[] | {
"{#AWS_BILLING_NAMESPACE}": (.Namespace),
"{#AWS_BILLING_METRIC_NAME}": (.MetricName),
"{#AWS_BILLING_METRIC_DISPLAYNAME}": (.MetricName + " - " + ((.Dimensions[] | select(.Name=="ServiceName") | .Value) // "total") ),
"{#AWS_BILLING_METRIC_DIMENSIONS}": (.Dimensions | tostring)
}' | jq -s '{data:(.|sort)}'
{
"data": [
{
"{#AWS_BILLING_NAMESPACE}": "AWS/Billing",
"{#AWS_BILLING_METRIC_NAME}": "EstimatedCharges",
"{#AWS_BILLING_METRIC_DISPLAYNAME}": "EstimatedCharges - AWSDataTransfer",
"{#AWS_BILLING_METRIC_DIMENSIONS}": "[{\"Value\":\"AWSDataTransfer\",\"Name\":\"ServiceName\"},{\"Value\":\"USD\",\"Name\":\"Currency\"}]"
},
{
"{#AWS_BILLING_NAMESPACE}": "AWS/Billing",
"{#AWS_BILLING_METRIC_NAME}": "EstimatedCharges",
"{#AWS_BILLING_METRIC_DISPLAYNAME}": "EstimatedCharges - AmazonEC2",
"{#AWS_BILLING_METRIC_DIMENSIONS}": "[{\"Value\":\"AmazonEC2\",\"Name\":\"ServiceName\"},{\"Value\":\"USD\",\"Name\":\"Currency\"}]"
},
{
"{#AWS_BILLING_NAMESPACE}": "AWS/Billing",
"{#AWS_BILLING_METRIC_NAME}": "EstimatedCharges",
"{#AWS_BILLING_METRIC_DISPLAYNAME}": "EstimatedCharges - AmazonRoute53",
"{#AWS_BILLING_METRIC_DIMENSIONS}": "[{\"Value\":\"AmazonRoute53\",\"Name\":\"ServiceName\"},{\"Value\":\"USD\",\"Name\":\"Currency\"}]"
}, …
お、上手くいっているっぽい。
ちなみに上記の情報を基に、実際の課金情報を引っ張ってみるとこうなります。
# aws cloudwatch --region us-east-1 get-metric-statistics \
--namespace "AWS/Billing" \
--metric-name "EstimatedCharges" \
--dimensions "[{\"Value\":\"AmazonEC2\",\"Name\":\"ServiceName\"},{\"Value\":\"USD\",\"Name\":\"Currency\"}]" \
--period 60 \
--start-time $(date --iso-8601=seconds --date '24 hour ago') \
--end-time $(date --iso-8601=seconds) \
--statistics "Maximum" \
| jq '.Datapoints | sort_by(.Timestamp)'
[
{
"Unit": "None",
"Maximum": 1.19,
"Timestamp": "2014-01-30T11:34:00Z"
},
{
"Unit": "None",
"Maximum": 1.2,
"Timestamp": "2014-01-30T15:34:00Z"
},
{
"Unit": "None",
"Maximum": 1.2,
"Timestamp": "2014-01-30T19:34:00Z"
},
{
"Unit": "None",
"Maximum": 1.21,
"Timestamp": "2014-01-30T23:34:00Z"
},
{
"Unit": "None",
"Maximum": 1.21,
"Timestamp": "2014-01-31T03:34:00Z"
},
{
"Unit": "None",
"Maximum": 1.21,
"Timestamp": "2014-01-31T07:34:00Z"
}
]
実際には最後の値しか要らなさそうなので、jqコマンドに "reverse | .[0]"を追加することになりそうです。( .[-1]だと上手くいかない )
続きはまた今度。