AWS の Billing Alert(請求アラート)を日々の増加分で設定する

AWS の請求アラートは昔は CloudWatch Alarm を使う必要がありましたが、最近なら AWS Budgets で簡単に設定できます。便利です。

がしかし、AWS Budgets はもっとも短いスパンでも月次の請求額なので、次のようなケースにはフィットしません。

  • 検証用の AWS アカウントなので普段はインスタンスなどを立ち上げておらずまったく費用はかからない
  • たまに検証のためにインスタンスなどを立ち上げたとしてもその日のうちに削除して立ち上げっぱなしにはしない

このケースでアラートしてほしいのは「インスタンスなどを削除し忘れていて課金されっぱなしになっている」ということなので、月次の請求額のアラートではあまり意味がありません。

(もっとも検証用のアカウントでも、だいたい月にこれくらいまで、という予算はあると思うのでそれを超えないようにするための月次のアラートはそれはそれで有用だと思いますが)

ので、CloudWatch Alarm で請求額の日々の増加分に対してアラートを仕込んでみました。

Terraform のテンプレートは次のような感じ。

provider "aws" {
  alias  = "us-east-1"
  region = "us-east-1"
}

variable "alarm_name" {}

resource "aws_sns_topic" "billing" {
  provider = aws.us-east-1
  name     = "BillingAlarm"
}

resource "aws_cloudwatch_metric_alarm" "billing_rate" {
  provider            = aws.us-east-1
  alarm_name          = var.alarm_name
  alarm_description   = "Billing rate over 0.1 USD in 6 hours"
  comparison_operator = "GreaterThanThreshold"
  evaluation_periods  = 1
  datapoints_to_alarm = 1
  threshold           = 0.1
  alarm_actions       = [aws_sns_topic.billing.arn]

  metric_query {
    id = "m1"

    metric {
      namespace   = "AWS/Billing"
      metric_name = "EstimatedCharges"
      period      = 6 * 60 * 60
      stat        = "Maximum"
      dimensions = {
        Currency = "USD"
      }
    }
  }

  metric_query {
    id         = "e1"
    expression = "RATE(m1) * 60 * 60 * 6"
  }

  metric_query {
    id          = "e2"
    expression  = "IF(e1>0, e1, 0)"
    label       = "USD/24H"
    return_data = true
  }
}

RATE 関数でメトリクスの直前値との差分を1秒あたりに換算した変化分が得られます。これに 60 * 60 * 6 して 6 時間分の増分にしています。日々の、と言っておきながら実際には 6 時間分のものになっていますが、請求額のメトリクスがだいたい 6 時間ごとの値なのでそれに合わせています。

月替りでメトリクスが 0 にリセットされるためその際に RATE がマイナス値になります。アラートしきい値としてはそのままでも問題ありませんが、グラフで見たときに変なので IF(e1>0, e1, 0) で 0 以下のメトリクスは 0 としています。

さいごに

結構前から仕込んでいていい感じにアラートしてくれていたのですが、

AWS Budgets で日次予算でアラートが仕込めるようになったようです。よってこの記事の内容はもう用済みです。