Il 17 luglio AWS Cost Explorer ha mostrato ai clienti stime di fatturazione da milioni, miliardi e, in qualche screenshot, migliaia di miliardi di dollari. I numeri erano sbagliati, nessuno ha pagato nulla e AWS ha corretto i dati entro un giorno. Il dettaglio da ricordare: i primi ad accorgersene sono stati quelli con gli avvisi di fatturazione già configurati. Questo post è la guida di base per configurarli con aws_budgets_budget di Terraform, da un semplice avviso mensile sui costi fino ai budget di utilizzo e al monitoraggio della utilization dei Savings Plan.

Chiunque abbia aperto LinkedIn o X quella mattina ha visto lo stesso feed: screenshot di stime di fatturazione AWS con più cifre di certi bilanci nazionali. Un utente che il mese precedente aveva pagato 0,19 dollari si è trovato una stima di quasi 2,5 miliardi. Altri hanno pubblicato numeri fino a 2.500 miliardi di dollari.

Cosa è successo

All'1:33 di notte, ora del Pacifico, AWS ha pubblicato sull'Health Dashboard che Cost Explorer stava "reflecting inaccurate estimated billing data", cioè mostrava dati di fatturazione stimata inaccurati. La causa, nelle parole di AWS, era "an issue with unit pricing within the estimated billing computation subsystem", un problema di prezzi unitari nel sottosistema che calcola le stime. In breve:

  • I numeri erano stime, non utilizzo o addebiti reali.
  • Nessun addebito è stato effettuato e non era richiesta alcuna azione da parte dei clienti.
  • AWS ha ricaricato i dati e il 18 luglio i numeri erano tornati alla normalità.

Ed ecco la parte interessante: molti hanno scoperto il bug da un'email di soglia di fatturazione superata. Gli account con gli avvisi configurati hanno individuato l'anomalia in pochi minuti. Quelli senza l'hanno saputo dai social, o non l'hanno saputo affatto.

Questa volta era un falso allarme. Un NAT Gateway dimenticato, una Lambda bloccata in un loop di retry o una access key finita in giro producono una fattura decisamente reale. Questa è quindi una buona settimana per configurare gli avvisi di fatturazione, e per farlo con il codice invece che con i clic in console.

Perché IaC e non la console

Un avviso creato in console vive in un solo account e nella memoria di una sola persona. Con Terraform:

  • Vive nel version control. Chi ha cambiato cosa, e quando, è visibile.
  • Nuovo account? Applichi lo stesso modulo e mantieni lo standard.
  • Un cambio di soglia è una pull request che passa dalla review.

La risorsa che fa il lavoro è aws_budgets_budget, che incapsula AWS Budgets.

1. Un budget mensile sui costi con avviso via email

Un budget mensile di 100 dollari che ti manda un'email quando la spesa effettiva supera l'80%:

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. Allerta anticipata basata sulla previsione

Con notification_type = "FORECASTED", AWS ti avvisa prima che i soldi siano spesi, quando la previsione di fine mese è in rotta per sforare il budget. Abbinarla a una notifica ACTUAL copre entrambe le direzioni:

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

  # Avvisa in anticipo se la previsione supererà il budget
  notification {
    comparison_operator        = "GREATER_THAN"
    threshold                  = 100
    threshold_type             = "PERCENTAGE"
    notification_type          = "FORECASTED"
    subscriber_email_addresses = ["ops@example.com"]
  }

  # Avvisa di nuovo quando la spesa effettiva supera il 90%
  notification {
    comparison_operator        = "GREATER_THAN"
    threshold                  = 90
    threshold_type             = "PERCENTAGE"
    notification_type          = "ACTUAL"
    subscriber_email_addresses = ["ops@example.com"]
  }
}

3. Slack o PagerDuty via SNS

Le email si perdono. Manda invece l'avviso a un topic SNS, poi collega il topic a un webhook Slack o a 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]
  }
}

Il punto in cui si sbaglia: la policy del topic deve concedere SNS:Publish al service principal budgets.amazonaws.com. Senza, Budgets non riesce a consegnare e i tuoi avvisi spariscono in silenzio. Sul lato budget non compare alcun errore.

4. Un budget per singolo servizio

Per tenere d'occhio un solo servizio, ad esempio EC2, aggiungi un cost_filter:

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. Un budget di utilizzo: 3 GB di S3

FinOps non significa solo tracciare i dollari; tracciare i consumi fa parte del lavoro. Con budget_type = "USAGE" il budget è definito in unità di utilizzo invece che in valuta. Un budget che limita lo storage S3 a 3 GB:

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"]
  }
}

Utile per i side project che vogliono restare dentro il free tier, e per intercettare il "perché questo bucket sta crescendo" prima che diventi una voce in fattura.

6. Un budget sulla utilization del Savings Plan

L'altra metà del FinOps: intercettare la spesa in eccesso conta, ma conta anche non sprecare lo sconto che hai già pagato in anticipo. Se hai comprato un Savings Plan e la tua utilization è bassa, il commitment brucia soldi mentre i tuoi workload girano on-demand altrove. Il tipo di budget SAVINGS_PLANS_UTILIZATION traccia esattamente questo:

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"]
  }
}

Nota l'operatore invertito: comparison_operator = "LESS_THAN". L'avviso scatta non quando la spesa sale ma quando la utilization scende sotto il 90%. Lo stesso schema funziona per le Reserved Instance con RI_UTILIZATION.

In chiusura

Gli screenshot da migliaia di miliardi di dollari del 17 luglio erano un bug di visualizzazione. Nessuno ha pagato quei soldi e AWS ha corretto i dati entro un giorno. La lezione resta valida comunque: un'anomalia nella tua fattura deve raggiungerti attraverso i tuoi avvisi, non attraverso la tua timeline.

  • Definisci un budget mensile con aws_budgets_budget.
  • Abbina le notifiche FORECASTED e ACTUAL per un'allerta a due livelli.
  • Instrada gli avvisi via SNS verso un canale che il tuo team guarda davvero.
  • Completa il quadro con i budget di utilizzo (3 GB di S3) e il monitoraggio della utilization dei Savings Plan.

La prossima volta che "la mia fattura AWS è esplosa" finisce in tendenza, potrai guardartela con il caffè in mano. Per ricostruire l'incidente: The Register e TechCrunch lo hanno seguito in tempo reale.

Da leggere dopo

Riferimenti