Skip to content

EKS (Elastic Kubernetes Service)

Protocol: REST-JSON
Endpoint: http://localhost:4566/ (path-routed via JAX-RS)

EKS uses a standard REST API with JSON bodies — not the JSON 1.1 (X-Amz-Target) or Query protocol.

Supported Operations

Operation Description
CreateCluster Create a new EKS cluster
DescribeCluster Describe a cluster by name
ListClusters List all cluster names
DeleteCluster Delete a cluster
TagResource Add tags to a cluster
UntagResource Remove tags from a cluster
ListTagsForResource List tags on a cluster

Modes

Mock mode (mock: true)

Cluster metadata is stored in-process. No Docker containers are started. The cluster transitions directly to ACTIVE on creation. Use this in CI or whenever you only need the EKS API shape, not a real Kubernetes API server.

Real mode (mock: false, default)

Floci starts a k3s (rancher/k3s) container for each cluster. The k3s API server is exposed on a host port from the configured range (6500–6599). Once /readyz responds, the cluster transitions to ACTIVE and the CA certificate is extracted from the kubeconfig.

By default describe-cluster returns a host-reachable endpoint (https://localhost:<hostPort>); the k3s server certificate includes a localhost SAN, so it verifies against the CA in cluster.certificateAuthority.data. Set endpoint-mode: network to return the container DNS name (https://floci-eks-<name>:6443) instead — reachable from other containers on the Docker network (the pre-#1118 behaviour). In network mode the endpoint falls back to the host-reachable form when Floci runs natively, since there is no container DNS name a host client could use.

Connecting with kubectl (native AWS workflow)

The standard AWS flow works end to end:

aws eks update-kubeconfig --name my-cluster
kubectl get nodes

aws eks update-kubeconfig wires aws eks get-token into the kubeconfig as an exec credential. The bearer token it produces is validated by a token-authentication webhook that Floci wires into k3s: the k3s API server POSTs a Kubernetes TokenReview to Floci's /_floci/eks/token-webhook endpoint, and Floci maps the token to the system:masters group (bound to cluster-admin). No aws-iam-authenticator is required.

This webhook is enabled by default (iam-auth-webhook: true). Set it to false to start k3s without it (in which case aws eks get-token tokens are rejected with 401).

Webhook reachability & networking

The k3s API server must be able to reach Floci's webhook URL. When Floci runs natively, k3s containers reach it via host.docker.internal; when Floci runs in a container (floci start), Floci and the k3s containers share a Docker network. The k3s network is taken from FLOCI_SERVICES_EKS_DOCKER_NETWORK if set, otherwise the global FLOCI_SERVICES_DOCKER_NETWORK, otherwise the network Floci is itself attached to (auto-detected) — so no EKS-specific network configuration is required in the standard compose setup.

The webhook kubeconfig is copied into the k3s container via the Docker API (not bind-mounted), so the token-webhook works the same in native and Docker-in-Docker modes with no host-path / host-persistent-path configuration.

Docker socket required

Real mode starts privileged Docker containers. Mount the Docker socket and set the Docker network so containers can reach each other.

services:
  floci:
    image: floci/floci:latest
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    ports:
      - "4566:4566"
    environment:
      FLOCI_SERVICES_EKS_DOCKER_NETWORK: my_project_default

No port mapping needed for k3s ports

k3s containers bind their API server port (6500–6599) directly on the host via Docker — no ports: entry is required in docker-compose.yml. See Ports Reference for the full explanation.

Configuration

Variable Default Description
FLOCI_SERVICES_EKS_ENABLED true Enable the EKS service
FLOCI_SERVICES_EKS_MOCK false Metadata-only mode (no Docker)
FLOCI_SERVICES_EKS_DEFAULT_IMAGE rancher/k3s:latest k3s Docker image
FLOCI_SERVICES_EKS_API_SERVER_BASE_PORT 6500 First port in the k3s API server range
FLOCI_SERVICES_EKS_API_SERVER_MAX_PORT 6599 Last port in the k3s API server range
FLOCI_SERVICES_EKS_DATA_PATH ./data/eks Host bind-mount root for cluster data
FLOCI_SERVICES_EKS_DOCKER_NETWORK (unset) Docker network for k3s containers (falls back to the global FLOCI_SERVICES_DOCKER_NETWORK, then Floci's own network)
FLOCI_SERVICES_EKS_KEEP_RUNNING_ON_SHUTDOWN false Leave k3s containers running after Floci stops
FLOCI_SERVICES_EKS_ENDPOINT_MODE host describe-cluster endpoint: host (localhost:<hostPort>) or network (container DNS)
FLOCI_SERVICES_EKS_IAM_AUTH_WEBHOOK true Wire a token-auth webhook into k3s so aws eks get-token works

Mock mode (CI / tests)

Use FLOCI_SERVICES_EKS_MOCK=true when you only need the API shape:

# docker-compose.yml — CI / test environment
services:
  floci:
    image: floci/floci:latest
    environment:
      FLOCI_SERVICES_EKS_MOCK: "true"

ARN Format

arn:aws:eks:<region>:<accountId>:cluster/<clusterName>

Examples

export AWS_ENDPOINT_URL=http://localhost:4566
export AWS_DEFAULT_REGION=us-east-1
export AWS_ACCESS_KEY_ID=test
export AWS_SECRET_ACCESS_KEY=test

# Create a cluster
aws eks create-cluster \
  --name my-cluster \
  --role-arn arn:aws:iam::000000000000:role/eks-role \
  --resources-vpc-config subnetIds=[],securityGroupIds=[] \
  --kubernetes-version 1.29

# Describe the cluster
aws eks describe-cluster --name my-cluster

# List clusters
aws eks list-clusters

# Tag a cluster
aws eks tag-resource \
  --resource-arn arn:aws:eks:us-east-1:000000000000:cluster/my-cluster \
  --tags env=dev,team=platform

# Delete a cluster
aws eks delete-cluster --name my-cluster

Java SDK Example

EksClient eks = EksClient.builder()
    .endpointOverride(URI.create("http://localhost:4566"))
    .region(Region.US_EAST_1)
    .credentialsProvider(StaticCredentialsProvider.create(
        AwsBasicCredentials.create("test", "test")))
    .build();

// Create cluster
CreateClusterResponse created = eks.createCluster(r -> r
    .name("my-cluster")
    .roleArn("arn:aws:iam::000000000000:role/eks-role")
    .resourcesVpcConfig(v -> v
        .subnetIds(List.of())
        .securityGroupIds(List.of()))
    .version("1.29")
    .tags(Map.of("env", "dev")));

// Describe cluster
DescribeClusterResponse described = eks.describeCluster(r -> r
    .name("my-cluster"));

System.out.println(described.cluster().status()); // ACTIVE

// List clusters
List<String> names = eks.listClusters(r -> {}).clusters();

// Tag resource
eks.tagResource(r -> r
    .resourceArn(created.cluster().arn())
    .tags(Map.of("team", "platform")));

// Delete cluster
eks.deleteCluster(r -> r.name("my-cluster"));

Not Implemented (Phase 1)

The following EKS features are not yet supported:

  • Node groups (CreateNodegroup, DescribeNodegroup, ListNodegroups, DeleteNodegroup)
  • Fargate profiles
  • UpdateClusterConfig / UpdateClusterVersion
  • Add-ons (CreateAddon, DescribeAddon, ListAddons)
  • Identity provider configs
  • Access entries and policies
  • Encryption config