Kubernetes
EKS, AKS, and GKE control planes plus a shared in-memory Kubernetes data plane that real client-go and kubectl drive end-to-end
aws EKSazr AKSgcp GKE
Emulates managed Kubernetes as two layers: the cloud control plane (EKS/AKS/GKE — the API you call to create clusters and node groups) and a shared data plane — an in-memory Kubernetes API server that kubectl and client-go talk to. Create a cluster with the real cloud SDK, and the kubeconfig it hands back points at the data plane, so kubectl apply round-trips against actual resources.
Reach for it in tests when your code provisions clusters, or when it drives Kubernetes objects directly — deployments, informers, watch streams — so you can exercise controller logic without a real cluster or a kind container. The data plane is a fast, deterministic test double: it stores and serves objects, but deliberately runs no controllers or scheduler.
| Provider | Service | SDK-compat | Driver |
|---|---|---|---|
| AWS | EKS (control plane + data plane) | ✓ Live | aws.EKS |
| Azure | AKS (control plane + data plane) | ✓ Live | azure.AKS |
| GCP | GKE (control plane + data plane) | ✓ Live | gcp.GKE |
Create a cluster and drive its data plane#
The recommended path points the real SDK at the SDK-compat server. Pass a shared *kubernetes.APIServer as K8sAPI and call SetBaseURL so the kubeconfigs the control plane issues point back at this server — then DescribeCluster returns a kubeconfig you can hand straight to client-go:
import (
"github.com/aws/aws-sdk-go-v2/service/eks"
"github.com/stackshy/cloudemu/v2"
"github.com/stackshy/cloudemu/v2/services/kubernetes"
awsserver "github.com/stackshy/cloudemu/v2/server/aws"
)
cloud := cloudemu.NewAWS()
k8s := kubernetes.NewAPIServer()
ts := httptest.NewServer(awsserver.New(awsserver.Drivers{
EKS: cloud.EKS,
K8sAPI: k8s, // shared in-memory Kubernetes data plane
}))
k8s.SetBaseURL(ts.URL) // so issued kubeconfigs point back at this server
client := eks.NewFromConfig(cfg, func(o *eks.Options) {
o.BaseEndpoint = aws.String(ts.URL)
})
client.CreateCluster(ctx, &eks.CreateClusterInput{Name: aws.String("prod")})
// DescribeCluster now returns a kubeconfig whose server URL is the in-memory
// data plane — point client-go at it and `kubectl apply` works.The AKS and GKE control planes are equivalent (armcontainerservice, container/apiv1) and share the same data plane. See the SDK-Compat Server.
Portable Go API#
Drive the control plane through the driver, or the data plane through the kubernetes package, without the HTTP hop. Creating a cluster registers it into the same *kubernetes.APIServer the SDK-compat path uses, so both layers see identical state:
import "github.com/stackshy/cloudemu/v2/services/kubernetes"
k8s := kubernetes.NewAPIServer()
// The control-plane mock registers a cluster into k8s on CreateCluster and
// deregisters it on DeleteCluster; the same in-memory state backs both layers.Because the data plane is a single *kubernetes.APIServer, passing it into awsserver.Drivers{K8sAPI: …}, azureserver.Drivers{K8sAPI: …}, and gcpserver.Drivers{K8sAPI: …} lands every provider's kubeconfig on the identical backend — just as the real Kubernetes REST API is provider-agnostic.
Behavior & fidelity#
- Two layers, one backend. The control plane covers cluster, node-group/node-pool, addon, Fargate-profile, and maintenance-config lifecycle; the data plane is an in-memory Kubernetes API server that the issued kubeconfigs point at.
kubectl apply -f deployment.yamlthenkubectl get podsround-trips, and realclient-goInformer/Reflectormachinery works against it. - Data-plane kinds. Namespace, Pod, Service, ConfigMap, Secret, ServiceAccount, and Deployment (all Create/Get/List/Update/Delete/Patch/Watch), plus Endpoints (read-only, auto-created per Service). API groups served:
core/v1andapps/v1. Each new cluster starts withdefault,kube-system, andkube-publicnamespaces and adefaultServiceAccount in each. - Patch and Watch. Patch is JSON-merge-patch (RFC 7396,
application/merge-patch+json);?watch=truestreamsADDED/MODIFIED/DELETEDas newline-delimited JSON so informers work. Strategic-merge and JSON-Patch (RFC 6902) are not supported. - Intentionally out of scope. To stay a fast, deterministic double, the data plane runs no controllers (a Deployment does not create ReplicaSets/Pods —
spec.replicasmirrors straight tostatus.replicas), no scheduler (Pods stayPending, no Node binding or Pod IPs), and omits RBAC, PersistentVolumes/PVCs, Nodes, and StatefulSet/DaemonSet/Job/CronJob/Ingress. - SDK-compat status — Live. Real
eks,armcontainerservice, andcontainer/apiv1clients drive the control plane. EKS covers cluster CRUD + UpdateConfig/UpdateVersion, managed node groups, Fargate profiles, and addons; AKS covers ManagedClusters (+ RotateClusterCertificates), agent pools, and maintenance configs; GKE covers clusters + config setters (logging, monitoring, master auth, network policy, maintenance, resource labels, IP rotation), node pools (+ SetSize/SetAutoscaling/SetManagement/Rollback), and operations.