如何在Terraform中使用嵌套循环 [英] How to use nested loop in terraform

查看:14
本文介绍了如何在Terraform中使用嵌套循环的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用Terraform Count在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"
  }
}

推荐答案

resource for_each的关键要求是构建一个映射,其中每个要创建的实例都有一个元素。

在本例中,您希望每个(实例、磁盘)对都有一个实例,这是the setproduct function的一个很好的用例。在本例中,因为您的一个资源正在使用count,所以我们将把它与the range function结合起来,以生成适当的整数序列来标识实例:

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...
}

该map满足资源for_each要求,可以作为azurerm_managed_diskazurerm_virtual_machine_data_disk_attachment资源中的for_each表达式:

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理解为请求销毁具有最高索引的所有附件。从var.disks中删除innodb_disk条目将被Terraform理解为请求销毁地址以:innodb_disk结尾的所有附件。

这篇关于如何在Terraform中使用嵌套循环的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆