Skip to content

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.

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.

  1. AWS account — with permissions to create EKS clusters, IAM roles, and VPCs
  2. AWS credentials — configure via aws configure or environment variables (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION, AWS_DEFAULT_REGION)
  3. Docker — required locally for the ksail CLI
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.

Terminal window
mkdir my-eks-cluster
cd my-eks-cluster
ksail project init \
--name eks-default \
--distribution EKS \
--provider AWS

This generates:

  • ksail.yaml — KSail cluster configuration
  • eks.yaml — eksctl ClusterConfig (source of truth for cluster metadata)
  • k8s/kustomization.yaml — directory for Kubernetes manifests

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/v1alpha5
kind: 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: AmazonLinux2023

Edit 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.

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.json
apiVersion: ksail.io/v1alpha1
kind: Cluster
metadata:
name: eks-default
spec:
cluster:
distribution: EKS
provider: AWS
Terminal window
export AWS_ACCESS_KEY_ID=your-access-key
export AWS_SECRET_ACCESS_KEY=your-secret-key
export AWS_REGION=us-east-1
ksail cluster create

KSail 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.

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

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:

Terminal window
AWS_REGION=eu-north-1 ksail cluster eks-bind --experimental --name my-cluster --provider AWS

The 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.

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: true

Preview 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.

To create a new managed node group on an existing cluster, enable the opt-in in ksail.yaml:

spec:
cluster:
eks:
experimentalManagedNodegroupCreation: true

Add 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:

Terminal window
ksail cluster update --dry-run
ksail cluster update

KSail 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.

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.

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.

  • 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 delete to 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 update applies desiredCapacity, minSize, and maxSize changes 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.experimentalAWSLoadBalancerController opt-in; see Support Matrix