Se você já configurou Network Watcher com Flow Logs antes, provavelmente usou NSG Flow Logs — o recurso clássico, associado a um Network Security Group específico. Isso mudou: desde 30 de junho de 2025, o Azure não aceita mais criar NSG Flow Logs novos, e o recurso inteiro será aposentado em 30 de setembro de 2027. O substituto é o VNet Flow Log, que funciona de forma quase idêntica no Terraform — só muda o alvo.
Mais um artigo da série artigos-network — que começou com o Azure Virtual Network Manager —, este mostra como configurar visibilidade de tráfego com Network Watcher e Terraform do jeito atual, com Traffic Analytics — e documenta o erro real que aparece se você seguir um tutorial desatualizado.
Segurança: os comandos deste guia de Network Watcher com Terraform 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
- Rede de exemplo pro Network Watcher: VNet e NSG
- Destino dos logs: Storage e Log Analytics
- VNet Flow Log com Traffic Analytics
- Troubleshooting: NSG Flow Logs descontinuados
- terraform plan e apply
- Conclusão
- Referências oficiais
Pré-requisitos
Antes de configurar o Network Watcher com Terraform, você vai precisar do Azure CLI autenticado (az login), do Terraform >= 1.5 e de permissão de Network Contributor na subscription. O provider usado é o azurerm ~> 4.0.
az account show --query "{name:name, id:id}" -o table
Uma particularidade importante do Network Watcher: o Azure já cria automaticamente um recurso NetworkWatcher_<região> no resource group NetworkWatcherRG assim que a primeira VNet de uma subscription é criada. Confirme que já existe antes de seguir:
az network watcher list -o table
# Location Name ProvisioningState ResourceGroup
# ---------- --------------------- ------------------- ----------------
# eastus NetworkWatcher_eastus Succeeded NetworkWatcherRG
Por isso o Terraform aqui referencia esse Network Watcher pelo nome, em vez de tentar criar um novo com azurerm_network_watcher — que provavelmente já existe e causaria conflito.
Rede de exemplo pro Network Watcher: VNet e NSG
No Network Watcher, o alvo do Flow Log agora é a VNet — mas ainda vale ter um NSG associado à subnet. Ele não é usado como alvo do Flow Log neste artigo (motivo explicado no troubleshooting), mas é comum ter um numa rede real. Como nos artigos anteriores da série, o código compõe os módulos reutilizáveis do repositório (terraform-virtual-network-modules e terraform-nsg-modules) em vez de declarar recursos crus:
module "vnet" {
source = "../../terraform-virtual-network-modules"
name = "vnet-netwatcher-blog-castilho"
resource_group_name = module.rg.name
location = var.location
address_space = [var.vnet_address_space]
subnets = [
{ key = "netwatcher", name = "snet-netwatcher", address_prefixes = [var.subnet_prefix] },
]
tags = var.tags
}
module "nsg" {
source = "../../terraform-nsg-modules"
name = "nsg-netwatcher-blog-castilho"
resource_group_name = module.rg.name
location = var.location
subnet_id = module.vnet.subnets["netwatcher"].id
security_rules = [
{
name = "allow-https-inbound"
priority = 100
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "443"
source_address_prefix = "Internet"
destination_address_prefix = "*"
},
]
tags = var.tags
}
Destino dos logs: Storage e Log Analytics
No Network Watcher, os logs brutos vão pra um Storage Account; o Traffic Analytics (agregações e insights visuais no portal) precisa de um Log Analytics Workspace separado:
resource "random_string" "storage_suffix" {
length = 8
special = false
upper = false
}
module "storage_flowlogs" {
source = "../../terraform-storage-modules"
name = "stflowlogs${random_string.storage_suffix.result}"
resource_group_name = module.rg.name
location = var.location
tags = var.tags
}
module "log_analytics" {
source = "../../terraform-log-analytics-modules"
name = "log-netwatcher-blog-castilho"
resource_group_name = module.rg.name
location = var.location
retention_in_days = 30
tags = var.tags
}
Uma pegadinha que aparece aqui: o Traffic Analytics pede dois identificadores diferentes do mesmo workspace — o customer ID (um GUID) e o resource ID ARM. Por isso o módulo de Log Analytics expõe os dois como outputs separados (customer_id e workspace_id); trocar um pelo outro gera erro de validação só na hora do apply.
VNet Flow Log com Traffic Analytics
O Flow Log vem do módulo terraform-network-watcher-modules, criado para este artigo. A chamada passa a VNet como alvo, o Storage como destino e o workspace para o Traffic Analytics:
module "flow_log" {
source = "../../terraform-network-watcher-modules"
name = "flowlog-netwatcher-blog-castilho"
location = var.location
target_resource_id = module.vnet.vnet_id
storage_account_id = module.storage_flowlogs.storage_account_id
retention_days = var.flow_log_retention_days
traffic_analytics_workspace_id = module.log_analytics.customer_id
traffic_analytics_workspace_region = var.location
traffic_analytics_workspace_resource_id = module.log_analytics.workspace_id
tags = var.tags
}
Dentro do módulo, o recurso azurerm_network_watcher_flow_log continua sendo o mesmo de sempre — só o argumento que define o alvo muda: target_resource_id apontando pra VNet inteira, em vez de network_security_group_id apontando pra um NSG específico. Repare também que ele referencia o Network Watcher que o Azure já criou, pelo nome e pelo resource group:
resource "azurerm_network_watcher_flow_log" "this" {
name = var.name
network_watcher_name = "NetworkWatcher_${var.location}"
resource_group_name = "NetworkWatcherRG"
target_resource_id = var.target_resource_id
storage_account_id = var.storage_account_id
enabled = true
version = 2
retention_policy {
enabled = true
days = var.retention_days
}
dynamic "traffic_analytics" {
for_each = var.traffic_analytics_workspace_id != null ? [1] : []
content {
enabled = true
workspace_id = var.traffic_analytics_workspace_id
workspace_region = var.traffic_analytics_workspace_region
workspace_resource_id = var.traffic_analytics_workspace_resource_id
interval_in_minutes = var.traffic_analytics_interval_minutes
}
}
tags = var.tags
}
A vantagem prática do VNet Flow Log sobre o NSG Flow Log: um único recurso cobre todo o tráfego da VNet, incluindo subnets sem NSG associado — antes, era preciso um Flow Log por NSG.
Troubleshooting: NSG Flow Logs descontinuados
A primeira versão deste Terraform usava network_security_group_id = azurerm_network_security_group.netwatcher.id — o jeito “clássico”, que aparece na maioria dos tutoriais publicados antes de 2025. O apply falhou com:
Error: creation of new NSG flow logs is no longer supported by Azure
as of June 30, 2025. NSG flow logs will be retired on September 30, 2027.
For more information, see
https://learn.microsoft.com/azure/network-watcher/nsg-flow-logs-migrate
A mensagem de erro é direta e explica a mudança — a correção foi trocar network_security_group_id por target_resource_id apontando pra VNet. Se você tem NSG Flow Logs antigos já em produção, eles continuam funcionando normalmente até a data de aposentadoria (30/09/2027) — só não dá mais pra criar novos, nem editar a maioria das configurações dos existentes.
terraform plan e apply
terraform init -backend-config=backend.hcl
terraform plan -out=tfplan.out
terraform apply tfplan.out
O ambiente completo cria 9 recursos: Resource Group, VNet + subnet + NSG associado, Storage Account, Log Analytics Workspace, e o VNet Flow Log com Traffic Analytics. Depois de corrigido o alvo do Flow Log, o apply completou sem mais erros, e o recurso final confirma a associação certa:
flow_log_id = ".../networkWatchers/NetworkWatcher_eastus/flowLogs/flowlog-netwatcher-blog-castilho"
Conclusão
Configurar Network Watcher com Flow Logs em 2026 significa usar VNet Flow Logs, não NSG Flow Logs — uma mudança pequena no código Terraform (um argumento diferente), mas que derruba qualquer tutorial ou snippet copiado de antes de junho de 2025. Vale sempre checar a data de publicação de exemplos de Terraform pra Azure antes de copiar, especialmente em recursos de rede, que a Microsoft reformula com alguma frequência.
Se você está acompanhando a série, os artigos anteriores cobrem outras peças da mesma rede: Application Gateway com WAF v2, NAT Gateway para saída de internet controlada e DDoS Protection Standard. O próximo é o Private Link Service; depois, a série artigos-paas entra em serviços gerenciados como Azure Functions, Container Apps e API Management.
Referências oficiais
- Migrate from NSG flow logs to VNet flow logs — Microsoft Learn
- VNet flow logs overview — Microsoft Learn
- azurerm_network_watcher_flow_log — Terraform Registry
Interessado em saber mais sobre esse assunto?