AWS SDK for Goでディスク使用率をCloudWatchカスタムメトリクス化する

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

まだまだAWS SDK for Goの話題を続けます。

CloudWatchは様々なシステム情報をモニタリングできるサービスですが、残念ながらメモリ使用率やディスク使用率といった値が取れません。このためAWS CLIやAWS SDKを使ったスクリプトなどを用いて、CloudWatchカスタムメトリクスとして登録することが多いかと思います。しかしAWS CLIにしてもAWS SDKにしても動作環境の整備が必要になります。でもGolangなら、バイナリを作って配置するだけですよね。

ってことで、AWS SDK for Goを使って、ディスク使用率をCloudWatchカスタムメトリクス化してみました。

やってみた

ソースコード

package main

import (
	"flag"
	"io/ioutil"
	"net/http"

	"github.com/awslabs/aws-sdk-go/aws"
	"github.com/awslabs/aws-sdk-go/gen/cloudwatch"
)

func getInstanceId() (instanceId string) {
	resp, _ := http.Get("http://169.254.169.254/latest/meta-data/instance-id")
	defer resp.Body.Close()
	body, _ := ioutil.ReadAll(resp.Body)
	instanceId = string(body)
	return
}

func getRegion() (region string) {
	resp, _ := http.Get("http://169.254.169.254/latest/meta-data/placement/availability-zone")
	defer resp.Body.Close()
	body, _ := ioutil.ReadAll(resp.Body)
	region = string(body)[0 : len(string(body))-1]
	return
}

func main() {
	f := flag.Float64("value", 0, "Value of disk usage.")
	flag.Parse()

	creds := aws.IAMCreds()
	cli := cloudwatch.New(creds, getRegion(), nil)

	dimensionParam := &cloudwatch.Dimension{
		Name:  aws.String("InstanceId"),
		Value: aws.String(getInstanceId()),
	}

	metricDataParam := &cloudwatch.MetricDatum{
		Dimensions: []cloudwatch.Dimension{*dimensionParam},
		MetricName: aws.String("DiskUsage"),
		Unit:       aws.String("Percent"),
		Value:      aws.Double(*f),
	}

	putMetricDataInput := &cloudwatch.PutMetricDataInput{
		MetricData: []cloudwatch.MetricDatum{*metricDataParam},
		Namespace:  aws.String("EC2"),
	}

	cli.PutMetricData(putMetricDataInput)
}

設定

対象のEC2では、IAM RoleによってCloudWatchへのPutMetricDataを許可しています。

go buildして出力されたバイナリファイルを/usr/local/bin/配下に配置し、cronで以下にように設定します。

*/5 * * * * /usr/local/bin/putDiskUsage -value=$(df | sed -e 1d -e 's/\%//' | awk '{print $5}' | sort -r | head -n 1)

実行結果

ちゃんと取れてますね!

CloudWatch_Management_Console

さいごに

Go言語でも簡単にCloudWatchカスタムメトリクスが登録できました!

僕のGo力が低いせいで冗長な書き方になっているので、この辺もっと修行して、綺麗なGoが書けるようになりたいです。