【问题标题】:Terraform looping with for_each使用 for_each 循环的 Terraform
【发布时间】:2020-11-01 21:12:12
【问题描述】:

如果您使用 for_each 而不是 count,如何获得子网 ID? 就我而言,我正在做这样的事情

resource "aws_instance" "k8s" {
    for_each = var.profiles

    ami = data.aws_ami.latest-ubuntu.id
    instance_type = "t2.medium"
    iam_instance_profile = "${each.value}"
    subnet_id = ??????????????
    vpc_security_group_ids = [var.security_group]
    key_name = var.keyname
    
    connection {
    type        = "ssh"
    host        = self.public_ip
    user        = "ubuntu"
    private_key = file(var.private_key_path)

  }
    tags = {
     Name = "${each.key}"
  }
}

这是因为我正在创建类似的实例,但需要为它们分配不同的实例配置文件。

理想情况下,我会做类似的事情

subnet_id = element(var.subnets, count.index )

将实例放置在不同的子网中,但我认为 countfor_each 不能用于同一个块定义中。

我需要子网和 4 个实例,并且想遍历子网,将每个实例放在一个中。

有什么想法吗? 谢谢。

【问题讨论】:

    标签: amazon-web-services terraform terraform-provider-aws terraform0.12+


    【解决方案1】:

    如果var.profiles是一个列表,可以使用each.key获取每个元素的索引。

    【讨论】:

      【解决方案2】:

      使用资源 for_each 的一个好的通用策略是设计您传递给它的数据结构,以便 each.value 包含您在资源块内需要的所有实例数据。

      在这种情况下,这意味着您的 aws_instance 资源的 for_each 表达式将是一个对象映射,其中每个对象都有一个实例配置文件和一个子网 ID。

      实现这一目标的一种方法是编写一个for expression,将var.profiles(可能是set(string) 值)转换为一个对象映射,从而获得您想要的结果。例如:

      resource "aws_instance" "k8s" {
        for_each = {
          # This assigns a subnet to each of the profiles
          # by first sorting them by name to produce a list
          # and then selecting subnets based on the order
          # of the sort result.
          for i, profile_name in sort(var.profiles) : profile_name => {
            iam_instance_profile = profile_name
            subnet_id            = element(var.subnets, i)
          }
        }
      
        ami                    = data.aws_ami.latest-ubuntu.id
        instance_type          = "t2.medium"
        iam_instance_profile   = each.value.iam_instance_profile
        subnet_id              = each.value.subnet_id
        vpc_security_group_ids = [var.security_group]
        key_name               = var.keyname
      }
      

      使用count.indexelement 元素依赖于每个项目都有自己的索引,但对于一组字符串来说,情况并非如此,所以在上面我使用sort 转换为下面的列表假设在这种情况下,将哪个子网分配给每个实例并不重要,只要实例最终大致均匀地分布在子网之间。

      但是,需要牢记这一点的重要含义:如果您稍后将新项目添加到 var.profiles,则可能会导致现有实例的 subnet_id 被重新分配,因此需要这些实例被重新创建。如果您不希望这是真的,那么您需要以某种方式更明确地选择每个配置文件的子网,这可以通过使 var.profiles 成为 list(string) 而不是 set(string) 然后记录新的配置文件应该只添加到该列表的末尾,或者您可以通过将var.profiles 本身设置为对象映射,然后调用者将为每个配置文件指定一个子网,将决策上移到模块的调用者中:

      variable "profiles" {
        type = map(object({
          subnet_id = string
        }))
      }
      

      在这种情况下,您的资源块会变得更简单,因为变量值已经具有合适的形状:

      resource "aws_instance" "k8s" {
        for_each = var.profiles
      
        ami                    = data.aws_ami.latest-ubuntu.id
        instance_type          = "t2.medium"
        iam_instance_profile   = each.key
        subnet_id              = each.value.subnet_id
        vpc_security_group_ids = [var.security_group]
        key_name               = var.keyname
      }
      

      【讨论】:

        【解决方案3】:

        您可以将个人资料作为对象列表提供:

        例如:

         variable "profiles" {
          type = list(object({
            name = string
            key =  string
          }))
          default = 
            [
              {name = "exemple" , key = "exemplekey" },
              {name = "exemple2" , key = "exemplekey2" }
            ]
        }
        

        像这样each.key 将包含列表中元素的索引,each.value 将包含对象 {name,key}

        所以你的代码会是这样的

        resource "aws_instance" "k8s" {
            for_each = var.profiles
            ami = data.aws_ami.latest-ubuntu.id
            instance_type = "t2.medium"
            iam_instance_profile = each.value
            subnet_id = element(var.subnets , each.key)
            vpc_security_group_ids = [var.security_group]
            key_name = var.keyname
            connection {
            type        = "ssh"
            host        = self.public_ip
            user        = "ubuntu"
            private_key = file(var.private_key_path)
        
          }
            tags = {
             Name = each.value.key
          }
        

        }

        【讨论】:

          猜你喜欢
          • 2021-01-17
          • 2021-11-25
          • 2021-12-08
          • 2021-10-04
          • 2021-10-06
          • 1970-01-01
          • 2021-05-25
          • 2022-07-21
          • 1970-01-01
          相关资源
          最近更新 更多