Search code examples
terraformterraform-provider-aws

Simple explanation of how modulo operations can assign EC2 instances to subnets when using Terraform's AWS Provider


No example code; I am too dumb to understand this section of the docs:

Each instance provisioned by the resource block with count will have a different incrementing value for count.index - starting with zero. This configuration uses count.index and modulo division to assign each instance to a private subnet.

Which refers to this block of code changes:

 resource "aws_instance" "app" {
 +  count = var.instances_per_subnet * length(module.vpc.private_subnets)
 +   
    ami           = data.aws_ami.amazon_linux.id   instance_type = var.instance_type
-  subnet_id              = module.vpc.private_subnets[0]
+  subnet_id              = module.vpc.private_subnets[count.index % length(module.vpc.private_subnets)]   vpc_security_group_ids = [module.app_security_group.this_security_group_id]
   ## ...
 }

Can someone explain to me what is going on here, or point me to docs that do?


Solution

  • An attempt to explain "what is going on here". Please excuse the verbosity.

    The objective is to create N instances and "spread" them evenly among M available subnets.

    Assume for this example that there are 3 private subnets (say one per Availability Zone). That is length(module.vpc.private_subnets) has value 3.
    The subnet ids of these 3 subnets will be accessible from an array returned by the vpc module as:

    • module.vpc.private_subnets[0]
    • module.vpc.private_subnets[1]
    • module.vpc.private_subnets[2]

    Lets assume that you want to create 2 instances per subnet. That is the variable var.instances_per_subnet has value 2.

    The count value for the first expression in the resource block will then be 2 * 3 = 6

    The resource block will then create 6 instances.

    I like to imagine Terraform "iterating" count.index from 0 to 5 as it creates the 6 instances (that's just for my understanding; in general you don't really care how it actually happens since HCL is declarative )

    Below I try to expand the expression

    subnet_id = module.vpc.private_subnets[count.index % length(module.vpc.private_subnets)]

    for each of the 6 instances created:

    Note: In HCL, the modulo operator (%) works roughly like the python % operator.

    • For the instance associated with count.index = 0 the subnet id will be module.vpc.private_subnets[0 % 3], that is we will use the subnet-id given by module.vpc.private_subnets[0]
    • For count.index = 1 => module.vpc.private_subnets[1 % 3], that is subnet_id = module.vpc.private_subnets[1]
    • For count.index = 2 => module.vpc.private_subnets[2 % 3], that is subnet_id = module.vpc.private_subnets[2]
    • For count.index = 3 we are back to the first subnet since 3 % 3 = 0 => subnet_id = module.vpc.private_subnets[0]
    • For count.index = 4 => module.vpc.private_subnets[4 % 3], that is subnet_id = module.vpc.private_subnets[1]
    • For count.index = 5 => module.vpc.private_subnets[5 % 3], that is subnet_id = module.vpc.private_subnets[2]

    The net result is that we are dividing "evenly" the 6 created instances [0,1,...,5] among the 3 available subnets [0,1,2]