EKS
KSail supports Amazon Elastic Kubernetes Service (EKS) as a managed Kubernetes distribution via eksctl. A declarative eks.yaml (eksctl ClusterConfig) defines the cluster shape; KSail provisions it and manages its lifecycle with the same commands used for local clusters.
EKS is the only distribution that uses the AWS provider. It is a cloud distribution — local mirror registries and local registry containers are not supported.
When to Use EKS
Section titled “When to Use EKS”EKS is ideal when you:
- Need a managed AWS Kubernetes cluster with full cloud integrations (ELB, EBS, VPC, IAM OIDC)
- Want to use the same KSail workflow (init → create → update → delete) for cloud clusters
- Require GitOps workflows (Flux or ArgoCD) on managed AWS infrastructure
For local development and testing, consider the Vanilla, K3s, or VCluster distributions instead.
Prerequisites
Section titled “Prerequisites”- AWS account — with permissions to create EKS clusters, IAM roles, and VPCs
- AWS credentials — configure via
aws configureor environment variables (AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY,AWS_REGION,AWS_DEFAULT_REGION) - Docker — required locally for the
ksailCLI
What EKS Provides by Default
Section titled “What EKS Provides by Default”| Component | Status | Details |
|---|---|---|
| CNI | Built-in | Amazon VPC CNI (vpc-cni addon) |
| CSI | Add-on | Amazon EBS CSI Driver (aws-ebs-csi-driver addon scaffolded in eks.yaml) |
| LoadBalancer | Built-in | AWS Service type LoadBalancer support via AWS cloud integration |
| Metrics Server | ❌ | Not provided by default |
EKS includes the Amazon VPC CNI and in-tree Service type LoadBalancer support as part of the managed service. The Amazon EBS CSI Driver is an EKS add-on requested by KSail’s default eks.yaml scaffold (aws-ebs-csi-driver) rather than built into the distribution itself.
Quick Start
Section titled “Quick Start”1. Initialize an EKS Project
Section titled “1. Initialize an EKS Project”mkdir my-eks-clustercd my-eks-cluster
ksail project init \ --name eks-default \ --distribution EKS \ --provider AWSThis generates:
ksail.yaml— KSail cluster configurationeks.yaml— eksctlClusterConfig(source of truth for cluster metadata)k8s/kustomization.yaml— directory for Kubernetes manifests
2. Review and Edit eks.yaml
Section titled “2. Review and Edit eks.yaml”The scaffolded eks.yaml is a minimal starting point:
# eksctl cluster configuration.# See https://eksctl.io/usage/schema/ for the full schema.apiVersion: eksctl.io/v1alpha5kind: ClusterConfig
metadata: name: eks-default region: us-east-1 version: "1.31"
iam: withOIDC: true
addons: - name: vpc-cni - name: kube-proxy - name: coredns - name: aws-ebs-csi-driver
managedNodeGroups: - name: default instanceType: t3.medium desiredCapacity: 2 minSize: 1 maxSize: 3 volumeSize: 20 amiFamily: AmazonLinux2023Edit this file to match your AWS environment: region, Kubernetes version, instance types, nodegroup sizing, and addon configuration. Creating a cluster requires this file; read-only operations (list, info) and lifecycle ones (start, stop, delete) work against an existing cluster without it.
3. Configure ksail.yaml
Section titled “3. Configure ksail.yaml”The ksail.yaml references your EKS cluster. All cluster metadata lives in eks.yaml — do not duplicate it in ksail.yaml:
# yaml-language-server: $schema=https://raw.githubusercontent.com/devantler-tech/ksail/main/schemas/ksail-config.schema.jsonapiVersion: ksail.io/v1alpha1kind: Clustermetadata: name: eks-defaultspec: cluster: distribution: EKS provider: AWS4. Create the Cluster
Section titled “4. Create the Cluster”export AWS_ACCESS_KEY_ID=your-access-keyexport AWS_SECRET_ACCESS_KEY=your-secret-keyexport AWS_REGION=us-east-1
ksail cluster createKSail invokes eksctl to provision the cluster from eks.yaml and waits for completion. See the AWS provider guide for the full credential and environment-variable reference.
Lifecycle
Section titled “Lifecycle”| Command | Effect |
|---|---|
ksail cluster create |
Provisions the cluster from eks.yaml via eksctl and waits for it |
ksail cluster update |
Applies managed node-group capacity changes in-place |
ksail cluster delete |
Deletes the cluster, unwinding the eksctl CloudFormation stacks |
ksail cluster stop |
Scales every managed nodegroup to zero to halt node costs |
ksail cluster start |
Restores the desired, minimum, and maximum capacity saved by stop |
ksail cluster list |
Lists clusters in the configured region (all regions when unset) |
ksail cluster info |
Shows cluster details |
Recover missing local ownership state
Section titled “Recover missing local ownership state”On a new machine, or after losing local KSail state, use the experimental
eks-bind command to recover the identity of an existing eksctl-created cluster.
Neither ksail.yaml, eks.yaml, nor the original creation snapshot is required.
Name the cluster and provider explicitly, and select the intended region:
AWS_REGION=eu-north-1 ksail cluster eks-bind --experimental --name my-cluster --provider AWSThe command makes read-only queries and displays the AWS account, cluster ARN,
region, and creation time. It exits without writing state until you repeat the
command with --yes after reviewing that identity. Your selected credentials must
be able to inspect the cluster and its eksctl provenance.
The confirmed command writes only a local immutable identity record and credential
environment-variable names. It never stores credential values, creates a synthetic
creation snapshot, or changes AWS resources. CLI lifecycle operations can then
use that record. For local web and desktop, select the recorded region in Settings
and refresh the cluster list before choosing the recovered cluster. The list follows
the selected region; the ownership record alone does not add a row. Every mutation
still checks the live account and exact cluster incarnation. The recovery command
remains off by default behind --experimental.
When the local web or desktop backend has no rendered EKS config, it rebuilds one from the single recorded region for a selected cluster. Multiple recorded regions, corrupt state, conflicting configuration, and changed live identities are refused. Use an explicitly selected CLI target when the local API cannot distinguish same-named clusters across regions.
Rebinding clears old node-group capacity snapshots. If a cluster was already stopped when its local state was lost, recovery cannot reconstruct its previous capacity; set the desired capacity through your reviewed EKS configuration or AWS tooling before relying on a later stop/start cycle.
Experimental control-plane upgrades
Section titled “Experimental control-plane upgrades”To upgrade an ACTIVE EKS control plane from 1.34 to 1.35, set an explicit target
and opt in through ksail.yaml:
spec: cluster: distribution: EKS kubernetesVersion: "1.35" eks: experimentalControlPlaneUpgrade: truePreview with ksail cluster update --dry-run, then run ksail cluster update.
The existing --kubernetes-version 1.35 flag overrides the YAML target.
ksail cluster diff --include-version-drift reports the supported control-plane change
as an in-place update. Without a target, KSail does not discover or select a newer
EKS version. The opt-in is false by default and applies only to the CLI.
The operator reports it through IgnoredFields and does not perform the upgrade.
Targets may use 1.35, v1.35 or the equivalent zero-patch forms. KSail accepts
one forward minor step or an already-current no-op. It rejects skipped minors,
nonzero patch versions, prereleases and rollback requests, including in previews.
The create-time version remains in eks.yaml; this target controls updates.
An explicit upgrade target cannot be combined with changes that require cluster
recreation. Apply those changes in separate updates and align eks.yaml
metadata.version before recreating the cluster.
The AWS caller needs eks:UpdateClusterVersion, eks:DescribeUpdate and the
existing cluster-inspection permissions. KSail verifies immutable cluster
ownership and freezes EKS/STS endpoint and credential selection. It rereads the
cluster identity, ACTIVE status and starting version immediately before submission.
AWS readiness checks remain enabled; KSail does not force an upgrade past them.
KSail waits for the exact AWS update to succeed, then checks that the same cluster is ACTIVE at the requested version. The wait is capped at 65 minutes and respects an earlier caller deadline or cancellation. Canceling KSail stops waiting; an accepted AWS update can continue. Inspect its status before retrying. Once ACTIVE at the target, another update is a no-op.
Before submitting, KSail checks the effective credentials of both the EKS and STS clients, including service-specific overrides. Each must cover the wait deadline plus one minute. Temporary credentials must come from a provider that reports their expiry and have sufficient lifetime remaining. A session-token tuple without expiry metadata is rejected for upgrades; dry runs remain available. KSail retains the selected credentials throughout verification and does not refresh into a different identity. The checked credentials sign the final cluster check, the update and its wait, and are released when the upgrade ends; a second upgrade cannot start on a client that still holds them. Reusing a captured selection preserves its expiry and endpoint settings; node-group inventory also retains the captured CloudFormation endpoint if the process environment changes.
This operation changes only the control plane. Upgrade worker nodes and add-ons separately and check their compatibility; managed node groups must meet AWS’s version prerequisites. KSail does not repair cluster stacks or change remote network configuration as part of this operation. Concurrent direct AWS operations are outside KSail’s control, and the AWS version API has no conditional expected-version parameter.
The feature remains experimental pending live AWS validation. See AWS’s upgrade guidance for service prerequisites and rollback operations outside this forward-upgrade path.
Add a managed node group (experimental)
Section titled “Add a managed node group (experimental)”To create a new managed node group on an existing cluster, enable the opt-in in
ksail.yaml:
spec: cluster: eks: experimentalManagedNodegroupCreation: trueAdd the group to managedNodeGroups in eks.yaml, keeping the existing groups in
the file. Each group must have a unique name. Review the planned changes before
applying them:
ksail cluster update --dry-runksail cluster updateKSail verifies the existing cluster’s ownership and uses
eksctl create nodegroup
to create each missing managed group separately. The configuration preserves the
new group’s instance, networking, storage, labels, taints, and IAM settings.
Self-managed groups under nodeGroups are not created by this operation. KSail
reports an addition as applied only after the live managed group is ACTIVE and
its declared capacity and instance type match. A ksail.io/nodegroup-creation-id
tag identifies the group created by that update.
Before applying any changes, KSail checks each addition against a conservative 50-slot tag budget. It counts metadata tags both in the stack and in the merged group tags, includes the ownership marker and eksctl node-group identifiers, and reserves four slots for eksctl stack identifiers and generated resource names. This reserve also applies when an external role or launch template needs fewer tags. With no metadata tags, up to 43 distinct user tag keys fit this budget; metadata tags reduce that allowance. Existing groups and scaling are unaffected. Other AWS and eksctl tag restrictions still apply.
The selected AWS identity also needs eks:ListNodegroups,
eks:DescribeNodegroup, and cloudformation:ListStacks read permissions. KSail
reads every inventory page and refuses creation if a live or unfinished eksctl
node-group stack already uses the new group’s name.
If the source file changes during the update, ownership verification fails, or the live inventory is ambiguous, the update stops. After a failed or interrupted creation, inspect the group in EKS before retrying. An unfinished or failed group blocks the next update; an active group already matching the supported settings is not created again. Earlier successful additions remain in place when a later addition fails.
This option defaults to false and is pending
live EKS validation. Scaling
existing groups does not require the option. Removing a managed group or changing
its instance type still requires recreation and prevents additions in the same
update. Changes to other settings on existing groups are not currently detected.
Concurrent lifecycle operations
Section titled “Concurrent lifecycle operations”EKS start, stop, and delete operations from the CLI and the local web/desktop
backend share an operating-system lock for each cluster name in the current user’s
KSail state directory. A competing process waits before resolving ownership,
reading capacity snapshots, or changing the cluster. Canceling a CLI command while
it waits leaves the cluster and its saved state unchanged. A second operation in
the same local API service still reports an immediate conflict.
The lock covers the complete operation, including restoration verification and state cleanup after deletion. AWS account, cluster ARN, and creation-time identity checks still verify the selected target before mutation. Same-named clusters in different regions serialize because their local metadata shares a name-scoped directory; changing a region or credential selector does not bypass the lock.
Lock files remain under ~/.ksail/locks/eks/, outside the removable cluster state.
The operating system releases the lock when the process exits, including after a
crash. An existing lock file is normal; do not remove it to interrupt an operation.
This coordination applies to processes sharing that local state store. Other
machines, direct AWS operations, create, and update are outside this lock.
kubeconfig Context
Section titled “kubeconfig Context”EKS contexts written by eksctl follow the format <iam-identity>@<name>.<region>.eksctl.io, where <iam-identity> is the last path segment of the caller’s ARN: an IAM user name, or the session name of an assumed role.
When spec.cluster.connection.context is not set, KSail selects the context for the configured cluster and region whose cluster entry points at the API endpoint AWS reports for the cluster KSail created. A context for another cluster with the same name and region, for example in a different AWS account, is never selected. Set spec.cluster.connection.context in ksail.yaml to choose a context yourself.
Limitations
Section titled “Limitations”- EKS is a cloud distribution — local mirror registries and local registry containers are not supported. Use external registry URLs (e.g.,
docker.io=https://registry-1.docker.io) - EKS only supports the AWS provider — the Docker, Hetzner, and Omni providers are not available
- The control plane keeps running (and billing) while nodegroups are stopped — use
ksail cluster deleteto tear down the cluster and stop its cluster-related charges (resources provisioned by workloads, such as load balancers or persistent volumes, may need separate cleanup) ksail cluster updateappliesdesiredCapacity,minSize, andmaxSizechanges to existing managed node groups in-place. Adding a managed node group requires the experimental opt-in above; without it, additions require cluster recreation. Changing an instance type or removing a managed node group still requires recreation. Other fields on existing groups (including AMI family, volumes, labels, taints, subnets, and IAM) are not currently diffed, so update will not detect those changes.- KSail-managed component installation (CNI/CSI/GitOps/security add-ons beyond eksctl’s built-ins) is still in progress — the AWS Load Balancer Controller is available behind the experimental
spec.cluster.eks.experimentalAWSLoadBalancerControlleropt-in; see Support Matrix