如何在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
相关产品推荐
相关产品推荐

