Criar um budget no Azure com Terraform substitui dezenas de cliques manuais no portal — que ninguém documenta e que você repete do zero na próxima subscription — por um módulo revisável, reaproveitável e com o histórico de alterações no Git, usando o recurso azurerm_consumption_budget_subscription.
Neste guia você vai ver como criar um módulo Terraform reutilizável para budgets de subscription, instanciá-lo com um valor mensal e múltiplos thresholds de alerta, e conferir o resultado com terraform plan/apply reais.
Segurança: os comandos deste artigo utilizam variáveis de ambiente para credenciais. Nunca insira IDs de subscription, senhas ou chaves diretamente nos comandos — use TF_VAR_*, um arquivo .tfvars fora do Git, ou o Azure Key Vault.
Sumário
- Pré-requisitos
- Criando o módulo terraform-budget-modules
- Instanciando o módulo
- terraform plan e apply
- Confirmando o budget no Azure com Terraform
- Troubleshooting comum
- Conclusão
- Referências oficiais
Pré-requisitos
Antes de criar o budget no Azure com Terraform, você vai precisar do Azure CLI autenticado (az login), do Terraform >= 1.5 e de uma role com permissão de escrita em Cost Management na subscription (Cost Management Contributor ou Owner/Contributor). O provider usado é o azurerm ~> 4.0.
az account show --query "{name:name, id:id}" -o table
Criando o módulo terraform-budget-modules
Esse módulo é a base de qualquer budget no Azure com Terraform: ele encapsula o recurso azurerm_consumption_budget_subscription e gera um bloco notification por threshold usando dynamic, para não repetir código a cada percentual de alerta:
# main.tf
resource "azurerm_consumption_budget_subscription" "this" {
name = var.name
subscription_id = "/subscriptions/${var.subscription_id}"
amount = var.amount
time_grain = var.time_grain
time_period {
start_date = var.start_date
end_date = var.end_date
}
dynamic "notification" {
for_each = var.thresholds
content {
enabled = true
threshold = notification.value
operator = "GreaterThanOrEqualTo"
threshold_type = "Actual"
contact_emails = var.contact_emails
}
}
}
threshold_type = "Actual" dispara o alerta com base no consumo já realizado. Trocando para "Forecasted" o alerta passa a considerar a projeção de custo do mês, o que avisa antes do limite ser efetivamente estourado.
# variables.tf
variable "name" { type = string }
variable "subscription_id" { type = string }
variable "amount" { type = number }
variable "time_grain" {
type = string
default = "Monthly" # Monthly, Quarterly, Annually, BillingMonth, BillingQuarter, BillingAnnual
}
variable "start_date" { type = string } # primeiro dia do mês, RFC3339: "2026-08-01T00:00:00Z"
variable "end_date" { type = string; default = null }
variable "thresholds" {
type = list(number)
default = [80, 100]
}
variable "contact_emails" { type = list(string) }
start_date precisa ser sempre o primeiro dia do mês — o provider rejeita qualquer outro dia. Se end_date não for informado, o Azure assume 10 anos de vigência a partir do início.
Instanciando o módulo
Com o módulo pronto, o ambiente que efetivamente cria o budget no Azure com Terraform fica pequeno — só passa os valores específicos deste caso: R$ 20/mês, alertas em 50%, 80% e 100%, notificando um único e-mail:
module "budget" {
source = "../../terraform-budget-modules"
name = "budget-finops-blog-castilho"
subscription_id = var.subscription_id
amount = 20
thresholds = [50, 80, 100]
contact_emails = ["<YOUR_EMAIL>"]
start_date = "2026-08-01T00:00:00Z"
}
O subscription_id nunca vai hardcoded — é passado via variável marcada como sensitive = true e populada por TF_VAR_subscription_id no ambiente de execução, nunca commitado:
export TF_VAR_subscription_id="<SUBSCRIPTION_ID>"
export TF_VAR_start_date="2026-08-01T00:00:00Z"
terraform plan e apply
Com o backend remoto inicializado (terraform init -backend-config=backend.hcl), o plan do budget no Azure com Terraform mostra exatamente o que vai ser criado — um recurso, três blocos de notificação:
$ terraform plan -out=tfplan.out
Terraform will perform the following actions:
# module.budget.azurerm_consumption_budget_subscription.this will be created
+ resource "azurerm_consumption_budget_subscription" "this" {
+ amount = 20
+ id = (known after apply)
+ name = "budget-finops-blog-castilho"
+ subscription_id = (sensitive value)
+ time_grain = "Monthly"
+ notification {
+ contact_emails = ["<YOUR_EMAIL>"]
+ enabled = true
+ operator = "GreaterThanOrEqualTo"
+ threshold = 50
+ threshold_type = "Actual"
}
+ notification {
+ threshold = 80
# ...
}
+ notification {
+ threshold = 100
# ...
}
+ time_period {
+ end_date = (known after apply)
+ start_date = "2026-08-01T00:00:00Z"
}
}
Plan: 1 to add, 0 to change, 0 to destroy.
Note que o Terraform marca subscription_id como (sensitive value) no plano — reflexo direto do sensitive = true declarado na variável, que evita vazar o ID em logs de CI/CD. Aprovado o plano, o apply cria o recurso em segundos:
$ terraform apply tfplan.out
module.budget.azurerm_consumption_budget_subscription.this: Creating...
module.budget.azurerm_consumption_budget_subscription.this: Creation complete after 6s [id=/subscriptions/<SUBSCRIPTION_ID>/providers/Microsoft.Consumption/budgets/budget-finops-blog-castilho]
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
Outputs:
budget_id = "/subscriptions/<SUBSCRIPTION_ID>/providers/Microsoft.Consumption/budgets/budget-finops-blog-castilho"
budget_name = "budget-finops-blog-castilho"
Os outputs desse budget no Azure com Terraform devolvem o id completo do recurso e o nome — úteis para referenciar o budget em outro módulo (um dashboard ou uma automação de resposta a alerta, por exemplo) sem precisar redigitar a string.
Confirmando o budget no Azure com Terraform
Depois do apply, o budget no Azure com Terraform aparece em Cost Management + Billing → Cost Management → Budgets na subscription de destino, já com os três thresholds configurados:

Abrindo esse budget no Azure com Terraform, a página de detalhe confirma o valor (R$20,00), o consumo avaliado até o momento e os três alertas configurados — 50%, 80% e 100% do valor, todos do tipo Actual cost:

Vale conferir ali a barra de progresso do consumo atual contra o valor definido nesse budget no Azure com Terraform — é a mesma visualização que o Azure usa para dispar os e-mails de alerta quando um threshold é cruzado.
Se quiser consultar o consumo diário via linha de comando antes de decidir o valor do budget, a extensão costmanagement do Azure CLI expõe a API de Cost Management:
az extension add --name costmanagement
az rest --method post \
--url "https://management.azure.com/subscriptions/<SUBSCRIPTION_ID>/providers/Microsoft.CostManagement/query?api-version=2023-11-01" \
--body '{
"type": "ActualCost",
"timeframe": "MonthToDate",
"dataset": {
"granularity": "Daily",
"aggregation": { "totalCost": { "name": "PreTaxCost", "function": "Sum" } }
}
}'
Em subscriptions com pouquíssimo consumo (labs, contas MPN/dev), a API de forecast (/providers/Microsoft.CostManagement/forecast) costuma responder 429 Too Many Requests com mais frequência — o rate limit dela é mais agressivo que o da query de custo real. Nesses casos, uma estimativa simples por média diária × dias do mês já é suficiente para calibrar o valor do budget.
Troubleshooting comum
Problemas mais frequentes de quem está configurando um budget no Azure com Terraform pela primeira vez:
| Sintoma | Causa | Solução |
|---|---|---|
start_date must be the first day of the month |
start_date informado com dia diferente de 01 |
Ajustar para o primeiro dia do mês em RFC3339 (ex: 2026-08-01T00:00:00Z) |
| Alerta não chega no e-mail | enabled = false na notification, ou threshold ainda não atingido |
Conferir enabled no bloco e o consumo atual no portal |
429 Too Many Requests na API de Cost Management |
Rate limit mais agressivo em subscriptions de baixo consumo (comum em contas MPN/dev) | Aguardar alguns minutos e repetir a chamada; evitar polling em loop curto |
subscription_id aparece em texto puro no state |
Comportamento esperado do Terraform — o state guarda o valor real mesmo com sensitive = true |
Usar backend remoto com criptografia e controle de acesso (Storage Account + RBAC), nunca versionar o .tfstate |
Conclusão
Um budget criado pelo portal resolve o problema uma vez; um budget no Azure com Terraform resolve o problema para toda subscription nova que você abrir depois. Com o módulo terraform-budget-modules pronto, adicionar um budget a uma subscription nova é só instanciar o módulo com nome, valor e e-mail de contato — sem repetir cliques no portal nem esquecer de configurar os thresholds de alerta.
Referências oficiais
Documentação oficial usada como base para este guia de budget no Azure com Terraform:
- azurerm_consumption_budget_subscription (Terraform Registry)
- Criar e gerenciar budgets no Azure Cost Management (Microsoft Learn)
- Cost Management Query API (Microsoft Learn)
Interessado em saber mais sobre artigos relacionados ao Microsoft Azure CLIQUE AQUI
🚀 Vamos nos conectar?
Não perca nenhuma oportunidade! Cadastre-se nas minhas redes e no canal do YouTube para receber conteúdos de TI, Cloud, Azure, Kubernetes e DevOps em primeira mão.
Dica: No Facebook, todos os artigos do blog são publicados automaticamente. Vale a pena curtir!
💬 Dúvidas ou Problemas?
Com o intuito de ajudar a comunidade, caso você tenha dúvidas ou encontre problemas na execução dos comandos deste artigo, deixe um comentário abaixo. Responderei o mais breve possível!
Muito obrigado pela visita e até o próximo post!
Jefferson Castilho Especialista em Cloud & DevOps.Este guia técnico é exclusivo do Blog do Castilho. Explore mais conteúdos sobre Cloud e DevOps.