如何在 terraform 中使用嵌套循环

舒巴姆·杰拉特

我正在尝试使用 Terraform 计数在 Azure 中创建 3 个 VM,每个 VM 需要多个磁盘。有什么办法可以做到这一点吗?我尝试创建磁盘名称和大小的映射,但出现错误,我不能同时使用 count 和 for_each?

resource "azurerm_managed_disk" "this" {
  for_each             = var.disks
  count                = each.value > 0 ? var.node_count : 0
  name                 = format("%s-%02d-datadisk", each.key, count.index + 1)
  location             = var.location
  resource_group_name  = var.resource_group_name
  storage_account_type = "Premium_LRS"
  create_option        = "Empty"
  disk_size_gb         = each.value

  tags = {
    environment = "staging"
  }
 }  

resource "azurerm_virtual_machine_data_disk_attachment" "this" {
  for_each           = var.disks
  count              = each.value > 0 ? var.node_count : 0
  managed_disk_id    = azurerm_managed_disk.this.*.id[count.index]
  virtual_machine_id = azurerm_virtual_machine.this.*.id[count.index]
  lun                = "10"
  caching            = "None"
}

vm.tf
variable "disks" {
  description = "Map of disk name and respective disk size"
  type        = map(string)
  default     = {
    "binlog_disk"    = "30"
    "innodb_disk"    = "20"
    "data_disk"      = "100"
    "tmp_disk"       = "10"
    "backup_disk"    = "150"
  }
}
马丁·阿特金斯

资源for_each的关键要求是您构建一个地图,该地图为您要创建的每个实例都包含一个元素。

在这种情况下,你想对每个(例如,磁盘)对,这是一个很好的用例的一个实例setproduct功能在这种情况下,因为你的资源之一是使用count,我们会结合它range功能产生整数合适的顺序来识别实例:

locals {
  instance_disks = {
    for pair in setproduct(range(length(azurerm_virtual_machine.this)), keys(var.disks)) : "${pair[0]}:${pair[1]}" => {
      vm_index  = pair[0]
      disk_key  = pair[1]
      disk_size = var.disks[pair[1]]
    }
  }
}

以上将生成一个映射,每对虚拟机索引和磁盘有一个元素,元素如下:

{
  "0:binlog_disk" = {
    vm_index  = 0
    disk_key  = "binlog_disk"
    disk_size = 30
  },
  "1:binlog_disk" = {
    vm_index  = 1
    disk_key  = "binlog_disk"
    disk_size = 30
  },
  etc...
}

此映射满足资源for_each需求,因此我们可以将其用作资源中for_each表达式azurerm_managed_diskazurerm_virtual_machine_data_disk_attachment

resource "azurerm_managed_disk" "this" {
  for_each = local.instance_disks

  name                 = format("%s-%02d-datadisk", each.value.disk_key, each.value.instance_index + 1)
  location             = var.location
  resource_group_name  = var.resource_group_name
  storage_account_type = "Premium_LRS"
  create_option        = "Empty"
  disk_size_gb         = each.value.disk_size

  tags = {
    environment = "staging"
  }
}

resource "azurerm_virtual_machine_data_disk_attachment" "this" {
  for_each = local.instance_disks

  managed_disk_id    = azurerm_managed_disk.this[each.key].id
  virtual_machine_id = azurerm_virtual_machine.this[each.value.instance_index].id
  lun                = "10"
  caching            = "None"
}

这些资源实例的地址将使用与映射相同的键,给出如下地址:

  • azurerm_managed_disk.this["0:binlog_disk"]
  • azurerm_managed_disk.this["1:binlog_disk"]
  • ...
  • azurerm_managed_disk.this["0:innodb_disk"]
  • azurerm_managed_disk.this["1:innodb_disk"]
  • ...

考虑用于资源的实例键很重要,因为它们决定了 Terraform 如何理解底层地图的变化。特别是在这种情况下,因为我们通过虚拟机在count序列中的位置来识别虚拟机,将虚拟机的数量减少一个会被 Terraform 理解为请求销毁所有具有最高索引的附件。innodb_disk从 中删除条目var.disks会被 Terraform 理解为销毁所有地址以:innodb_disk.

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章