README
¶
playpen-operator
playpen-operator serves the aggregated Kubernetes API for playpen runner pods.
It runs next to a pool of playpen-runner pods and allocates one idle runner to
a client that presents a WireGuard public key.
The operator maintains the runner pod pool itself. It assigns each runner a
unique WireGuard UDP hostPort, and on alloc patches the selected pod with the
client key and returns the endpoint, network, VXLAN, and Redfish details needed
to use the playpen VM.
The returned guest network metadata is intended for a VM whose default gateway is configured on the client side of the tunnel. The runner pod exposes only the VM's L2 path into VXLAN; VM egress is routed and NATed by the client tunnel namespace.
The same runner image is also used for pooled k3s control-plane pods. Those pods
run k3s plus playpen-runner control-plane, which publishes the kubeconfig and
guest API server metadata consumed by control-plane allocations.
The operator does not proxy Redfish or console traffic. Clients reach Redfish and the serial console stream on the runner through the WireGuard tunnel. The alloc response includes the runner Redfish URL, the system URL, and the OEM serial console stream URI for convenience.
API
The operator is registered as v1alpha1.playpen.unbounded-cloud.io and is meant
to be reached through the Kubernetes API server, not by calling the operator
Service directly. It trusts only Kubernetes front-proxy client certificates and
authorizes requests with SubjectAccessReview.
| Endpoint | Method | Purpose |
|---|---|---|
/apis/playpen.unbounded-cloud.io |
GET |
API group discovery |
/apis/playpen.unbounded-cloud.io/v1alpha1 |
GET |
API version discovery |
/apis/playpen.unbounded-cloud.io/v1alpha1/allocs |
POST |
Allocate an idle runner pod |
/apis/playpen.unbounded-cloud.io/v1alpha1/deallocs |
POST |
Deallocate by idempotency key and delete the runner pod |
/healthz |
GET |
Liveness probe |
/readyz |
GET |
Readiness probe |
Alloc and dealloc share one RBAC action. Both handlers authorize create on
allocs.playpen.unbounded-cloud.io, so granting that action grants both API
operations together.
Alloc requests require an idempotency key and a valid WireGuard public key. The
idempotency key can be passed in the Idempotency-Key header or, for kubectl
clients without a header flag, as idempotencyKey in the JSON body:
kubectl create --raw /apis/playpen.unbounded-cloud.io/v1alpha1/allocs \
-f - <<'EOF'
{"idempotencyKey":"smoke-test-1","wireGuardPublicKey":"<client-wireguard-public-key>"}
EOF
The same idempotency key can be retried with the same request body. Reusing the
key with a different WireGuard public key returns 409 Conflict.
Dealloc uses the same idempotency key and is idempotent:
kubectl create --raw /apis/playpen.unbounded-cloud.io/v1alpha1/deallocs \
-f - <<'EOF'
{"idempotencyKey":"smoke-test-1"}
EOF
Kubernetes Behavior
- Runner pods are created in
--runner-namespacefrom--runner-image. --runner-amd64-countand--runner-arm64-countset the desired idle pool size for each architecture.--runner-wireguard-host-port-startand--runner-wireguard-host-port-enddefine the cluster-wide UDP hostPort range used for runner WireGuard endpoints.- Runner pods are selected from
--runner-namespaceusing--runner-label-selectorfor allocation and reconciliation. - An alloc writes pod annotations for the client key, request hash, idempotency key hash, and allocation time, then labels the pod with an allocation ID.
- The alloc response uses the runner node's
ExternalIPand the runner pod's WireGuardhostPortas the externally reachable endpoint. If the runner node has noExternalIP, allocs fail with503 Service Unavailable. --playpen-ttlis the only playpen pod TTL enforcement point. It deletes expired allocated pods. Deallocs also delete the allocated pod. The operator replaces deleted allocated pods during runner pool reconciliation.- On startup, the operator ensures the operator TLS Secret exists, then injects
the serving certificate into the APIService
caBundle.
Run
For local development against the current Kubernetes context:
go run ./cmd/playpen-operator --listen-addr=:8443
For the in-cluster deployment, build the shared playpen image with
make image-playpen-local, render manifests with make playpen-manifests, and
apply the files under deploy/playpen/rendered.
Documentation
¶
There is no documentation for this package.