rvn-eks-cluster · Latest version: 0.2.0
Dependencies and consumers
Every dependency input can be specified manually to reference existing external infrastructure rather than a Ravion module.Readme
Production-ready Amazon EKS cluster with default managed capacity, core add-ons, and optional Fargate compute. Extend with the EKS Add-ons module (Karpenter, load balancer controller, EBS CSI, Container Insights).Overview
Amazon EKS (Elastic Kubernetes Service) runs managed Kubernetes control planes on AWS. This module creates an EKS cluster inside your selected VPC and provisions everything a working cluster needs, in the correct order:- Cluster - control plane, secrets encryption, VPC CNI, kube-proxy, Pod Identity Agent, and the AWS Load Balancer Controller IAM role; optional OIDC provider for IRSA workloads
- Default capacity - a managed node group for cluster components, add-ons, and workloads without stricter placement
- CoreDNS - installed only after compute exists so it starts healthy
- Optional compute - additional managed node groups and Fargate profiles
Use cases
Compute
Default capacity
Every cluster gets a required managed node group that provides default compute for cluster components such as CoreDNS, add-ons, and workloads without stricter placement. It defaults to 2-4 On-demandt3.medium nodes. Its settings are collapsed by default so teams using Karpenter can keep the recommended baseline without extra configuration. The minimum node count is also used as the initial size; after creation, the running node count is managed by Kubernetes autoscalers, and Terraform only enforces the min/max bounds. Each workload module can use automatic placement or target EC2 On-demand, EC2 Spot, or a dedicated Fargate profile.
Additional node groups
Add managed node groups for application workloads through the Additional node groups form. Each group independently chooses On-demand or Spot capacity, instance types, size bounds, labels, and taints. The minimum node count is also the initial node count. Add one On-demand group and one Spot group when workloads should be able to use both. Multiple instance types are especially useful for Spot because AWS can choose from more available pools.Karpenter
This module does not create any Karpenter resources. To add Karpenter autoscaling, deploy the EKS Add-ons module referencing this cluster - it provisions everything Karpenter needs (IAM roles, Pod Identity association, instance profile, interruption queue, EventBridge rules) and installs the controller and a default NodePool.Fargate
Fargate profiles run pods from selected namespaces on serverless compute instead of EC2 nodes. Each profile matches one or more namespace selectors, optionally narrowed by pod labels. Profiles use the cluster’s private subnets and a generated pod execution role unless you override them.Cluster access
By default the Kubernetes API server is reachable only from inside the VPC. Enable Public endpoint access to reach it from the internet, and restrict the allowed source ranges with Public access CIDRs. A Ravion Runner security group is created automatically and allowed to reach the API endpoint on port 443. Modules that talk to the Kubernetes API (such as EKS Add-ons with Karpenter enabled) pick it up from this cluster so their pipeline runs can reach a private endpoint, so there is nothing to configure. Its ID is available as theravion_runner_security_group_id stack output.
A Ravion Runner role is also created by default: a stable IAM role registered as an EKS access entry with cluster-admin, which Ravion Runner step executions assume when they need the Kubernetes API. This keeps per-run pipeline roles out of the cluster’s access configuration — the EKS Add-ons module assumes it automatically via aws eks get-token. Its ARN is available as the ravion_runner_role_arn stack output. The trust policy admits only this AWS account; tighten it further with the ravion_runner_role_trusted_principal_arns Terraform variable.
EKS access entries control which IAM principals can access the cluster. The IAM principal that creates the cluster is granted admin access automatically. Grant additional principals access through the Access entries form: give each entry an IAM principal ARN, then attach EKS access policies scoped to the whole cluster or to selected namespaces, and optionally map the principal to Kubernetes RBAC groups. Automatic access for Ravion deploys will be wired here in a future release.
IAM compatibility when upgrading
Add-ons use EKS Pod Identity, so the IAM OIDC provider and its certificate lookup are now off by default. Existing workloads that use IRSA needoidc_provider_creation_enabled: true under Advanced Terraform variables before upgrading to retain their provider. The cluster’s issuer URL remains available even without an IAM provider.
The cluster role no longer includes AmazonEKSVPCResourceController by default. Existing Windows networking or security groups for pods need vpc_resource_controller_policy_enabled: true under Advanced Terraform variables to retain it. Ordinary Linux pod networking and multi-AZ placement do not need it.
Managed node roles replace ECR ReadOnly with PullOnly, matching Karpenter nodes. This updates IAM attachments without replacing nodes. Worker-node and CNI permissions remain in place.
Networking
Zone-local routing
A multi-AZ cluster spreads pods across availability zones for resilience, but by default Kubernetes also spreads every in-cluster request across those zones, and AWS bills cross-AZ data transfer in both directions. This module keeps that traffic local by default:- CoreDNS is spread across zones with a
topology.kubernetes.io/zonetopology spread constraint, so every zone has a resolver. - The EKS Add-ons module patches the
kube-dnsService withtrafficDistribution: PreferClose, so DNS lookups go to the resolver in the caller’s zone. - The EKS Web Service chart sets the same
trafficDistributionon each workload Service, and both the Web Service and Worker charts spread their pods across zones, so service-to-service calls stay in-zone whenever the destination has a pod there.
ScheduleAnyway), so a two-node cluster or a Spot interruption never leaves pods pending. Zone-local routing needs Kubernetes 1.31 or later; on older versions the Service field is ignored and routing behaves as before.
Turn it off for the cluster by setting topology_aware_routing_enabled: false under Advanced Terraform variables; the EKS Add-ons module reads the same flag from this cluster’s outputs. Individual workloads keep the chart defaults regardless of the cluster flag.
Observability
Control plane logs (API server, audit, and authenticator by default) are shipped to CloudWatch Logs and shown on the module’s Logs tab. Adjust the log types and retention in the Observability section. Container Insights (node, pod, and container metrics plus application/data plane logs) is installed through the EKS Add-ons module; once enabled there, its data populates this module’s Metrics and Logs tabs. Control plane health metrics (API server requests and errors, pending pods, etcd database size) are published by EKS automatically at no cost and appear on the Metrics tab regardless.Configuration
Design decisions
This module follows AWS EKS production patterns:- Ordered provisioning: CoreDNS is installed only after the default capacity node group exists, avoiding the add-on deadlock that occurs on clusters without compute
- Private by default: the API endpoint is private unless public access is explicitly enabled
- Encrypted secrets: Kubernetes secrets are envelope-encrypted with KMS by default
- Deletion protection on: the cluster cannot be deleted until protection is turned off, preventing accidental destroys
- Autoscaler-friendly sizing: Terraform sets the initial node count but never fights an autoscaler over the running count
- Pod Identity over IRSA: add-on IAM roles use EKS Pod Identity associations; creating an IAM OIDC provider for IRSA workloads is opt-in
- Zone-local by default: CoreDNS is spread across availability zones and, together with the EKS Add-ons and workload modules, Service traffic prefers same-zone endpoints, so multi-AZ resilience does not come with cross-AZ data transfer charges on every request
Learn more
Amazon EKS- Amazon EKS User Guide - Official documentation
- EKS access entries - IAM principal access management
- EKS Pod Identity - IAM roles for workloads
- Managed node groups - EC2 node lifecycle management
- Karpenter - Just-in-time node autoscaling
- Fargate for EKS - Serverless pods
Inputs reference
All inputs forrvn-eks-cluster version 0.2.0. Use the name shown for each field as the input key in module config.
$ref:rvn-aws-network
required
VPC network.
- Immutable after creation
EKS cluster config
string
required
EKS cluster name. Name and prefix for related resources.
- Default:
<<project.given_id>>-<<environment.given_id>> - Immutable after creation
- Pattern:
^[0-9A-Za-z][A-Za-z0-9-_]{0,99}$— 1-100 letters, numbers, hyphens, and underscores. Start with a letter or number.
string
required
Kubernetes version. Kubernetes version for the EKS cluster.
- Default:
$values:first
boolean
Deletion protection. Prevent the cluster from being deleted via the AWS API. Must be turned off before this module can be destroyed.
- Default:
true
boolean
Secrets encryption. Envelope-encrypt Kubernetes secrets with a KMS key. A key is created automatically unless an existing key ARN is provided below.
- Default:
true
string
Secrets KMS key ARN. Existing KMS key for Kubernetes secrets encryption. Leave blank to create a dedicated key.
- Shown when:
{"secrets_encryption_enabled":true}
Default capacity
string
Capacity type. On-demand is stable default capacity; Spot is lower cost but nodes can be interrupted.
- Default:
ON_DEMAND - Allowed values:
ON_DEMAND(On-demand),SPOT(Spot)
string_array
required
Instance types. EC2 instance types AWS may use for this node group. Multiple types improve Spot availability.
- Default:
["t3.medium"]
number
Minimum nodes. Minimum nodes in the default managed node group. Set it high enough to run cluster components and leave spare capacity for workloads and rolling node updates.
- Default:
2 - Min:
1
number
Maximum nodes. Maximum nodes in the default managed node group. Set it high enough for peak workloads and replacement capacity during rolling node updates, otherwise pods can remain pending.
- Default:
4 - Min:
1
number
Disk size (GB). Root EBS volume size for default capacity nodes. Leave blank for the AMI default.
- Min:
20
object_map
Additional node groups. Add independently sized On-demand or Spot managed node groups when workloads need more or separate capacity. Create one of each to make both capacity types available.
- Default:
{}
Fargate
object_map
Fargate profiles. Run pods from selected namespaces on AWS Fargate instead of EC2 nodes.
- Default:
{}
Cluster access
boolean
Private endpoint access. Allow access to the Kubernetes API server from inside the VPC.
- Default:
true
boolean
Public endpoint access. Allow access to the Kubernetes API server from the public internet.
- Default:
false
string_array
Public access CIDRs. IPv4 CIDR blocks allowed to reach the public API server endpoint. Terraform defaults to 0.0.0.0/0.
- Shown when:
{"endpoint_public_access_enabled":true}
boolean
Ravion Runner role. Create an IAM role that Ravion Runner step executions assume for Kubernetes API access, registered as an EKS access entry with cluster-admin. Used by the EKS Add-ons module to install Helm charts.
- Default:
true
object_map
Access entries. Additional IAM principals that need cluster access. The principal that creates the cluster receives admin access automatically.
- Default:
{}
Observability
string_array
Control plane log types. Control plane log types shipped to CloudWatch Logs. Remove all entries to disable control plane logging.
- Default:
["api","audit","authenticator"] - Allowed values:
api(API server),audit(Audit),authenticator(Authenticator),controllerManager(Controller manager),scheduler(Scheduler)
number
Log retention (days). Retention in days for the control plane CloudWatch log group.
- Default:
30 - Min:
1
Misc
keyvalue
Tags. A map of tags to assign to all resources. Default tags are
Owner, ProjectGivenId, EnvironmentGivenId, ModuleGivenId, ModuleIdTerraform settings
string
OpenTofu version override. Override the environment’s default version for this module
string
Ravion Terraform workspace name. Override Terraform state backend workspace name. Defaults to project + environment + module given ids.
- Immutable after creation
object
Advanced Terraform variables. Optional raw Terraform variable overrides for advanced module inputs or one-off overrides. Values here override the generated variables above.
- Default:
{}