DEV Community

POTHURAJU JAYAKRISHNA YADAV for AWS Community Builders

Posted on • Edited on

πŸ” 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)