この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
はじめに
最近、お気に入りの札幌ランチは炎のランチバイキングの横山です。 以下の記事を参考にCloudWatchのカスタムメトリクスを登録スクリプトをGoで作ったものをMacでビルドを行い、CentOS5で実行するまでの手順をまとめました。
前提
- ビルドするMac
$ sw_vers -productVersion
10.10.2
$ brew --version
0.9.5
- 実行するCentOS5
- IAM Roleなし
- Goをビルドする環境なし
- PutMetricsDataを行う権限あり
$ uname -a
Linux ip-xxx-xxx-xxx-xxx 2.6.21.7-2.fc8xen #1 SMP Fri Feb 15 12:34:28 EST 2008 x86_64 x86_64 x86_64 GNU/Linux
$ cat /etc/redhat-release
CentOS release 5.4 (Final)
今回準備したソース
- putMetricsData.go
package main
import (
"fmt"
"strings"
"flag"
"os"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/gen/cloudwatch"
)
func main() {
var nameSpace, metricName, unit, region, dimensions string
var value float64
accessKey := os.Getenv("AWS_ACCESS_KEY_ID")
secretKey := os.Getenv("AWS_SECRET_ACCESS_KEY")
if accessKey == "" || secretKey == "" {
fmt.Println("Error: Undefined AWS_ACCESS_KEY_ID or AWS_SECRET_ACCESS_KEY")
os.Exit(9)
}
creds := aws.Creds( accessKey,
secretKey,
"" )
flag.StringVar(&nameSpace, "namespace", "", "")
flag.StringVar(&metricName, "metric-name", "", "")
flag.StringVar(&unit,"unit", "", "")
flag.StringVar(®ion, "region", "", "")
flag.StringVar(&dimensions, "dimensions", "", "")
flag.Float64Var(&value, "value", 0, "")
flag.Parse()
if len(dimensions) == 0 {
fmt.Println("error: --dimensions value empty!")
return
}
cli := cloudwatch.New(creds, region, nil)
dimension_strings := strings.Split(dimensions, ",")
dimension_items := make([]cloudwatch.Dimension, len(dimension_strings))
for index, dimension_string := range dimension_strings {
var items = strings.SplitN(dimension_string, "=", 2)
if len(items) > 1 {
dimension_items[index].Name = aws.String(items[0])
dimension_items[index].Value = aws.String(items[1])
}
}
metricDataParam := &cloudwatch.MetricDatum {
Dimensions: dimension_items,
MetricName: aws.String(metricName),
Unit: aws.String(unit),
Value: aws.Double(value),
}
putMetricDataInput := &cloudwatch.PutMetricDataInput{
MetricData: []cloudwatch.MetricDatum{*metricDataParam},
Namespace: aws.String(nameSpace),
}
fmt.Println(cli.PutMetricData(putMetricDataInput))
}
- memoryUsage.sh
#!/bin/bash
export AWS_ACCESS_KEY_ID="AKIAxxxxxxxxxxxxxxxx"
export AWS_SECRET_ACCESS_KEY="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
program="./putMetricsData"
usage=$(free | head -n 3 | tail -n 1 | awk '{a = $3/($3 + $4)*100; print a}')
instanceId=$(curl -s http://169.254.169.254/latest/meta-data/instance-id)
region=$(curl -s http://169.254.169.254/latest/meta-data/placement/availability-zone | sed -e 's/.$//')
cw_opts="--namespace Classmethod/EC2"
cw_opts=${cw_opts}" --metric-name MemoryUtilization"
cw_opts=${cw_opts}" --dimensions InstanceId=${instanceId}"
cw_opts=${cw_opts}" --unit Percent"
cw_opts=${cw_opts}" --region ${region}"
cw_opts=${cw_opts}" --value ${usage}"
${program} ${cw_opts}
クロスコンパイルするための準備
すでにgoをインストールしている場合、クロスコンパイルを行おうとすると次の様なエラーが出ると思います。
$ GOOS=linux GOARCH=amd64 go build putMetricsData.go
go build runtime: linux/amd64 must be bootstrapped using make.bash
手動でできるかもですが、楽するために一度brewからGoをアンインストールし、 --with-cc-allオプション使ってインストールし直します。
$ brew uninstall go
Uninstalling /usr/local/Cellar/go/1.4.1...
$ brew install go --with-cc-all
==> Downloading https://storage.googleapis.com/golang/go1.4.1.src.tar.gz
######################################################################## 100.0%
==> ./make.bash --no-clean
==> ./make.bash --no-clean
==> ./make.bash --no-clean
==> ./make.bash --no-clean
==> ./make.bash --no-clean
==> ./make.bash --no-clean
==> ./make.bash --no-clean
==> ./make.bash --no-clean
==> ./make.bash --no-clean
==> ./make.bash --no-clean
==> ./make.bash --no-clean
==> ./make.bash --no-clean
==> ./make.bash --no-clean
==> ./make.bash --no-clean
==> ./make.bash --no-clean
==> ./make.bash --no-clean
==> ./make.bash --no-clean
==> ./make.bash --no-clean
==> ./make.bash --no-clean
==> ./make.bash --no-clean
==> Caveats
As of go 1.2, a valid GOPATH is required to use the `go get` command:
http://golang.org/doc/code.html#GOPATH
`go vet` and `go doc` are now part of the go.tools sub repo:
http://golang.org/doc/go1.2#go_tools_godoc
To get `go vet` and `go doc` run:
go get golang.org/x/tools/cmd/vet
go get golang.org/x/tools/cmd/godoc
You may wish to add the GOROOT-based install location to your PATH:
export PATH=$PATH:/usr/local/opt/go/libexec/bin
==> Summary
瑳 /usr/local/Cellar/go/1.4.1: 7696 files, 1.5G, built in 19.3 minutes
参考
ビルド
- Mac上
$ GOOS=linux GOARCH=amd64 go build putMetricsData.go
$ file putMetricsData
putMetricsData: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, not stripped
実行
scpやFileZillaなどつかってCentOS5にバイナリを持っていきます。
実行し、問題がなければ出力に<nil>が表示されます。(失敗、問題があるとエラーが表示されます)
$ sh memoryUsage.sh
<nil>
エラー例
- PutMetricDataを行う権限がない場合
$ sh memoryUsage.sh
User: arn:aws:iam::xxxxxxxxxxxx:user/test_putmetrics is not authorized to perform: cloudwatch:PutMetricData
- IAM Roleがない場合
$ sh memoryUsage.sh
decoding <?xml version="1.0" encoding="iso-8859-1"?> IAM credentials
まとめ
以上、CentOS5のみですがクロスコンパイルの実行が確認できました。 これにより、監視するインスタンスにGoをインストールせずにバイナリを設置するだけで、Python2.6が入ってなくても、aws-cliが入ってなくてもカスタムメトリクスをCloudWatchに登録することが出来そうです。
また、確認はしてませんがRaspberryPiにGoのビルド環境を導入せずとも、Macでビルド後RaspberryPi側にバイナリだけ持っていけば動くということも出来そうです(未確認)。