Modularizing terraform is a great way to make reusable code but it can often come with it's own difficulties.
Regardless, using battle tested modules (like the ones at terraform-aws-modules) is a great way to build strong deployments. You just need to think about how much modularization you are going to do. The top open source contributors in terraform all recommend the use of terragrunt which we rely on heavily at inight-infrastructure to put together modular deployments.
Here are a few links discussing how we approach things.
When you start to break up terraform into different sections (ie different deployments / folders) that refer to dynamic variables (think you setup VPC in one place and need to get vpc_id out of it to run a module in another) , have three options to pipe variables from one location to another.
Terraform:
data "terraform_remote_state" "vpc" {
backend = "remote"
config = {
organization = "hashicorp"
workspaces = {
name = "vpc-prod"
}
}
}
resource "aws_instance" "foo" {
# ...
subnet_id = data.terraform_remote_state.vpc.outputs.subnet_id
}
data "aws_ami" "web" {
filter {
name = "state"
values = ["available"]
}
filter {
name = "tag:Component"
values = ["web"]
}
most_recent = true
}
Terragrunt