Skip to content

Latest commit

 

History

History
130 lines (100 loc) · 5.26 KB

File metadata and controls

130 lines (100 loc) · 5.26 KB

module: EKS

EKS cluster, node groups, OIDC provider, addons

Provisions the EKS cluster, managed node groups, OIDC identity provider, and core Kubernetes addons. This module is the runtime environment where all application workloads run.

What this module creates

EKS Cluster (Kubernetes 1.29)
├── Managed Node Group "applications"
│   ├── EC2 instances in private subnets
│   ├── Auto Scaling Group (min / desired / max)
│   └── IAM node role (ECR pull, SSM, CloudWatch)
├── OIDC Identity Provider
│   └── Enables IRSA — pods assume IAM roles without static keys
└── Cluster Addons
    ├── coredns    — DNS resolution inside the cluster
    ├── kube-proxy — network rules on each node
    └── vpc-cni    — gives each pod a real VPC IP address

OIDC and why it matters

The OIDC provider is the most important thing this module creates beyond the cluster itself. It registers the cluster as a trusted identity provider with AWS IAM, which enables IRSA (IAM Roles for Service Accounts).

Without IRSA, giving a pod access to AWS services (S3, Secrets Manager, etc.) requires embedding static access keys — a security risk. With IRSA, a pod's Kubernetes service account is mapped to an IAM role, and AWS issues short-lived credentials automatically. No keys stored anywhere.

The ALB Ingress Controller uses IRSA. Any future service that needs AWS access (read from S3, send to SQS, etc.) should use IRSA too.

Usage

module "eks" {
  source = "../../modules/eks"
 
  cluster_name       = "aetherion-dev"
  environment        = "dev"
  vpc_id             = module.vpc.vpc_id
  private_subnet_ids = module.vpc.private_subnet_ids
 
  node_instance_type = "t3.medium"
  node_desired_size  = 2
  node_min_size      = 1
  node_max_size      = 5
}

Inputs

Name Type Default Description
cluster_name string Name of the EKS cluster
environment string dev or prod, applied as a node label and tag
vpc_id string VPC to deploy the cluster into — from module.vpc.vpc_id
private_subnet_ids list(string) Subnets for nodes — from module.vpc.private_subnet_ids
cluster_version string "1.29" Kubernetes version. Changing this triggers a cluster upgrade
node_instance_type string "t3.medium" EC2 instance type for worker nodes
node_desired_size number 2 Initial number of nodes
node_min_size number 1 Minimum nodes (ASG lower bound)
node_max_size number 5 Maximum nodes (ASG upper bound)

Outputs

Name Description Consumed by
cluster_name Cluster identifier environments/*/outputs.tf, GHA workflow
cluster_endpoint API server URL kubectl, GHA workflow
oidc_issuer_url Bare OIDC URL (no https://) modules/iam trust policies
oidc_provider_arn Full ARN of the OIDC provider modules/iam trust policies
node_role_arn IAM role ARN attached to nodes modules/iam if additional node policies needed

Cluster addons

Addons are AWS-managed components that run inside the cluster. Using managed addons means AWS handles version compatibility and patching.

Addon Purpose Why before_compute = true on vpc-cni
vpc-cni Assigns VPC IPs to pods Must exist before nodes join or they boot without pod networking
coredns In-cluster DNS Pods resolve service-name.namespace.svc.cluster.local
kube-proxy iptables rules on nodes Service-to-pod routing
cluster_addons = {
  vpc-cni = {
    most_recent              = true
    before_compute           = true
    resolve_conflicts_on_update = "OVERWRITE"
  }
  coredns = {
    most_recent              = true
    resolve_conflicts_on_update = "OVERWRITE"
  }
  kube-proxy = {
    most_recent              = true
    resolve_conflicts_on_update = "OVERWRITE"
  }
}

Dev vs prod differences

Setting Dev Prod
node_instance_type t3.medium t3.xlarge or larger
node_desired_size 2 4+
node_max_size 5 20+
cluster_endpoint_public_access true true with CIDR restrictions

In prod, consider restricting cluster_endpoint_public_access_cidrs to your office/VPN IP ranges so the Kubernetes API is not reachable from the public internet.

After apply — configure kubectl

Once terraform apply completes, run this once to configure your local kubectl:

aws eks update-kubeconfig \
  --name aetherion-dev \
  --region us-east-2
 
# verify
kubectl get nodes

Notes

  • Never run nodes in public subnets. Nodes in public subnets get public IPs, which exposes the kubelet port (10250) and node ports to the internet. Always use private subnets.
  • Cluster upgrades are in-place — changing cluster_version triggers a rolling upgrade. EKS upgrades the control plane first, then you re-apply to upgrade node groups. Test in dev before applying to prod.
  • The node group is named applications — this matches the karpenter.sh/nodepool: applications node selector in your Helm values files.