My Note

自己理解のためのブログ

AWS請求額をGoとMackerelで可視化して監視・通知する

はじめに

今回もMackerelを使ってメトリクスを可視化する系の記事です。今回は監視と通知もしています。 AWSの請求額をグラフ化して閾値を超えたらLine通知するようにしました。AWSを利用しすぎて今月の支払額が予算オーバーしたっ!! ...ってならないよにするため。

アーキテクチャ

f:id:yhidetoshi:20190920184424p:plain

  1. CloudWatch EventでLambdaを定期実行
  2. Lmabda ( Go ) でバージニア北部のCloudWatchにAPIでデータを取得
  3. Lambda ( Go ) でMackerelにメトリクスを投げて可視化と監視
  4. 閾値を超えたらMackerelの機能でLINE通知

Lambda ( Go )について

実装はGoとaws-sdk-goとmackerel-client-goを利用しました。 デプロイに関してはServerlessFrameworkで 行いました。付与するIAMロール権限はCloudwatch Readonlyです。

docs.aws.amazon.com

github.com

package main

import (
    "fmt"
    "os"
    "time"

    "github.com/aws/aws-lambda-go/lambda"
    "github.com/aws/aws-sdk-go/aws"
    "github.com/aws/aws-sdk-go/aws/session"
    "github.com/aws/aws-sdk-go/service/cloudwatch"
    "github.com/mackerelio/mackerel-client-go"
)

var (
    mkrKey = os.Getenv("MKRKEY")
    client = mackerel.NewClient(mkrKey)
    config = aws.Config{Region: aws.String(region)}
    cwt    = cloudwatch.New(session.New(&config))
)

const (
    region      = "us-east-1"
    serviceName = "AWS"
    timezone    = "Asia/Tokyo"
    offset      = 9 * 60 * 60
)

func main() {
    lambda.Start(Handler)
}

// Handler Lambda
func Handler() {
    var cost float64

    jst := time.FixedZone(timezone, offset)
    nowTime := time.Now().In(jst)

    input := &cloudwatch.GetMetricStatisticsInput{
        Dimensions: []*cloudwatch.Dimension{
            {
                Name:  aws.String("Currency"),
                Value: aws.String("USD"),
            },
        },
        StartTime:  aws.Time(time.Now().Add(time.Hour * -24)),
        EndTime:    aws.Time(time.Now()),
        Period:     aws.Int64(86400),
        Namespace:  aws.String("AWS/Billing"),
        MetricName: aws.String("EstimatedCharges"),
        Statistics: []*string{
            aws.String(cloudwatch.StatisticMaximum),
        },
    }
    response, err := cwt.GetMetricStatistics(input)
    if err != nil {
        fmt.Println(err)
    }

    for _, v := range response.Datapoints {
        cost = *v.Maximum
    }
    fmt.Println(cost)

    errMkr := PostValuesToMackerel(cost, nowTime)
    if errMkr != nil {
        fmt.Println(errMkr)
    }
}

// PostValuesToMackerel Post Metrics to Mackerel
func PostValuesToMackerel(cost float64, nowTime time.Time) error {
    err := client.PostServiceMetricValues(serviceName, []*mackerel.MetricValue{
        &mackerel.MetricValue{
            Name:  "Cost.cost",
            Time:  nowTime.Unix(),
            Value: cost,
        },
    })
    if err != nil {
        fmt.Println(err)
    }
    return nil
}

結果 ( Mackerelの画面 )

f:id:yhidetoshi:20190920183430p:plain

監視設定とアラート通知 ( LINE )

今回はLineに通知を飛ばす設定にしました! Lineに通知するためのMackerelの設定は以下のページで説明されています。

mackerel.io

アラートの閾値設定をします。とりあえずアラートを発生させるために低く設定しました。

f:id:yhidetoshi:20190920185055p:plain

■ LINEへのアラート通知結果

f:id:yhidetoshi:20190920185555p:plain

デプロイ

  • Mackerelにサービスを登録する
export MKRKEY=XXX

curl -X POST https://api.mackerelio.com/api/v0/services \
    -H "X-Api-Key: ${MKRKEY}" \
    -H "Content-Type: application/json" \
    -d '{"name": "AWS", "memo": "aws cost"}'
make build
  • ServerlessFrameworkでデプロイする
sls deploy --aws-profile <PROFILE> --mkrkey ${MKRKEY}

ソースコード等はこちらにおいています。(MakefileとかserverlessFrameworkのyamlファイルとか)

github.com

さいごに

今回はGoとMackerelを使ってAWSの請求額をグラフ化して監視設定とLINE通知をできるようにしました。 これで、月々どれくらい使ってるのか、急に利用金額が増えても気づけるようになると思います。