Skip to main content
The EKS install package ships a Terraform module, lilt-aws-env, that provisions the AWS infrastructure LILT runs on. This article covers what the module creates, how to configure it, and how to map its outputs into the installer’s configuration. You do not need access to any LILT source repository. The module is a plain local module inside the tarball.

The Two Layers

An EKS deployment has two layers, and they run in order:
  1. lilt-aws-env provisions the AWS resources: subnets, the EKS cluster and its node groups, the RDS database, the S3 bucket, the SQS queue, and the IAM roles the workloads assume.
  2. install-lilt-eks.sh deploys LILT onto that cluster with Helm. See Install System (AWS EKS).
If you already have a cluster, or you provision AWS resources with your own tooling, skip this article and see Install on an existing EKS cluster instead.

Prerequisites

Tools

AWS

  • An IAM role or user that can create EKS, RDS, S3, SQS, IAM, KMS, and Route53 resources in the target account.
  • A VPC with at least one NAT gateway. The module creates subnets inside your VPC. It does not create the VPC.
  • Two non-overlapping CIDR blocks available in that VPC for the module’s private subnets. A /22 in each of two availability zones is a reasonable starting point.
  • A Route53 hosted zone for your base domain.

What the Module Creates

Instantiate the Module

Create a terraform/ directory next to the extracted tarball, so that the relative module path resolves:
Every variable without a default is required. The following example sets the required variables plus the ones most deployments tune:
Then run:
eks_bootstrap_creator_admin has no default, and AWS treats an unset value as false. The cluster is then reachable only by the principals listed in eks_cluster_admin_arns and by the bastion. If you leave both empty, every kubectl call returns a 401 and there is no way back in. Confirm that eks_cluster_admin_arns contains a role you can assume before you apply.

Required Variables

Commonly Tuned Variables

Raise eks_application_volume_size above its 100 GB default. The neural services pull trained-data images that are tens of gigabytes compressed and roughly double that unpacked, so 100 GB cannot hold one. The pull fails part way through with no space left on device. A 300 GB volume is a safe starting point.

GPU Node Groups

eks_extra_node_groups defaults to the four GPU pools LILT needs. LILT spreads its GPU workloads across all four, and a partial set fails in a way that does not name itself: batch-worker-gpuv4 stays Pending, and the neural services block on the artifacts endpoint it serves rather than reporting a GPU shortage. Each pool carries the nvidia.com/gpu taint and the capability: gpu label that the LILT charts select on. Four warm GPU nodes are expensive. To let the autoscaler bring each pool up on demand, set min_size to 0 for the pools you want cold. Cluster Autoscaler is enabled by default, which is what makes a group at zero discoverable. For an infrastructure-only deployment with no GPU workloads, set eks_extra_node_groups = {}.
Widen availability_zones on each GPU pool. The default is empty, which places every pool in the cluster’s own two zones. GPU instance types are frequently capacity-constrained per zone: a g6.12xlarge request can return InsufficientInstanceCapacity in both zones, and the group has nowhere else to go. Listing every zone in the region for each pool avoids this. The field is replace-forcing, so set it before your first apply.
Setting eks_extra_node_groups replaces the default map wholesale rather than merging into it, so list every pool you want, not only the one you are changing. The block below is the shipped default with availability_zones added to each pool. Substitute the zones your region offers.
The gpu-class label is what the LILT charts select on, so each pool needs its own value. The root volumes are large because the neural services pull trained-data images of tens of gigabytes. To let the autoscaler bring a pool up only when something needs it, set that pool’s min_size to 0. cluster_autoscaler = true is what makes a group at zero discoverable.

Workload Identity

iam_auth_method selects how pods obtain AWS credentials. Use pod_identity for a new environment. Use irsa only when something in your environment already depends on OIDC federation.
The module and the installer default to different values. Set both. The module’s iam_auth_method defaults to pod_identity, but the installer’s IAM_AUTH_METHOD defaults to irsa. Left at their defaults, the module creates Pod Identity associations and no OIDC provider, and the installer then annotates the service accounts with eks.amazonaws.com/role-arn anyway. The annotation wins over the association, the SDK looks for a web identity provider that the account does not have, and every S3 call fails with a credentials error that mentions none of this.Set IAM_AUTH_METHOD in install.env to the same value as the module’s iam_auth_method:
Under pod_identity, leave the service accounts unannotated. The installer does that for you once IAM_AUTH_METHOD is set correctly.

Read the Outputs

The install scripts find IAM roles by a substring match on the role name, not the ARN. Take the part after the last slash: arn:aws:iam::111122223333:role/acme-prod-app-workload becomes acme-prod-app-workload.

The PREFIX Shortcut

If you set PREFIX in install.env to the same value as the module’s prefix, the installer derives these names and you can leave them unset:
  • CLUSTER_NAME becomes <PREFIX>-eks
  • RDS_IDENTIFIER becomes <PREFIX>-rds
  • S3_BUCKET becomes <PREFIX>-s3
  • SQS_QUEUE_URL becomes https://sqs.<AWS_REGION>.amazonaws.com/<account>/<PREFIX>-sqs
  • APP_WORKLOAD_ROLE_NAME becomes <PREFIX>-app-workload
  • CLUSTER_AUTOSCALER_ROLE_NAME becomes <PREFIX>-cluster-autoscaler
  • CERT_MANAGER_ROLE_NAME becomes <PREFIX>-cert-manager-role

Certificate Ownership

Both the module and the installer can obtain a TLS certificate, and both write the same lilt-com-tls secret. Pick one.
  • Set enable_tls_certificate = true in the module to run an ACME DNS-01 challenge against your Route53 zone and store the certificate in Vault. Leave ENABLE_CERT_MANAGER=false in install.env.
  • Or leave the module’s flag at false and set ENABLE_CERT_MANAGER=true in install.env, which makes cert-manager the permanent owner of the secret.
Enabling both makes the two owners compete for the same Let’s Encrypt identifier set, which is rate-limited to five certificates per 168 hours. You lose the week.
Whichever path you choose, the certificate must cover every LILT hostname. The hostnames are siblings, not subdomains, so a *.<subdomain>.<base_domain> wildcard does not cover them. The full list is in install.env.example, and it includes core-api-, connectors-api-, and wso2- prefixed names. If you miss one, browsers look correct while API clients fail hostname verification, which reads as a TLS bug rather than as a missing name.

Version Pinning

The module is vendored into the tarball at a single commit. Read terraform-modules/lilt-aws-env/PROVENANCE.md in the extracted tarball to see which commit shipped with your release. To source the module from a location of your own, copy the terraform-modules/lilt-aws-env directory wherever suits your layout and point source at it. Pin by commit rather than by branch so that a given apply is reproducible.

Known Constraints

  • eks_service_cidr defaults to empty, which lets AWS pick 10.100.0.0/16. Changing this value later replaces the cluster. Pin it before your first apply if you might ever need a different range.
  • enable_karpenter = true creates the AWS prerequisites, the IAM role and the SQS interruption queue. It does not install the Karpenter controller.
  • Let’s Encrypt limits you to five certificates per identifier set per 168 hours. Repeated rebuilds of the same environment exhaust that quota.

Next Steps