DEV Community

# ๐Ÿ” Terraform Modular EKS + Istio โ€” The Part Nobody Explains

When I first modularized my Terraform for EKS, everything looked cleanโ€ฆ

Until it didnโ€™t work.

Modules were correct.
Code was clean.
Folder structure looked โ€œperfectโ€.

But Terraform was behaving in ways I didnโ€™t expect.

Resources were creating in weird order.
Dependencies felt invisible.
And debugging became painful.

Thatโ€™s when I realized:

๐Ÿ‘‰ Understanding Terraform syntax is easy
๐Ÿ‘‰ Understanding how Terraform thinks is the real game

This blog is about that shift.


๐Ÿง  The Biggest Misconception

Initially, I thought Terraform runs like a script:

Step 1 โ†’ Step 2 โ†’ Step 3

But that assumption is completely wrong.

Terraform doesnโ€™t execute line by line.

๐Ÿ‘‰ It builds a dependency graph first, and only then decides what to create and in what order.

Once this clicked, everything started making sense.


๐Ÿงฉ My Project Structure (Real Setup)

Hereโ€™s how I organized everything:

modularized/
โ”œโ”€โ”€ eks/                      # Root module (entry point)
โ”‚   โ”œโ”€โ”€ main.tf
โ”‚   โ”œโ”€โ”€ variables.tf
โ”‚   โ”œโ”€โ”€ providers.tf
โ”‚   โ””โ”€โ”€ backend.tf
โ”œโ”€โ”€ modules/
โ”‚   โ”œโ”€โ”€ vpc/
โ”‚   โ”œโ”€โ”€ iam/
โ”‚   โ”œโ”€โ”€ eks-cluster/
โ”‚   โ”œโ”€โ”€ eks-nodes/
โ”‚   โ”œโ”€โ”€ aws-load-balancer-controller/
โ”‚   โ”œโ”€โ”€ istio-base/
โ”‚   โ”œโ”€โ”€ istiod/
โ”‚   โ”œโ”€โ”€ istio-gateway/
โ”‚   โ””โ”€โ”€ istio-manifests/
โ””โ”€โ”€ environments/
    โ”œโ”€โ”€ dev/
    โ”‚   โ”œโ”€โ”€ terraform.tfvars
    โ”‚   โ””โ”€โ”€ backend.hcl
Enter fullscreen mode Exit fullscreen mode

At a glance, this looks like just folders.

But in reality:

๐Ÿ‘‰ This is a system design mapped into code


๐Ÿ”— The Real Role of main.tf

Think of main.tf not as a fileโ€ฆ

๐Ÿ‘‰ But as an orchestrator

It doesnโ€™t โ€œdoโ€ things directly.
It connects modules together using data.


๐Ÿ”น Step 1: VPC โ€” The Foundation

module "vpc" {
  source               = "../modules/vpc"
  vpc_name             = var.vpc_name
  vpc_cidr             = var.vpc_cidr
  availability_zones   = var.availability_zones
  private_subnet_cidrs = var.private_subnet_cidrs
  public_subnet_cidrs  = var.public_subnet_cidrs
  cluster_name         = var.cluster_name
}
Enter fullscreen mode Exit fullscreen mode

This module creates:

  • VPC
  • Public & private subnets
  • Routing

But the important part is not creationโ€ฆ

๐Ÿ‘‰ Itโ€™s what it exports

output "private_subnet_ids" {
  value = aws_subnet.private[*].id
}
Enter fullscreen mode Exit fullscreen mode

๐Ÿง  First Realization

Terraform modules donโ€™t โ€œtalkโ€ directly.

They communicate through:

๐Ÿ‘‰ Outputs โ†’ Inputs


๐Ÿ”น Step 2: IAM โ€” Identity Layer

module "iam" {
  source       = "../modules/iam"
  cluster_name = var.cluster_name
}
Enter fullscreen mode Exit fullscreen mode

This creates:

  • Cluster role
  • Node role
  • IRSA roles

And exposes:

output "eks_cluster_role_arn" {}
output "eks_nodes_role_arn" {}
Enter fullscreen mode Exit fullscreen mode

๐Ÿ”— Step 3: EKS Cluster โ€” Where Things Clicked

module "eks_cluster" {
  source = "../modules/eks-cluster"

  cluster_name       = var.cluster_name
  cluster_version    = var.cluster_version
  cluster_role_arn   = module.iam.eks_cluster_role_arn
  private_subnet_ids = module.vpc.private_subnet_ids
  public_subnet_ids  = module.vpc.public_subnet_ids
}
Enter fullscreen mode Exit fullscreen mode

This line changed everything for me:

module.iam.eks_cluster_role_arn
Enter fullscreen mode Exit fullscreen mode

๐Ÿ‘‰ This is not just a reference
๐Ÿ‘‰ This is a dependency signal


๐Ÿ’ฅ The Aha Moment

I didnโ€™t define any order like:

  • โ€œCreate IAM firstโ€
  • โ€œThen VPCโ€
  • โ€œThen EKSโ€

Yet Terraform automatically knew.

Why?

Because:

๐Ÿ‘‰ Dependencies define execution order


๐Ÿ”น Step 4: Node Groups โ€” Implicit Dependency

module "eks_nodes" {
  source = "../modules/eks-nodes"

  cluster_name  = module.eks_cluster.cluster_id
  node_role_arn = module.iam.eks_nodes_role_arn
  subnet_ids    = module.vpc.private_subnet_ids
}
Enter fullscreen mode Exit fullscreen mode

Now Terraform understands:

  • Nodes depend on cluster
  • Cluster depends on IAM + VPC

So it builds a graph like:

VPC โ†’ IAM โ†’ EKS โ†’ Nodes
Enter fullscreen mode Exit fullscreen mode

Without you ever writing that flow.


โš ๏ธ Mistake I Made (Important)

At one point, I hardcoded subnet IDs inside my EKS module.

It workedโ€ฆ initially.

But the moment I tried another environment โ€” everything broke.

Thatโ€™s when I understood:

๐Ÿ‘‰ Hardcoding breaks modular design
๐Ÿ‘‰ Outputs make modules reusable


โš™๏ธ Variables โ€” The Real Power

variable "cluster_name" {
  type = string
}
Enter fullscreen mode Exit fullscreen mode

Values come from:

# environments/dev/terraform.tfvars

cluster_name = "dev-cluster"
Enter fullscreen mode Exit fullscreen mode

๐Ÿ‘‰ Same code
๐Ÿ‘‰ Different environments

No duplication.


๐Ÿง  What Terraform Actually Does

When you run:

terraform apply
Enter fullscreen mode Exit fullscreen mode

Terraform does NOT just โ€œrun codeโ€.

It:

  1. Reads variables
  2. Resolves all references
  3. Builds dependency graph
  4. Plans execution order
  5. Applies resources

๐Ÿ” Backend โ€” Silent but Critical

terraform {
  backend "s3" {
    bucket = "my-tf-state"
    key    = "eks/dev/terraform.tfstate"
    region = "us-east-1"
  }
}
Enter fullscreen mode Exit fullscreen mode

This enables:

  • Remote state
  • Team collaboration
  • State locking

Without this, things get messy fast.


๐Ÿง  Final Shift in Thinking

At the beginning, Terraform felt like:

๐Ÿ‘‰ โ€œWriting infrastructure scriptsโ€

Now it feels like:

๐Ÿ‘‰ โ€œDesigning systems using data flowโ€

That shift changes everything.


๐Ÿ’ก Key Takeaways

  • main.tf is not execution โ€” itโ€™s orchestration
  • Outputs are how modules communicate
  • Dependencies are inferred, not written
  • Variables make environments scalable
  • Terraform is a graph engine, not a script runner

๐Ÿ”— Repo

https://github.com/jayakrishnayadav24/istio-ip-based-routing


๐Ÿš€ Final Thought

Once you stop thinking in terms of filesโ€ฆ

And start thinking in terms of data flowing between modulesโ€ฆ

Terraform stops being just infrastructure code.

๐Ÿ‘‰ It becomes a system design tool.


If this helped you understand Terraform at a deeper level:

โญ Star the repo
๐Ÿ” Share with others
๐Ÿ’ฌ Let me know what confused you โ€” Iโ€™ll write about it next

Happy building ๐Ÿš€

Top comments (0)