You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Terraform跨多订阅部署azurerm_monitor_activity_log_alert遇阻求助

跨多Azure订阅部署Activity Log Alert解决方案

问题背景

需求是跨多个Azure订阅部署azurerm_monitor_activity_log_alert,每个活动日志告警需部署在对应订阅的独立资源组中。当前实现时遇到两个核心问题:

  • azurerm_monitor_activity_log_alert资源本身不支持直接指定部署目标订阅ID
  • Terraform默认仅对当前配置的订阅执行操作,跨多订阅部署的方法不明确

实际执行后所有资源组都创建在同一个订阅下,部署其他订阅时返回如下错误。

错误信息

Error: creating or updating Monitor Activity Log Alert (Subscription:
"***"
│ Resource Group Name: "rg-prod-uks-srv-hlth-001"
│ Activity Log
Alert Name: "sha-prod-uks-hlth-001"): unexpected status 400 (400 Bad
Request) with response: {"code":"ScopeIsInvalid","message":"The
resources in the scope must be in the same subscription as the rule.
Activity ID: xyz."}
│   with
module.service_health_alerts["sub-id"].azurerm_monitor_activity_log_alert.service_health_alert,
│
on
.terraform/modules/service_health_alerts/modules/azurerm_monitor_activity_log_alert/1.0.0/main.tf
line 15, in resource "azurerm_monitor_activity_log_alert"
"service_health_alert": │   15: resource
"azurerm_monitor_activity_log_alert" "service_health_alert" {

当前代码

根模块代码

# Local Variables: Subscription Number Mapping
locals {
  sub_number_map = {
    "sub-id-1" = "001" # sub-dev-d
    "sub-id-2" = "002" # sub-prod-c
    "sub-id-3" = "003" # sub-prod-d
    and so on...
  }
}

module "service_health_alerts" {
  for_each = local.sub_number_map

  source              = "git::/modules/azurerm_monitor_activity_log_alert/1.0.0"
  subscription_id     = each.key
  subscription_number = each.value
  resource_group_name = "rg-prod-${each.value}"
  action_group_id     = module.action-group.id
  tags                = module.tags.tags
  depends_on          = [xyz]
}

子模块代码

resource "azurerm_resource_group" "resource_group" {
  name     = var.resource_group_name
  location = var.location
}

resource "azurerm_monitor_activity_log_alert" "service_health_alert" {
  name                = "sha-prod-uks-hlth-${var.subscription_number}"
  resource_group_name = azurerm_resource_group.resource_group.name
  location            = "global"
  scopes              = ["/subscriptions/${var.subscription_id}"]
  description         = "Alerts when Azure Service Health reports an issue affecting our resources"

  criteria {
    category       = "ServiceHealth"
    operation_name = "Microsoft.ResourceHealth/healthevent/Activated/action"

    service_health {
      events    = ["Incident", "Maintenance"]
      locations = ["xyz", "zyx"]
    }
  }

  action {
    action_group_id = var.action_group_id
  }

  tags = var.tags
}

解决方案

1. 配置多订阅Azure Provider实例

在根模块中为每个目标订阅创建独立的Provider实例,通过alias区分,绑定对应订阅ID:

# 可选保留默认Provider(用于操作当前默认订阅的资源,如动作组)
provider "azurerm" {
  features {}
}

# 为每个目标订阅创建专属Provider
provider "azurerm" {
  for_each = local.sub_number_map
  alias    = each.key

  subscription_id = each.key
  features {}
}

2. 修改模块调用,传递对应Provider

在模块调用中添加providers参数,将当前订阅的Provider实例传递给模块,确保模块内的资源(资源组、告警)部署到对应订阅:

module "service_health_alerts" {
  for_each = local.sub_number_map

  source              = "git::/modules/azurerm_monitor_activity_log_alert/1.0.0"
  subscription_id     = each.key
  subscription_number = each.value
  resource_group_name = "rg-prod-${each.value}"
  action_group_id     = module.action-group.id
  tags                = module.tags.tags
  depends_on          = [xyz]

  # 指定当前订阅对应的Provider实例
  providers = {
    azurerm = azurerm[each.key]
  }
}

3. 子模块无需额外修改

子模块中的azurerm_resource_group和azurerm_monitor_activity_log_alert会自动使用传递的Provider,确保资源组与告警作用域(scopes)处于同一订阅,符合Azure的要求。

关键注意事项

  • Azure强制要求:Activity Log Alert的资源组必须与告警作用域的订阅一致,因此必须通过对应订阅的Provider创建资源
  • 执行Terraform的账号需拥有所有目标订阅的权限(如Contributor、Monitor Contributor)
  • 此方案支持扩展到10-30个订阅,通过维护local.sub_number_map即可统一管理所有订阅的部署

内容的提问来源于stack exchange,提问作者Daniel T

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 22:02:31