Why cluster setup deserves real design time
A cluster that works on day one can still be wrong. The decisions that hurt later are rarely about Kubernetes itself: a pod CIDR that is too small, a public API endpoint nobody meant to expose, one node pool for every workload, or add-ons installed by hand and forgotten. Fixing these on a live cluster usually means replacing it.
Our Kubernetes consulting work starts with these early decisions, because kubernetes cluster setup with Terraform is mostly about getting the foundations right once and making them repeatable. If you are earlier in the journey and still clicking through a console, the ClickOps to Terraform guide explains why that stops scaling.
Choosing between EKS, AKS and GKE
All three run a conformant control plane for you. The differences that matter in practice sit around the cluster.
| Concern | EKS | AKS | GKE |
|---|---|---|---|
| Identity for pods | IAM Roles for Service Accounts or EKS Pod Identity | Entra Workload ID | Workload Identity Federation |
| Node autoscaling | Karpenter or Cluster Autoscaler | Cluster Autoscaler, node auto provisioning | Cluster Autoscaler, Autopilot option |
| Best fit | Existing AWS estate | Existing Azure and Entra ID estate | Teams free to pick a cloud |
Pick the platform your identity, networking and compliance already live in. Moving a cluster between clouds later is possible (we do cloud migrations), but it is a project in its own right. We cover cloud specific detail in our AWS EKS consulting service and the dedicated AKS and GKE pages.
What a good architecture looks like
- Private by default. The API endpoint is private or restricted by CIDR, nodes sit in private subnets, and outbound traffic goes through controlled egress.
- Sized for pods. Pod and service address ranges are planned for growth, because exhausting IPs is a common production surprise.
- Separated node pools. System components, general workloads and special cases (GPU, memory heavy, spot tolerant) run on different pools, using taints and tolerations to keep them apart.
- Workload identity, not static keys. Pods assume cloud roles through the platform’s federation mechanism.
- Encryption and logging on. Secrets encryption with a managed key, control plane logs shipped somewhere searchable.
- Spread across zones. At least three availability zones where the region allows it, with topology spread configured on workloads.
How we structure the Terraform
Layout matters as much as content. We separate three layers, each with its own state so a mistake in one cannot destroy another:
- Network layer: VPC or VNet, subnets, routing, NAT and private endpoints.
- Cluster layer: the managed control plane, node pools, encryption and identity wiring.
- Platform layer: add-ons installed through Helm or a GitOps tool, such as ingress, metrics and policy.
A trimmed EKS example using the community module shows the shape:
module "eks" {
source = "terraform-aws-modules/eks/aws"
version = "~> 20.0"
cluster_name = "platform-prod"
cluster_version = var.kubernetes_version
vpc_id = module.network.vpc_id
subnet_ids = module.network.private_subnet_ids
cluster_endpoint_public_access = false
eks_managed_node_groups = {
system = {
instance_types = ["m6i.large"]
min_size = 2
max_size = 3
taints = [{
key = "CriticalAddonsOnly"
value = "true"
effect = "NO_SCHEDULE"
}]
}
}
}
Pin module versions and pass the Kubernetes version as a variable, so an upgrade is a one line, reviewed change. State handling is its own discipline, covered in our Terraform state management work and the broader Terraform infrastructure as code service.
Decisions and trade-offs
Managed node groups or Karpenter. Managed node groups are simple and predictable. Karpenter chooses instance types dynamically and can reduce waste, but it adds a component to operate and learn. For a small, stable workload, node groups are often enough.
Serverless nodes. Options like Fargate or Autopilot remove node management but constrain DaemonSets, privileged workloads and cost control. They suit some teams and frustrate others.
Terraform for add-ons or GitOps. Terraform can install Helm charts, but ongoing application configuration belongs in GitOps. Our rule: Terraform builds the cluster and bootstraps the GitOps controller, and GitOps owns everything running inside.
When not to build this. If you run two or three small services with modest traffic, a managed container platform may serve you better than a cluster and the team it needs. We will tell you if that is the case.
Worked example: planning address space before the first apply
Suppose a team plans one production cluster in a single VPC and expects to double its service count within a year. We would work through the address plan on paper before any code is written. First, list what consumes IPs: nodes, and on EKS with the default VPC CNI, every pod as well. Second, multiply by the number of availability zones, because each zone needs its own subnet. Third, add headroom for rolling upgrades, when old and new nodes briefly coexist.
If the result does not fit the existing ranges, there are three honest options: choose larger subnets, add a secondary CIDR for pods, or use a CNI mode that reduces pod IP consumption. Each has costs, and we record the choice in the decision log so nobody rediscovers the problem during an incident.
Common failure modes
- Pod IP exhaustion from small subnets, avoided by sizing ranges up front.
- Open API endpoints left public after testing.
- Node role over-permissioning, where every pod inherits the node’s cloud permissions.
- Unpinned add-ons that change behaviour on the next apply.
- Single zone nodes, causing outages during a zone problem.
- State drift from manual console changes, caught by regular plan runs in the pipeline.
Handover and what you receive
At the end you have a repository with documented modules, a diagram of the network and identity design, a decision record explaining each major choice, and a recorded session with your engineers applying a change end to end. Operating the cluster afterwards can stay with your team, or move to our Managed DevOps service.
How to tell it is working
- A new environment can be created from code with no manual steps.
terraform planon a quiet day shows no changes (no drift).- Losing a node or a zone does not take down replicated workloads.
- Engineers can explain where a given setting lives without asking the original builder.
If you want an independent view on a planned or existing design, book a consultation and bring your current network diagram.