Modules: how to maintain N similar resources (ec2 instances)?

I have this example

locals {
  multiple_instances = {
    dispatcher = {
      instance_type     = "c3.4xlarge"
      availability_zone = element(module.vpc.azs, 0)
      subnet_id         = element(module.vpc.private_subnets, 0)
      root_block_device = [
        {
          encrypted   = true
          volume_type = "gp3"
          throughput  = 200
          volume_size = 50
          tags = {
            Name = "my-root-block"
          }
        }
      ]
    }
    consumer = {
      instance_type     = "c3.large"
      availability_zone = element(module.vpc.azs, 1)
      subnet_id         = element(module.vpc.private_subnets, 1)
      root_block_device = [
        {
          encrypted   = true
          volume_type = "gp2"
          volume_size = 50
        }
      ]
    }
    producer = {
      instance_type     = "t3.medium"
      availability_zone = element(module.vpc.azs, 2)
      subnet_id         = element(module.vpc.private_subnets, 2)
    }
  }
}

module "ec2_multiple" {
  source = "terraform-aws-modules/ec2-instance/aws"

  for_each = local.multiple_instances

  name = "${local.name}-multi-${each.key}"

  ami                    = data.aws_ami.amazon_linux.id
  instance_type          = each.value.instance_type
  availability_zone      = each.value.availability_zone
  subnet_id              = each.value.subnet_id
  vpc_security_group_ids = [module.security_group.security_group_id]

  enable_volume_tags = false
  root_block_device  = lookup(each.value, "root_block_device", [])

  tags = local.tags
}

So as a result I have 3 instances running:

  • dispatcher
  • consumer
  • producer

Now I want to spinup 20 instances of dispatcher, 30 instances of consumer, and 25 instances of producer. What’s the best way to do it without removing for_each?

Hi @Stan,

The rule for for_each is that your map must have one element for each instance you want to declare, and so the main thing to achieve here is to derive a new map where there is more than one element for each of the elements in your source map.

Some building blocks you can use to achieve that include:

  • The range function, which you can pass the number of elements you want and get a list with that many elements.
  • for expressions, which you can use to derive one collection from another.
  • The flatten function, which can turn multiple nested lists into a single list as shown in its documentation.

With these building blocks you can make a list of numbers representing different indices of the same instance type, and then treat the result as a “nested data structure” as the flatten documentation describes.

If you try putting these pieces together and have further questions, please let me know! I know what I’m describing here isn’t exactly the situation the documentation covers, so I’m happy to fill in some gaps if you aren’t sure.

1 Like