Smart Subnet Allocation: Optimizing Your AWS Infrastructure with Terraform
Tags: terraform, aws, devops, cloud
Published: 2024-07-13 19:17:04

Picture this: You're orchestrating a complex AWS infrastructure, juggling multiple subnets and a fleet of instances that seem to multiply overnight. Suddenly, you're faced with a puzzle - how do you efficiently allocate these instances across your subnets without turning your VPC into a digital traffic jam 😵?


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t8zf7j80meo681lkfolo.gif)
 Ahh total mess!! Let's understand the problem statement clearly.

Imagine you're the conductor of a grand cloud orchestra. You've got a VPC with more than two subnets, and you're tasked with deploying a variety of servers, including those sneaky auto-scaling groups that grow and shrink on a whim. The question that keeps you up at night: "How can I ensure each instance finds its perfect subnet home, automatically 🤔?"

Sure, AWS offers auto-allocation of IP addresses within a CIDR block, but when you're dealing with a complex VPC architecture, you need something smarter. Something that can look at the big picture and make decisions that keep your network balanced and efficient.

Ta-daa, here enters The Smart Subnet Allocator 🤓.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/azvzmqrehb9utfte9e3n.gif)



After much head-scratching and coffee-fueled brainstorming, I stumbled upon an elegant solution. Here's the secret sauce:

1. **Subnet Reconnaissance**: First, we scout out all available subnets in our target VPC. It's like taking inventory of all possible homes for our instances.

2. **IP Usage Analytics**: We then put on our detective hats and calculate how many IPs are being used in each subnet. This gives us a clear picture of which neighborhoods are bustling and which are quiet.

3. **The Great Subnet Sort**: Armed with this information, we sort our subnets from least crowded to most crowded. It's like arranging your closet from emptiest shelf to fullest.

4. **Round-Robin Magic**: Finally, we assign our instances to subnets in a round-robin fashion, starting with the least crowded subnet. It's like dealing cards, ensuring everyone gets a fair shot at the best spots.

This approach ensures that we're always placing new instances in the subnets with the most room to breathe, automatically balancing our network load and making the most efficient use of our VPC real estate.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6s1hc081ty67m615nsno.png)


By implementing this logic in Terraform, we can automate this entire process, making our infrastructure not just code, but smart code. It's like having a tiny, efficient robot organizing your cloud resources for optimal performance.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/875g21h8mdp17h4hw92x.gif)

We'll next dive into the Terraform code that makes this happen. We'll show you how to implement this smart subnet allocation strategy, turning your VPC from a chaotic city into a well-planned metropolis of cloud resources.

```tf
terraform {
  required_providers {
    aws = {
      version = ">= 2.7.0"
      source  = "hashicorp/aws"
    }
  }
}
```
We first configured Terraform and required providers. For our use case we took AWS as the cloud provider

```tf
# Fetch VPC details
data "aws_vpc" "vpc" {
  filter {
    name   = var.vpc_name
    values = var.vpc_values
  }
  state = "available"
}

# Get all subnet IDs inside the VPC
data "aws_subnet_ids" "subnets" {
  vpc_id = var.vpc_id
  tags = {
    Type = "my-vpc"
  }
}

# Fetch details for all available subnets
data "aws_subnet" "available_subnets" {
  for_each = data.aws_subnet_ids.subnets.ids
  id       = each.value
}

# Get instance allocation details for each subnet
data "aws_instances" "instances_in_subnets" {
  for_each = data.aws_subnet.available_subnets
  filter {
    name   = "subnet-id"
    values = [each.value.id]
  }
}
```
For the next, we defined our data section in order to get the subnet details from our VPC.
```tf
locals {
  # Calculate available IP count for each subnet
  subnet_counts = {
    for subnet in data.aws_subnet.available_subnets : subnet.id => 
      tonumber(split("/", subnet.cidr_block)[1]) - length(data.aws_instances.instances_in_subnets[subnet.id].ids)
  }

  # Sort subnets based on available IP count (ascending order)
  sorted_subnet_counts = sort([
    for subnet_id, count in local.subnet_counts :
    { subnet_id = subnet_id, count = count }
  ])

  # Reverse the sorted list to get descending order
  sorted_subnet_counts_desc = reverse(local.sorted_subnet_counts)
}
```
This code snippet encapsulates the core logic of our solution:

  1. The _subnet_counts_ map calculates the number of available IPs in each 
     subnet, addressing points 1 and 2 of our solution.
  2. _sorted_subnet_counts_ transforms this information into a sorted list, 
     implementing point 3.
  3. Finally, _sorted_subnet_counts_desc_ reverses the list, preparing us 
     for the round-robin allocation described in point 4.

Now that we have our sorted list of subnets, let's look at how we can use it to deploy multiple instances with smart subnet allocation.

```tf
# Considering simplest approach to deploy multiple instances 
variable "instance_count" {
  type    = number
  default = 50
}

# Create EC2 instances with dynamic subnet allocation
resource "aws_instance" "instance" {
  count         = var.instance_count
  instance_type = "t2.micro"
  subnet_id     = local.sorted_subnet_counts_desc[count.index % length(local.sorted_subnet_counts_desc)].subnet_id

  tags = {
    Name = "instance-${count.index + 1}"
  }

  # Other configuration...
}
```
This code demonstrates the practical application of our subnet allocation strategy:

  1. We define a variable _instance_count_ to specify how many instances we 
     want to deploy.
  2. The aws_instance resource uses Terraform's count parameter to create 
     multiple instances.
  3. The _subnet_id_ assignment is where the magic happens. We use the 
     modulo operator (%) to cycle through our sorted subnet list in a 
     round-robin fashion, implementing the fourth point of our solution.
  4. Each instance is tagged with a unique name for easy identification.

This approach ensures that our instances are evenly distributed across the available subnets, starting with those that have the most available IPs. It's a simple yet effective way to maintain balance in your VPC as you scale your infrastructure.

Let's not forget, in the world of cloud infrastructure, a little automation goes a long way 😋.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zxsr1fgvlh5e0abfd5sg.gif)
 Happy terraforming 🤗!