Kubernetes

Kubernetes Infrastructure with Terraform: EKS, GKE, and AKS Setup Guide

By CloudFormation Team ยท 2025-06-12 ยท 15 min read

Why Manage Kubernetes with Terraform?

Terraform manages the infrastructure layer of Kubernetes โ€” the cluster, node pools, networking, IAM roles, and storage โ€” while tools like Helm or Flux manage the application layer (Deployments, Services, ConfigMaps). This separation gives you full lifecycle control over your clusters alongside your other cloud infrastructure.

AWS EKS with Terraform

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

  cluster_name    = "${var.project}-eks"
  cluster_version = "1.29"
  vpc_id          = module.vpc.vpc_id
  subnet_ids      = module.vpc.private_subnet_ids

  cluster_endpoint_public_access  = true
  cluster_endpoint_private_access = true

  eks_managed_node_groups = {
    general = {
      instance_types = ["m6i.large"]
      min_size       = 2
      max_size       = 10
      desired_size   = 3
      disk_size      = 50
    }
    gpu = {
      instance_types = ["g4dn.xlarge"]
      min_size       = 0
      max_size       = 4
      desired_size   = 0
      taints = [{
        key    = "nvidia.com/gpu"
        value  = "true"
        effect = "NO_SCHEDULE"
      }]
    }
  }
}

Google GKE Autopilot

resource "google_container_cluster" "main" {
  name     = "${var.project}-gke"
  location = var.region

  enable_autopilot = true  # Google manages node pools automatically

  network    = google_compute_network.main.name
  subnetwork = google_compute_subnetwork.private.name

  private_cluster_config {
    enable_private_nodes    = true
    enable_private_endpoint = false
    master_ipv4_cidr_block  = "172.16.0.0/28"
  }

  workload_identity_config {
    workload_pool = "${var.project_id}.svc.id.goog"
  }
}

Azure AKS

resource "azurerm_kubernetes_cluster" "main" {
  name                = "${var.project}-aks"
  location            = azurerm_resource_group.main.location
  resource_group_name = azurerm_resource_group.main.name
  dns_prefix          = var.project
  kubernetes_version  = "1.29"

  default_node_pool {
    name                = "system"
    node_count          = 3
    vm_size             = "Standard_D4s_v3"
    os_disk_size_gb     = 128
    type                = "VirtualMachineScaleSets"
    enable_auto_scaling = true
    min_count           = 2
    max_count           = 10
  }

  identity { type = "SystemAssigned" }

  oidc_issuer_enabled       = true
  workload_identity_enabled = true
  azure_policy_enabled      = true
}

Installing Helm Charts with Terraform

resource "helm_release" "cert_manager" {
  name             = "cert-manager"
  repository       = "https://charts.jetstack.io"
  chart            = "cert-manager"
  version          = "v1.14.0"
  namespace        = "cert-manager"
  create_namespace = true

  set { name = "installCRDs"; value = "true" }

  depends_on = [module.eks]
}

resource "helm_release" "ingress_nginx" {
  name             = "ingress-nginx"
  repository       = "https://kubernetes.github.io/ingress-nginx"
  chart            = "ingress-nginx"
  version          = "4.9.0"
  namespace        = "ingress-nginx"
  create_namespace = true
}
Always use explicit chart versions in production Helm releases. Floating versions like latest cause unexpected upgrades during terraform apply.

Production Hardening Checklist

  • Enable private cluster endpoints โ€” master API not exposed to internet
  • Use managed identity / Workload Identity for pod AWS/GCP/Azure access
  • Set resource requests and limits on all pods
  • Enable Pod Disruption Budgets for critical workloads
  • Use Cluster Autoscaler or Karpenter for node auto-scaling
  • Enable network policies (Calico or Cilium)
  • Separate system and application node pools
  • Enable audit logging for the Kubernetes API server

Try CloudFormation Free

Design infrastructure visually and generate production-ready Terraform in seconds โ€” 693 resources across 9 cloud providers.

๐Ÿš€ Open the Designer โ†’