Am 17. Juli zeigte der AWS Cost Explorer Kunden geschätzte Rechnungen in Millionen-, Milliarden- und auf einigen Screenshots sogar Billionenhöhe. Die Zahlen waren falsch, niemandem wurde etwas berechnet, und AWS korrigierte die Daten innerhalb eines Tages. Das Detail, das man sich merken sollte: Zuerst bemerkt haben es die Leute, die Billing-Alerts konfiguriert hatten. Dieser Post zeigt die Grundlagen dafür mit Terraforms aws_budgets_budget, vom einfachen monatlichen Kosten-Alert bis zu Usage-Budgets und Savings-Plan-Utilization-Tracking.

Wer an diesem Morgen LinkedIn oder X öffnete, sah überall dasselbe: Screenshots von AWS-Rechnungsschätzungen mit mehr Stellen als so mancher Staatshaushalt. Ein Nutzer, der im Vormonat 0,19 Dollar gezahlt hatte, sah eine Schätzung von fast 2,5 Milliarden Dollar. Andere posteten Zahlen von bis zu 2,5 Billionen Dollar.

Was passiert ist

Um 1:33 Uhr Pacific Time meldete AWS im Health Dashboard, der Cost Explorer zeige "reflecting inaccurate estimated billing data", also fehlerhafte geschätzte Abrechnungsdaten. Die Ursache war laut AWS "an issue with unit pricing within the estimated billing computation subsystem", ein Problem mit den Stückpreisen im Subsystem für die Rechnungsschätzung. Kurz gefasst:

  • Die Zahlen waren Schätzungen, keine tatsächliche Nutzung und keine tatsächlichen Kosten.
  • Niemandem wurde etwas berechnet, und Kunden mussten nichts tun.
  • AWS hat die Daten nachträglich korrigiert, am 18. Juli waren die Zahlen wieder normal.

Und jetzt der interessante Teil: Viele haben von dem Bug durch eine E-Mail über einen überschrittenen Abrechnungsschwellenwert erfahren, Betreff sinngemäß billing threshold exceeded. Accounts mit konfigurierten Alerts entdeckten die Anomalie innerhalb von Minuten. Accounts ohne erfuhren es über Social Media, oder gar nicht.

Diesmal war es ein Fehlalarm. Ein vergessenes NAT Gateway, eine Lambda in einer Retry-Schleife oder ein geleakter Access Key produziert dagegen eine Rechnung, die sehr real ist. Diese Woche ist also ein guter Zeitpunkt, Billing-Alerts einzurichten, und zwar mit Code statt mit Klicks in der Konsole.

Warum IaC und nicht die Konsole

Ein in der Konsole angelegter Alert lebt in einem Account und im Gedächtnis einer einzelnen Person. Mit Terraform:

  • Er liegt in der Versionskontrolle. Wer was wann geändert hat, ist sichtbar.
  • Neuer Account? Dasselbe Modul anwenden, der Standard bleibt erhalten.
  • Eine Schwellenwert-Änderung ist ein Pull Request, der durch das Review geht.

Die Arbeit erledigt die Resource aws_budgets_budget, ein Wrapper um AWS Budgets.

1. Ein monatliches Kostenbudget mit E-Mail-Alert

Ein monatliches Budget von 100 Dollar, das dir eine E-Mail schickt, sobald die tatsächlichen Ausgaben 80% überschreiten:

resource "aws_budgets_budget" "monthly_cost" {
  name         = "monthly-cost-budget"
  budget_type  = "COST"
  limit_amount = "100"
  limit_unit   = "USD"
  time_unit    = "MONTHLY"

  notification {
    comparison_operator        = "GREATER_THAN"
    threshold                  = 80
    threshold_type             = "PERCENTAGE"
    notification_type          = "ACTUAL"
    subscriber_email_addresses = ["ops@example.com"]
  }
}

2. Frühwarnung auf Prognosebasis

Mit notification_type = "FORECASTED" warnt AWS, bevor das Geld ausgegeben ist: dann, wenn die Prognose zum Monatsende das Budget zu sprengen droht. In Kombination mit einer ACTUAL-Notification sind beide Richtungen abgedeckt:

resource "aws_budgets_budget" "with_forecast" {
  name         = "monthly-cost-budget"
  budget_type  = "COST"
  limit_amount = "100"
  limit_unit   = "USD"
  time_unit    = "MONTHLY"

  # Frühwarnung, wenn die Prognose das Budget überschreiten wird
  notification {
    comparison_operator        = "GREATER_THAN"
    threshold                  = 100
    threshold_type             = "PERCENTAGE"
    notification_type          = "FORECASTED"
    subscriber_email_addresses = ["ops@example.com"]
  }

  # Erneute Warnung, wenn die tatsächlichen Ausgaben 90% überschreiten
  notification {
    comparison_operator        = "GREATER_THAN"
    threshold                  = 90
    threshold_type             = "PERCENTAGE"
    notification_type          = "ACTUAL"
    subscriber_email_addresses = ["ops@example.com"]
  }
}

3. Slack oder PagerDuty über SNS

E-Mails gehen unter. Schick den Alert stattdessen an ein SNS-Topic und verdrahte das Topic mit einem Slack-Webhook oder PagerDuty:

resource "aws_sns_topic" "billing_alerts" {
  name = "billing-alerts"
}

resource "aws_budgets_budget" "sns_alert" {
  name         = "monthly-cost-budget-sns"
  budget_type  = "COST"
  limit_amount = "100"
  limit_unit   = "USD"
  time_unit    = "MONTHLY"

  notification {
    comparison_operator       = "GREATER_THAN"
    threshold                 = 80
    threshold_type            = "PERCENTAGE"
    notification_type         = "ACTUAL"
    subscriber_sns_topic_arns = [aws_sns_topic.billing_alerts.arn]
  }
}

Die Falle dabei: Die Topic-Policy muss dem Service Principal budgets.amazonaws.com die Aktion SNS:Publish erlauben. Ohne sie kann Budgets nicht zustellen, und die Alerts verschwinden lautlos. Auf der Budget-Seite gibt es keinen Fehler.

4. Ein Budget pro Service

Um einen einzelnen Service zu beobachten, etwa EC2, kommt ein cost_filter dazu:

resource "aws_budgets_budget" "ec2_only" {
  name         = "ec2-monthly-budget"
  budget_type  = "COST"
  limit_amount = "50"
  limit_unit   = "USD"
  time_unit    = "MONTHLY"

  cost_filter {
    name   = "Service"
    values = ["Amazon Elastic Compute Cloud - Compute"]
  }

  notification {
    comparison_operator        = "GREATER_THAN"
    threshold                  = 80
    threshold_type             = "PERCENTAGE"
    notification_type          = "ACTUAL"
    subscriber_email_addresses = ["ops@example.com"]
  }
}

5. Ein Usage-Budget: 3 GB S3

Bei FinOps geht es nicht nur um Dollar; auch den Verbrauch im Blick zu behalten gehört dazu. Mit budget_type = "USAGE" wird das Budget in Nutzungseinheiten statt in Währung definiert. Ein Budget, das S3-Storage bei 3 GB deckelt:

resource "aws_budgets_budget" "s3" {
  name         = "s3-3GB-limit"
  budget_type  = "USAGE"
  limit_amount = "3"
  limit_unit   = "GB"
  time_unit    = "MONTHLY"

  notification {
    comparison_operator        = "GREATER_THAN"
    threshold                  = 80
    threshold_type             = "PERCENTAGE"
    notification_type          = "ACTUAL"
    subscriber_email_addresses = ["ops@example.com"]
  }
}

Nützlich für Side Projects, die im Free Tier bleiben sollen, und um die Frage "warum wächst dieser Bucket" zu klären, bevor sie zu einem Posten auf der Rechnung wird.

6. Ein Savings-Plan-Utilization-Budget

Die andere Hälfte von FinOps: Mehrausgaben zu erwischen ist wichtig, den im Voraus bezahlten Rabatt nicht zu verschwenden genauso. Wer einen Savings Plan gekauft hat und ihn schlecht auslastet, verbrennt Geld mit dem Commitment, während die Workloads anderswo on-demand laufen. Genau das trackt der Budget-Typ SAVINGS_PLANS_UTILIZATION:

resource "aws_budgets_budget" "savings_plan_utilization" {
  name         = "savings-plan-utilization"
  budget_type  = "SAVINGS_PLANS_UTILIZATION"
  limit_amount = "100.0"
  limit_unit   = "PERCENTAGE"
  time_unit    = "MONTHLY"

  cost_types {
    include_credit             = false
    include_discount           = false
    include_other_subscription = false
    include_recurring          = false
    include_refund             = false
    include_subscription       = true
    include_support            = false
    include_tax                = false
    include_upfront            = false
    use_blended                = false
  }

  notification {
    comparison_operator        = "LESS_THAN"
    threshold                  = 90
    threshold_type             = "PERCENTAGE"
    notification_type          = "ACTUAL"
    subscriber_email_addresses = ["finops@example.com"]
  }
}

Beachte den umgekehrten Operator: comparison_operator = "LESS_THAN". Der Alert feuert nicht, wenn die Ausgaben steigen, sondern wenn die Auslastung unter 90% fällt. Dasselbe Muster funktioniert für Reserved Instances mit RI_UTILIZATION.

Fazit

Die Billionen-Screenshots vom 17. Juli waren ein Anzeigefehler. Niemand hat dieses Geld bezahlt, und AWS hat die Daten innerhalb eines Tages korrigiert. Die Lektion gilt trotzdem: Eine Anomalie in der Rechnung sollte dich über deine eigenen Alerts erreichen, nicht über deine Timeline.

  • Definiere ein monatliches Budget mit aws_budgets_budget.
  • Kombiniere FORECASTED- und ACTUAL-Notifications für eine zweistufige Warnung.
  • Route Alerts über SNS in einen Kanal, den das Team wirklich liest.
  • Vervollständige das Bild mit Usage-Budgets (3 GB S3) und Savings-Plan-Utilization-Tracking.

Wenn das nächste Mal "meine AWS-Rechnung ist explodiert" trendet, kannst du in Ruhe beim Kaffee zuschauen. Hintergrund zum Vorfall: The Register und TechCrunch haben live berichtet.

Lies das als Nächstes

Referenzen