install-lilt-eks.sh has to run somewhere that can reach the Kubernetes API. When the EKS endpoint is private, which is the default for clusters created by the lilt-aws-env Terraform module, an operator’s laptop has no such route. The install runs from a small EC2 instance inside the VPC instead.
This article covers what that machine needs: the tools, the IAM permissions, and the order to do things in.
The Terraform module creates the instance when you set enable_bastion = true. Your own jump host works equally well. Nothing here depends on the module having created it.
Why a Bastion
-
The EKS API is private.
helm,kubectl, and every install script need to reach it. -
Seeding the registry moves a lot of data.
seed-registry.shpushes about 180 GB of images into your registry. From inside the VPC that traffic stays on the AWS network. From a laptop it crosses your uplink twice. - The install takes hours. A long-running unit on an instance survives a closed laptop lid.
Sizing
Give the instance a root volume with room for the largest image in the release, which is roughly 47 GB. A 120 GB volume is comfortable.seed-registry.sh streams one image at a time, so it does not need room for all 180 GB at once.
Tools
Install these before you start. The installer does not install them for you, and a missing tool usually surfaces late, after an hour of successful steps.
On Amazon Linux 2023:
IAM Permissions
The bastion’s instance profile needs whatever the install scripts call. The policy below is derived from the scripts themselves, rather than discovered one failed run at a time. Scope the resources to your own account, region, and names. Attach it to the module’s bastion withbastion_extra_policy_arns.
-
ecr:GetAuthorizationToken,route53:GetChange, and theDescribe*actions do not accept a resource ARN."*"is the only valid value, and the API itself is the boundary. -
Narrow
ReadDatabaseSecretto the specific secret where you can. When RDS manages the master password, the secret’s ARN is not known until the database exists, so scoping by a resource tag is usually easier than scoping by ARN.
Step 1: Get the Release onto the Bastion
Copy the tarball across however you normally move artifacts, then unpack it:Step 2: Point kubectl at the Cluster
kubectl get nodes times out, the bastion has no route to the API endpoint. Fix that before you go further. Every later step depends on it, and the failures it produces are much harder to read than this one.
Step 3: Write install.env
0600. It holds credentials.
Step 4: Seed the Registry
Step 5: Run the Install
Optional: run the installer as a systemd unit
Optional: run the installer as a systemd unit
For an environment you expect to rebuild, running the installer as a unit rather than in a shell survives a dropped connection and keeps the log in one place.With
RemainAfterExit=yes, use systemctl restart to run the installer again. A systemctl start against a unit that already succeeded is a silent no-op, which reads exactly like a run that finished instantly.Step 6: Verify
Three checks, working outwards from the cluster to the browser. Run them in order: each one only makes sense if the previous one passed. 1. Are the pods healthy?Init or ContainerCreating shortly after the install is usually still pulling an image; the neural images are tens of gigabytes. Anything in CrashLoopBackOff or Pending needs kubectl describe pod.
2. Did the load balancer get an address?
EXTERNAL-IP column should hold a hostname, not <pending>. Stuck at <pending> means no controller claimed the Service: on EKS, the AWS Load Balancer Controller is missing or lacks permissions. Nothing outside the cluster can reach LILT until this resolves.
3. Does the whole path work from outside?
verify=0is the part that matters. It means the certificate chain validated. A chain missing its intermediate still satisfies a browser that cached it, then fails in a stricter client later, so check it here rather than by loading the page.- Any status code means the request reached the gateway. A
200,302, or401are all fine at this stage. A connection or TLS error is not.
Tear Down in the Right Order
To decommission an environment, uninstall LILT from inside the cluster before you runterraform destroy:
When It Fails
The install is re-runnable. Fix the cause and run it again. Every component useshelm upgrade --install, which is a no-op when the chart and values are unchanged. See Resuming a failed install.
