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

如何在Terraform的RSV模块中传递多块托管磁盘实现ASR复制?

如何在Terraform中配置azurerm_site_recovery_replicated_vm实现多磁盘复制?

场景说明

现有一台位于西海岸的Azure虚拟机,包含1个OS磁盘和2个数据磁盘,需要通过Azure Site Recovery(ASR)将其复制到东海岸区域。

现有代码结构与实现

代码目录结构

Modules
  KeyVault
  PublicIP
  RecoverServiceVault
  BunchOfOtherAzureResources
Project01
Project02
Project03
Project0x

Project01的main.tf(单磁盘复制实现)

data "azurerm_managed_disk" "os_disk" {
  name                = local.osDiskName
  resource_group_name = data.azurerm_virtual_machine.host.resource_group_name
}

module "AddRecoveryServiceVault" {
  source                       = "../modules/RecoveryServiceVault"
  rgDr                         = azurerm_resource_group.dr.name
  rgAsr                        = azurerm_resource_group.asr.name
  # 其他传递给模块的参数...
  
  sourceDiskId                 = data.azurerm_managed_disk.os_disk.id

  # 其他传递给模块的参数...
  tags                         = local.tags
}

RecoveryServiceVault模块配置

variables.tf(仅支持单磁盘)

variable "sourceDiskId" {
  type = string
  description = "the disk Id of the virtual machine being protected in Source (Primary)"
}

main.tf(单磁盘复制配置)

resource "azurerm_site_recovery_replicated_vm" "vm-replication" {
  name                                      = var.sourceHostName
  resource_group_name                       = var.rgDr
  recovery_vault_name                       = azurerm_recovery_services_vault.vault.name
  source_recovery_fabric_name               = azurerm_site_recovery_fabric.primary.name
  source_vm_id                              = var.sourceHostId
  recovery_replication_policy_id            = azurerm_site_recovery_replication_policy.policy.id
  source_recovery_protection_container_name = azurerm_site_recovery_protection_container.primary.name

  target_resource_group_id                = var.rgAsrId
  target_recovery_fabric_id               = azurerm_site_recovery_fabric.secondary.id
  target_recovery_protection_container_id = azurerm_site_recovery_protection_container.secondary.id

  managed_disk {
    disk_id                    = var.sourceDiskId
    staging_storage_account_id = var.storageAccountId
    target_resource_group_id   = var.rgAsrId
    target_disk_type           = "Premium_LRS"
    target_replica_disk_type   = "Premium_LRS"
  }

  network_interface {
    source_network_interface_id   = var.sourceNicId
    target_subnet_name            = azurerm_subnet.secondary.name
    recovery_public_ip_address_id = azurerm_public_ip.secondary.id
  }

  depends_on = [
    azurerm_site_recovery_protection_container_mapping.container-mapping,
    azurerm_site_recovery_network_mapping.network-mapping,
  ]
}

尝试的修改方案

Project01的main.tf(传入多磁盘配置列表)

module "AddRecoveryServiceVault" {
  source = "../modules/RecoveryServiceVault"
  rgDr   = azurerm_resource_group.dr.name
  rgAsr  = azurerm_resource_group.asr.name
  # 其他传递给模块的参数...

  managed_disk = [{
    disk_id                    = "osDisk01Id"
    staging_storage_account_id = "stId"
    target_resource_group_id   = "rgId"
    target_disk_type           = "Premium_LRS"
    target_replica_disk_type   = "Premium_LRS"
    },
    {
      disk_id                    = "dataDisk01Id"
      staging_storage_account_id = "stId"
      target_resource_group_id   = "rgId"
      target_disk_type           = "Premium_LRS"
      target_replica_disk_type   = "Premium_LRS"
    },
    {
      disk_id                    = "dataDisk02Id"
      staging_storage_account_id = "stId"
      target_resource_group_id   = "rgId"
      target_disk_type           = "Premium_LRS"
      target_replica_disk_type   = "Premium_LRS"
  }]
  # 其他传递给模块的参数...

  tags = local.tags
}

RecoveryServiceVault模块的variables.tf(更新变量类型)

variable "managed_disk" {
  type =  list(object({
    disk_id                    = string
    staging_storage_account_id = string
    target_resource_group_id   = string
    target_disk_type           = string
    target_replica_disk_type   = string
  }))
}

遇到的问题

无法将managed_disk列表直接传递给azurerm_site_recovery_replicated_vm资源中的managed_disk块,因为该资源需要多个独立的managed_disk块而非列表参数。

解决方案

使用Terraform的**动态块(Dynamic Block)**遍历managed_disk列表,自动生成对应数量的managed_disk块。

修改RecoveryServiceVault模块的main.tf

将原来的单个managed_disk块替换为dynamic块,遍历传入的var.managed_disk列表:

resource "azurerm_site_recovery_replicated_vm" "vm-replication" {
  name                                      = var.sourceHostName
  resource_group_name                       = var.rgDr
  recovery_vault_name                       = azurerm_recovery_services_vault.vault.name
  source_recovery_fabric_name               = azurerm_site_recovery_fabric.primary.name
  source_vm_id                              = var.sourceHostId
  recovery_replication_policy_id            = azurerm_site_recovery_replication_policy.policy.id
  source_recovery_protection_container_name = azurerm_site_recovery_protection_container.primary.name

  target_resource_group_id                = var.rgAsrId
  target_recovery_fabric_id               = azurerm_site_recovery_fabric.secondary.id
  target_recovery_protection_container_id = azurerm_site_recovery_protection_container.secondary.id

  # 动态生成多个managed_disk块
  dynamic "managed_disk" {
    for_each = var.managed_disk
    content {
      disk_id                    = managed_disk.value.disk_id
      staging_storage_account_id = managed_disk.value.staging_storage_account_id
      target_resource_group_id   = managed_disk.value.target_resource_group_id
      target_disk_type           = managed_disk.value.target_disk_type
      target_replica_disk_type   = managed_disk.value.target_replica_disk_type
    }
  }

  network_interface {
    source_network_interface_id   = var.sourceNicId
    target_subnet_name            = azurerm_subnet.secondary.name
    recovery_public_ip_address_id = azurerm_public_ip.secondary.id
  }

  depends_on = [
    azurerm_site_recovery_protection_container_mapping.container-mapping,
    azurerm_site_recovery_network_mapping.network-mapping,
  ]
}

优化Project01的磁盘ID获取(可选,自动化获取)

无需手动填写磁盘ID,可通过虚拟机数据源自动提取所有磁盘ID:

data "azurerm_virtual_machine" "host" {
  name                = local.vmName
  resource_group_name = local.sourceRgName
}

# 合并OS磁盘和数据磁盘ID
locals {
  all_disk_ids = concat(
    [data.azurerm_virtual_machine.host.storage_profile.os_disk.managed_disk_id],
    [for disk in data.azurerm_virtual_machine.host.storage_profile.data_disks : disk.managed_disk_id]
  )

  # 构造符合模块要求的managed_disk配置列表
  managed_disks_config = [
    for disk_id in local.all_disk_ids : {
      disk_id                    = disk_id
      staging_storage_account_id = var.staging_storage_account_id # 需提前定义该变量
      target_resource_group_id   = azurerm_resource_group.asr.id
      target_disk_type           = "Premium_LRS"
      target_replica_disk_type   = "Premium_LRS"
    }
  ]
}

module "AddRecoveryServiceVault" {
  source = "../modules/RecoveryServiceVault"
  rgDr   = azurerm_resource_group.dr.name
  rgAsr  = azurerm_resource_group.asr.name
  # 其他参数...
  
  managed_disk = local.managed_disks_config
  
  # 其他参数...
  tags = local.tags
}

清理旧变量(可选)

移除模块中不再使用的sourceDiskId变量,保持代码简洁。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 19:17:31