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