~ / projects / eks-terraform
in progress

EKS Cluster via Terraform

Production-style EKS cluster provisioned using Terraform VPC and EKS modules with remote state in S3 + DynamoDB locking.

Terraform EKS AWS IaC Kubernetes
View on GitHub

Overview

Provisioning a production-style Amazon EKS cluster using Terraform — using the official community modules for VPC and EKS, with remote state stored in S3 and DynamoDB for state locking. This is the IaC + Kubernetes intersection that Platform Engineering roles look for.

Status: In progress as part of a structured Udemy course on Terraform and AWS. Remote backend (S3 + DynamoDB) is complete. EKS provisioning in progress.

Infrastructure Design

+-------------------------------------------------------+
|                      AWS Account                      |
|                                                       |
|  +-------------------------------------------------+  |
|  |                VPC (10.0.0.0/16)                |  |
|  |                                                 |  |
|  |  +--------------+    +--------------+           |  |
|  |  |Public Subnet |    |Public Subnet |           |  |
|  |  | ap-south-1a  |    | ap-south-1b  |           |  |
|  |  +------+-------+    +------+-------+           |  |
|  |         | NAT GW            | NAT GW            |  |
|  |  +------v-------+    +------v-------+           |  |
|  |  |Private Subnet|    |Private Subnet|           |  |
|  |  |  EKS Nodes   |    |  EKS Nodes   |           |  |
|  |  +--------------+    +--------------+           |  |
|  +-------------------------------------------------+  |
|                                                       |
|  EKS Control Plane (managed)                          |
|  Node Group: t3.medium × 2 (min 1, max 4)             |
+-------------------------------------------------------+

  Remote State:
  S3 bucket: sandeeprn-tf-state
  DynamoDB:  sandeeprn-tf-lock

Remote Backend (Complete)

The first piece — remote state with locking prevents concurrent applies from corrupting state:

# backend.tf
terraform {
  backend "s3" {
    bucket         = "sandeeprn-tf-state"
    key            = "eks-cluster/terraform.tfstate"
    region         = "ap-south-1"
    dynamodb_table = "sandeeprn-tf-lock"
    encrypt        = true
  }
}

The S3 bucket and DynamoDB table are themselves provisioned by a separate bootstrap Terraform config — state for the state backend is local only:

# bootstrap/main.tf
resource "aws_s3_bucket" "tf_state" {
  bucket = "sandeeprn-tf-state"
}

resource "aws_s3_bucket_versioning" "tf_state" {
  bucket = aws_s3_bucket.tf_state.id
  versioning_configuration { status = "Enabled" }
}

resource "aws_dynamodb_table" "tf_lock" {
  name         = "sandeeprn-tf-lock"
  billing_mode = "PAY_PER_REQUEST"
  hash_key     = "LockID"
  attribute {
    name = "LockID"
    type = "S"
  }
}

EKS Cluster (In Progress)

Using the official terraform-aws-modules/eks and terraform-aws-modules/vpc modules:

module "vpc" {
  source  = "terraform-aws-modules/vpc/aws"
  version = "~> 5.0"

  name = "sandeeprn-eks-vpc"
  cidr = "10.0.0.0/16"

  azs             = ["ap-south-1a", "ap-south-1b"]
  private_subnets = ["10.0.1.0/24", "10.0.2.0/24"]
  public_subnets  = ["10.0.101.0/24", "10.0.102.0/24"]

  enable_nat_gateway = true
  single_nat_gateway = true  # cost optimisation for non-prod

  tags = {
    "kubernetes.io/cluster/sandeeprn-eks" = "shared"
  }
}

module "eks" {
  source  = "terraform-aws-modules/eks/aws"
  version = "~> 20.0"

  cluster_name    = "sandeeprn-eks"
  cluster_version = "1.30"

  vpc_id     = module.vpc.vpc_id
  subnet_ids = module.vpc.private_subnets

  eks_managed_node_groups = {
    general = {
      desired_size   = 2
      min_size       = 1
      max_size       = 4
      instance_types = ["t3.medium"]
    }
  }
}

What This Demonstrates

  • IaC best practices — remote state, state locking, module reuse over hand-rolled resources
  • EKS architecture — private node groups, NAT gateway, proper subnet tagging for Kubernetes
  • Terraform module usage — community modules vs writing everything from scratch (the right call for well-tested infra patterns)
  • Cost awareness — single NAT gateway for non-prod, PAY_PER_REQUEST DynamoDB, right-sized nodes